Nematode Earth ← back to the visualization

How this was made

The piece you have just watched removes Earth's matter over forty seconds and leaves a veil behind. That veil is not a texture painted on a sphere. It is one number per cell — the modelled areal abundance of soil nematodes — converted into an optical depth and integrated along every view ray, every frame.

The veil shows a modelled population, not a census of individual animals. A separate layer marks 6,825 measured soil samples; terrain and built-up surface come from other geospatial products. The soil model has no marine coverage and leaves polar gaps. This page is the audit trail: what the numbers are, where they came from, what the rendering invents on purpose, and the six or seven places where the thing on screen was confidently, silently wrong.

Credits & rights

Visualization and engineering: Ethan Soch. Nematode Earth is an independent creative and technical project: the interactive experience, rendering, data conversion pipeline, and project-specific calculations were developed here, with coding assistance from Claude Code and Codex. The underlying research, field measurements, and source datasets belong to the researchers and providers below. These credits do not imply their affiliation with or endorsement of this project.

What the image adds: veil thickness, rim brightness, color, and the fourfold city-brightening control are authored visual choices. Cobb supplied no numerical multiplier. The assumed optical area and exploratory twenty-city regression belong to this project, not to results published by the cited researchers. Missing ocean or polar data does not mean no nematodes live there. This is an interpretation of terrestrial data, not a complete test of Cobb’s world.

Dataset rights: both ETH records carry In Copyright — Non-Commercial Use Permitted (InC-NC), a rights statement rather than a Creative Commons licence. The derived soil atlases retain this source attribution. ETOPO and the individual Figshare sample dataset are CC0; GHSL specifies the European Commission reuse notice. The linked source records give the terms for each dataset.

Tools: three.js 0.185.1 (WebGPU and TSL, MIT), TypeScript, Vite, and Vitest; the offline Python pipeline uses NumPy, tifffile, imagecodecs, and Requests. Tool licences apply to their respective packages, not the datasets. Implementation details · full references.

three.js copyright and MIT licence
The MIT License

Copyright © 2010-2026 three.js authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
How to read this page

Every figure below carries its provenance in a dim note under the claim it supports, and those notes come in three kinds so you can tell at a glance what a number rests on. Published source means an external citation you can open — a DOI, a dataset landing page, a specification. Measured by this project (set on a dashed rule) means we computed it here, not that we collected field samples, and no publication states it; those notes say what was measured, over what, and when. Published source · measured here is the mixed case, and it is the commonest one: somebody else's dataset, our own number derived from it.

Repository paths appear throughout as secondary detail — the file that holds the code, the constant or the sidecar — for anyone who has the source. They are never offered as the citation for a claim that has a real external one. Where a figure could not be sourced at all, the note says so in those words rather than implying otherwise. Full citations are collected in Section VI.

One convention carries over from the piece: warm italic marks Cobb's 1914 prediction and is never used for something we measured. It appears on this page under exactly the same rule.

Section I

The claim, and the test

In 1914 Nathan Cobb wrote the sentence the piece is built on:

if all the matter in the universe except the nematodes were swept away, our world would still be dimly recognizable

Nathan A. Cobb, “Nematodes and their relationships”, Yearbook of the United States Department of Agriculture 1914, p. 472

Cobb, N. A. “Nematodes and their relationships.” In Yearbook of the United States Department of Agriculture 1914. Washington: Government Printing Office, 1915, pp. 457–490; the quoted sentence is on p. 472 — archive.org/details/yoa1914, p. 472, the USDA National Agricultural Library’s digitisation, public domain as a work of the US Government. Carried in this repository at app/src/sweep/Timeline.ts (COBB_LINE) and app/src/hud/copy.ts (quotationAttribution).

Cobb did not stop at the general image. He itemised what would survive: “its mountains, hills, vales, rivers, lakes, and oceans represented by a film of nematodes”; trees standing “in ghostly rows representing our streets and highways”; and — the clause that matters here — the location of towns “decipherable, since for every massing of human beings there would be a corresponding massing of certain nematodes.” The design spec tabulates each fragment as a separate, separately checkable proposition, which is what makes the passage unusual. “Dimly recognizable” sounds like a flourish, but it has two quantitative halves — dim, and recognizable — and a modern global nematode map can be asked whether both hold.

Quoted fragments: Cobb 1914, p. 472 (archive.org), read from the full text of the volume, so each fragment above is verbatim rather than paraphrased — note that Cobb puts the mountains, hills, vales, rivers, lakes and oceans in one film, not two. Breaking the passage into separately checkable propositions is this project’s own reading, tabulated in docs/superpowers/specs/2026-08-15-nematode-earth-design.md §1; Cobb wrote continuous prose and made no such table.

Illustrative single-column rendering calculation τ = 0.04  →  3.9% expected coverage In the rendering model, expected silhouette coverage is 1 − exp(−τ). This example is not a measured global mean or a photograph of nematodes. It assumes randomly placed, opaque silhouettes and the project’s chosen average projected area per animal. Color, exposure and the visible shell thickness are additional display choices. Example evaluated from arealCoverage in app/src/math/optical.ts. The former 4.06% headline did not have a reproducible current-atlas mean behind it, and the former 27× biome contrast came from a synthetic design illustration. Neither is used here as a measured ecological result. Spatially averaging 1 − exp(−τ) is also not the same as applying that formula to a spatially averaged τ.

The visualization uses geographic differences in modelled abundance to make the veil legible, with increased exposure so it can be explored on a screen. This illustrates part of Cobb’s thought experiment; it does not establish how his complete world of soil, marine and parasitic nematodes would actually look.

The clause we could actually test

The towns clause is a different kind of claim, because two rasters exist that can be laid over each other: modelled nematode density from van den Hoogen et al. 2019, and the European Commission's GHSL built-up surface layer for epoch 2020, both on a ~30 arc-second grid. If cities really are a “corresponding massing”, built-up fraction can be compared with predicted soil abundance. This is an exploratory comparison of two maps, not a direct test of all nematodes associated with settlements.

The original spec proposed to render the answer as an inversion — cities as voids rather than massings, via a multiplier m(u) = 1 − 1.70u + 0.75u² — and flagged its own problem in the same paragraph: the urban suppression exponent “rests on a source that could not be located,” and must be calibrated against real cities or dropped. So it was calibrated.

This project’s own design record: docs/superpowers/specs/2026-08-15-nematode-earth-design.md §6.3, written 2026-08-15. The admission quoted is the spec’s own — no external source for the 1.70 urban-suppression coefficient could be found when it was written, and none has been found since.

The first pass, in August 2026, regressed density against built-up fraction globally on the coarse 512 × 256 extraction — about 78 km per pixel — binned into 10° latitude bands to reduce broad geographic differences; this does not eliminate climatic or spatial confounding. At 78 km an entire metropolitan area and its countryside fall inside one pixel, so a second, sharper pass followed: twenty named cities spanning climate, continent and development level — Amsterdam, Paris, London, Stockholm, Moscow, Phoenix, Atlanta, Toronto, Mexico City, Tokyo, Cairo, Lagos, São Paulo, Delhi, Mumbai, Beijing, Istanbul, Nairobi, Buenos Aires, Jakarta — each sampled in a 1.0° × 1.0° window at the density raster's native resolution.

The method and both passes are this project’s own, run 2026-08-16: pipeline/build/urban_calibration.py (module docstring, main()) · pipeline/build/city_windows.py (CITIES, WINDOW_DEG = 1.0). Its two inputs are published: the modelled density raster of van den Hoogen et al. 2019, Nature 572, 194–198, distributed at ETH Research Collection doi:10.3929/ethz-b-000354035, and the JRC’s GHS-BUILT-S R2023A built-up surface grid.

Each city is compared only to itself: the baseline is that city's own low-built-up pixels inside the same window, so the fit measures the walk from a city's rural surroundings into its core, never city A against city B. Ocean pixels are dropped entirely, port or not. The fitted model is m(u) = 1 + a·u + b·u² with the intercept pinned at 1 as an additional modelling constraint. Normalising by the mean density of pixels with u < 0.02 makes that subset’s average ratio one; it does not establish the value exactly at u = 0. The nominal confidence interval comes from 2,000 pixel-bootstrap resamples at a fixed seed.

This project’s own method and code, run 2026-08-16: pipeline/build/city_calibration.py (module docstring; N_BOOTSTRAP = 2000, RNG_SEED = 42) · pipeline/build/urban_calibration.py (fit_quadratic_through_one). The self-comparison design, the ocean exclusion and the pinned intercept are choices made here, not a protocol taken from any paper.

The result a = −0.0085 Nominal 95% independent-pixel bootstrap interval for a: −0.035 to +0.019 · R² = −0.0003 · 243,294 mapped pixels · 20 cities Measured by this project, 2026-08-16, by regressing the van den Hoogen 2019 density raster against the GHSL built-up grid over 243,294 native-resolution pixels in twenty 1° city windows. No published study reports this regression; these figures exist only here. Recorded at docs/superpowers/results/2026-08-16-urban-claim-ruling.md, carried on screen by app/src/field/cobb.ts (MEASUREMENT_CAPTION) and app/src/hud/copy.ts (findingStatistics) — a test asserts these figures are on screen so a copy edit cannot quietly drop the unflattering ones (app/test/hudCopy.test.ts).

Here a is the linear coefficient of a quadratic, not the total contrast between open and fully built-up ground: that contrast would be a + b. An interval for a containing zero does not test the whole relationship. The bootstrap independently resamples pixels; it does not account for spatial or city dependence, uncertainty in the rural baselines, or uncertainty in the source model. These pixels are predictions, not 243,294 independent field observations.

The negative R² is not a typo. Because the intercept is fixed at 1 rather than fitted, the model is permitted to do worse than simply predicting the average of the data, and it does — by 0.03%. In these windows, this fitted relationship does not improve on the mean baseline. That is a limitation of this analysis, not a universal ecological claim.

What shipped instead

m(u) = 1 − 1.70u + 0.75u² was never shipped. In the code, dataMultiplier returns the constant 1 for every input, and a test pins it there at u = 0, 0.1, 0.5, 0.9 and 1 — omitting an unsupported extra multiplier. Only Cobb's end of the slider does anything: cobbMultiplier(u) = 1 + 3u, brightening fully built-up ground up to fourfold, labelled in warm italic as a 1914 prediction and never as a measurement. The fourfold magnitude was chosen by this project; Cobb supplied no quantitative multiplier. The two slider ends are labelled “Soil model” and “Cobb illustration”: a published model on one side, an authored interpretation on the other, rather than an off switch and a measurement.

This project’s own code and its own design decision; there is nothing external to cite. app/src/field/cobb.ts (dataMultiplier, cobbMultiplier) · app/test/cobb.test.ts · app/src/hud/copy.ts (cobbAxisMeasured, cobbAxisPredicted), enforced by app/test/hudCopy.test.ts.

The soil-model end leaves the source predictions unchanged. The Cobb illustration adds an authored fourfold local multiplier, which has a small global footprint: this project’s GHSL integral is 4.646 × 10¹¹ m² of built-up surface, roughly 0.31% of the 1.478 × 10¹⁴ m² classified as land by the project’s terrain mask. Neither the footprint nor the multiplier is a measurement of urban nematode abundance.

The built-up grid is GHS-BUILT-S R2023A (doi:10.2905/9F06F36F-4B11-47EC-ABB0-4F8B7B1D72EA); the land mask comes from ETOPO 2022 (doi:10.25921/fd45-gt74); the global nematode total is van den Hoogen et al. 2019, 4.40 ± 0.64 × 10²⁰ individuals. Every arithmetic step is this project’s own, computed 2026-08-16 from those rasters: the 4.646 × 10¹¹ m² built-up total (app/public/data/urban_plain_1024/cube_meta.json, source_total_built_up_area_m2 = 464,568,186,170.9 — our recomputation from the raster, not a JRC-published figure); and the land area derived from elevation_plain_2048/cube_meta.json, total_area_m2 times global_land_fraction = 0.28977. That mask includes grounded ice; it is not an ice-free land fraction. Its limitations are described in Section II.

Why we did not add an urban multiplier

The regression compares predictions, not a new urban field survey. The selected 2019 random-forest model used all 73 covariates. Its predictors include environmental, remote-sensing and human-related information, but they do not identify a causal urbanization effect. The earlier claim that population density had been excluded from the selected model was incorrect.

van den Hoogen et al. 2019, Methods; author-hosted full text at UC Davis. The paper distinguishes the selected 73-covariate model from its reduced-covariate analysis. A variable-importance ranking alone cannot establish ecological causation.

Different summaries answer different questions. Our analysis of the updated deposited database, aggregated into 1,933 map pixels, found a +0.091 correlation between log population density and log nematode abundance. The city-window correlations also differed in sign: Moscow +0.61, Amsterdam −0.27. These are descriptive associations. They neither isolate pavement effects nor demonstrate why cities differ. The 1,933 updated pixels are not the original model’s 1,876 non-Antarctic modelling pixels.

Updated database: van den Hoogen et al. 2020. Correlations computed here in August 2026 and recorded in docs/superpowers/results/2026-08-16-urban-claim-ruling.md. That historical note’s stronger ecological interpretations are not established by these calculations.

The published urban result also needs its uncertainty. Li et al. reported an estimated 27% higher total abundance in the urban category than in primary habitat, but urban total abundance did not differ significantly from the other land-use categories. The analysis concerns counts per 100 g of dry soil classified by regional land use, not counts underneath pavement. It reuses the underlying sample database, so it is not independent replication of this project’s map comparison.

Li et al. 2022, Results §3.1 and Figure S4. The point estimate and the non-significant urban comparison must be read together.

Accordingly, m_data(u) = 1 means that this visualization adds no extra urban correction to the published soil model. It is not a measured law that cities have no effect on nematodes. A defensible correction would need an appropriate observational design, spatial validation and uncertainty accounting.

What this comparison does not test

Cobb referred to “certain nematodes”, not simply a uniform increase in every soil animal. Species, feeding groups and host-associated parasites need not respond alike. Our illustrative calculation of 100 worms per person against a global-average soil density does not test local parasite burdens, species composition or the full historical claim, and cannot refute Cobb’s mechanism.

Cobb, USDA Yearbook 1914, p. 472. The 100-worm burden was this project’s hypothetical example, not a published mean or a result from the soil rasters.

Composition does show urban differences in some research. Across 12 Chinese cities and a comparison with global data, Gong et al. reported lower proportions of omnivores and predators, with higher proportions of bacterivores and fungivores. A shift in proportions does not by itself show how absolute abundance changed. The current global abundance view cannot reproduce that study’s city-level composition findings.

Gong et al. 2024, Soil Biology & Biochemistry 190, 109297, abstract. The reported reductions are 45–60% in the proportion of omnivores and 40–50% in predators, not the previously stated 45–80% loss in counts.

The sources reviewed for this project do not establish nematode abundance beneath pavement. Hu et al. measured soil properties and bacteria beneath impervious surfaces in Beijing; their organic-carbon and moisture comparisons use different vegetated reference settings. Those results cannot supply a nematode-suppression multiplier, and an unsuccessful literature search is not evidence that no such measurement exists anywhere.

Hu et al. 2018, Frontiers in Microbiology 9:226, Table 1. This study is not a nematode census.

Section II

The data

Four data families reach the screen: modelled soil abundance, a compiled terrain model, satellite-derived built-up surface and a collection of measured soil samples. The models also draw on observations, but their output pixels are not individual field measurements. Keeping that distinction visible is what this section is for.

The abundance model: a validated release and the August record

Viewer release, 2026-09-26: the validated soil extraction upgrade is deployed on Cloudflare Pages, using /data/soil_plain_512_v2 with 512-texel faces. Complete local reads of total abundance and bootstrap CV passed the numerical data checks; browser checks covered calibrated probes, coverage, orientation, the opening, the full sweep and the uncertainty toggle. Independent review is complete with no blocking findings, including file hashes, regional/coastal/no-data probes and composition-gap checks. The hosted viewer loaded the soil and elevation atlases, completed the sweep, and rendered the nematode veil. This is not a new research population estimate.

The nematode veil is a random-forest prediction published with van den Hoogen et al., Soil nematode abundance and functional group composition at a global scale, Nature 572, 194–198 (2019). The two ETH Research Collection deposits contain sixteen GeoTIFFs totalling about 87.6 GB. The abundance layer, TotalNumber_perSquareMeter.tif, is 43,201 × 21,121 pixels of uncompressed float64 on a 30 arc-second EPSG:4326 grid — about 0.93 km per pixel at the equator, roughly 7.3 GB on its own. Its tiepoint is (−180.0, 88.0): the grid stops at ±88° latitude, not ±90°, so the poles are a hole in the source, not something the bake invented.

The rasters are van den Hoogen, J. & Routh, D. (2019), Supplementary Data for Nematode Abundance at Global Scale, ETH Zurich Research Collection, doi:10.3929/ethz-b-000354035, the prediction surface behind van den Hoogen et al. 2019. Everything numeric above is this project’s own reading of the file, 2026-08-16: the 43,201 × 21,121 float64 geometry, the (−180.0, 88.0) tiepoint and the ±88° limit were parsed out of the TIFF header by pipeline/fetch/tiff_header.py and recorded in pipeline/out/total_persqm_meta_512x256.json; the sixteen-GeoTIFF, 87.6 GB inventory is our own tally across that deposit and the additional functional-group deposit. These are file properties, not ecological accuracy estimates. The direct bitstream is a ~7.3 GB download and is deliberately not linked.

The September 22 candidate reads every native row from the complete downloaded TIFFs: 21,121 of 21,121 rows for total abundance per m² and 21,120 of 21,120 for bootstrap CV. Each file is georeferenced independently and conservatively reduced by spherical overlap area to a 2,048 × 1,024 grid spanning ±88° latitude. These grids feed six 512 × 512 cube faces, with a nominal mean pitch of about 19.55 km per texel. Reading the full model rasters adds no field observations and does not establish ecological accuracy at that spacing.

The reduced density grid integrates to 4.614562821134919e20 under this project’s spherical area convention and domain. Exact conservative native-to-grid reduction preserves the native integral to about 1.18 × 10⁻¹⁴ relative error. After cube resampling and renderer-equivalent log/float16 conversion, the integral differs from that source grid by 0.056%. These are distinct numerical checks: the latter is a CPU texel-centre calculation, not an integral of a filtered, raymarched GPU image. Neither is a new population estimate.

Candidate measurements, 2026-09-22: app/public/data/soil_plain_512_v2/cube_meta.json (source.density.extraction, source.cv.extraction, geography, validation). Both inputs report complete row coverage. The public sidecar records accepted-local-viewer-not-deployed and the completed checks in local_acceptance. The 19.55 km figure is nominal cube geometry, not the source model’s resolving power.

The August extraction: a historical 2.4% sample

The August 16 run did not download the full raster. The file is uncompressed with RowsPerStrip = 1, which makes every scanline directly addressable by byte offset, so that extractor read selected rows over HTTP range requests. The figures below describe that historical run and its legacy atlas, not the full local candidate.

Historical extraction, 2026-08-16 512 of 21,121 rows  ·  2.42% 176,951,296 bytes of roughly 7.3 GB, in 277 requests with 21 retries, over 214 seconds, against a server delivering 70–120 KB/s per connection. Column coverage was total, and rows were contiguous box-averaged blocks — never point-sampled every Nth row, which would alias a high-frequency prediction surface badly. It was a sample, not a full box average. Measured by this project on its own extraction run, 2026-08-16 — the request count, the retries, the elapsed time and the observed throughput are properties of that one run against that one server, not of any published dataset: pipeline/out/total_persqm_meta_512x256.json · pipeline/fetch/eth_raster.py · pipeline/fetch/range_client.py. The mechanism itself is ordinary HTTP (RFC 9110 §14, Range Requests).

That extraction landed on a 512 × 256 equirectangular grid: about 78 km per cell. The legacy density cube was baked from it into 128-texel faces, nominally 78.2 km per texel, with a real ground footprint ranging 44.0 km at the face corners to 99.5 km at the centres (72.0 km RMS). Against a 0.93 km native pixel that was roughly 84× linear coarsening, making density the coarsest atlas in the August viewer by a factor of sixteen: elevation and built-up both reached 4.89 km per texel.

Measured by this project from the shipped atlases, 2026-08-17 — pure geometry computed by the bake and written into its own sidecars: app/public/data/cube_plain_128/cube_meta.json (texel_ground_stats) · app/public/data/elevation_plain_2048/cube_meta.json and urban_plain_2048/cube_meta.json (km_per_texel = 4.88649579980971). No external source states these numbers; they describe this project’s own encoding.

Rebaking that legacy cube finer was measured and ruled out at the time: the sharpness instrument saturated at 5.6% because no finer detail remained in its 512 × 256 input. That was a limit of the August extraction, not of the native TIFF. The new candidate instead starts from the full local reads and a finer conservative grid; the old result does not establish a resolution ceiling for it.

Measured by this project, 2026-08-16, by running the same sharpness instrument across all four atlases: app/src/field/loadCube.ts (comment at the texel-warp definition) · app/test/cubeFilter.test.ts, with the fuller record at docs/superpowers/results/2026-08-16-sharpness-findings.md. The 5.6% saturation is a property of the August bake, not a published quantity.

The August validation gate passed on real bytes: integrating that extracted grid over exact spherical lat-band areas gave 4.617 × 10²⁰ nematodes against the paper's published 4.40 ± 0.64 × 10²⁰ — a ratio of 1.049 against the point estimate, within the paper's own ±14.6% uncertainty. The legacy baked cube re-integrated to 4.628 × 10²⁰, within 0.25% of its own source. The full local extraction now gives approximately 4.615 × 10²⁰, still about 4.9% above the paper’s point estimate. Reading every row has therefore not resolved the discrepancy; sparse row sampling does not explain it away. The cause remains unestablished, and numerical conservation does not reproduce or replace the paper’s population estimate or its uncertainty. No rescaling to the paper’s total was applied.

The denominator is published: van den Hoogen et al. 2019 gives 4.40 ± 0.64 × 10²⁰ individuals in its abstract and Table 1 — a ±14.6% uncertainty the ratios below do not carry. The two August integrals and their ratios are this project’s own computations, 2026-08-16: pipeline/out/total_persqm_meta_512x256.json (ratio_to_published = 1.0492) · app/public/data/cube_plain_128/cube_meta.json (ratio_baked_to_source = 1.00247) · docs/superpowers/results/2026-08-16-session-2-data-pipeline.md. The 4.9% overshoot persists in the September candidate metadata cited above; it remains an unexplained comparison made by this project, not a new research finding.

In the August atlas, about 68.5% of texels — 67,384 of 98,304 — decoded to a density floor rather than a supported model prediction. Every floored texel had coverage exactly 0.0; thirty-two texels fell in the polar gap beyond ±88° and were marked explicit no-data. These are historical encoding checks. Missing model support is neither a direct observation of zero nematodes nor an ocean classification.

Audited by this project’s own bake and written into the atlas sidecar, 2026-08-17: app/public/data/cube_plain_128/cube_meta.json (floored_texel_audit, polar_gap). The ±88° coverage limit itself is a property of the source raster (ETH doi:10.3929/ethz-b-000354035), not of the bake.

In the August cube, G stored a structure fraction — omnivores plus predators over the sum of the five functional-group rasters. That ecological denominator remains a deliberate choice. The five group grids were modelled independently of the published TotalNumber grid: the historical extraction measured a global area-weighted summation ratio of 1.0875, with per-pixel ratios running 0.538 to 2.330. Normalising by TotalNumber would have silently encoded that model disagreement as ecology. In that bake, the global structure fraction was 0.1361 against 0.134 computed from Table 1's per-group counts — 1.6% relative error. (0.134 is not a number the paper prints; it is omnivores plus predators over the total, taken from that table.)

The source for B is native pixel bootstrap uncertainty, the coefficient of variation of a 100-iteration bootstrap — explicitly not the TotalNumber_Ensemble_CoefVar.tif raster, which shares the same convenient grid but measures seed-to-seed jitter of a single model run and would read as “confidence” while measuring nothing of the kind. The August cube audit reported 0.064 to 0.545, mean 0.189, over 32,918 cells labelled land in that audit; regional checks found higher values over the Gobi and Sahara than over Western Europe and the US cornbelt. These historical model diagnostics do not locate direct observations or establish the uncertainty of an aggregated population count.

The five functional-group rasters are van den Hoogen, J. & Routh, D. (2019), Additional Supplementary Data for Nematode Abundance at Global Scale, doi:10.3929/ethz-b-000354394; TotalNumber and the bootstrap coefficient-of-variation grid are in doi:10.3929/ethz-b-000354035. The 0.134 comparison is not a printed value: it is (omnivores 0.39 + predators 0.20) ÷ total 4.40 from Table 1 of van den Hoogen et al. 2019, computed here. The 1.0875 summation ratio, the 0.538–2.330 per-pixel spread, the baked 0.1361 and every bootstrap statistic (32,918 land cells, 0.064–0.545, mean 0.189) are this project’s own measurements, 2026-08-17: app/public/data/cube_plain_128/cube_meta.json (channels.G, channels.B, validation.summation_trap, validation.structure_fraction, validation.bootstrap_cv) · regional means in app/test/terrain.test.ts.

The candidate’s channel contract

R is the log of an all-cell area-mean density; A is valid-model support. The mean already accounts for the supported share of each cell. A is a zero-only gate: if A is zero, density is unavailable; if A is nonzero, do not multiply the decoded density by A again. A cell with density 50 and support 0.5 stays 50, not 25. Neither A nor its complement is an independent land/ocean mask.

G retains the older, sparse 512 × 256 feeding-group inputs. A larger output cube does not upgrade those five source grids. The candidate stores G = structure fraction × groups_support and carries separate R16Float group-support masks. A consumer must filter G and its own mask at identical directions and LOD, then divide by that mask only where it is positive — never by A. Gaps remain unavailable, including 3,631 candidate texels with density but no group support. They do not discard valid density or CV. The current viewer has no G consumer.

B is the support-normalized, area-weighted mean of native pixel bootstrap CVs. It is not the CV of the aggregated count and must not be interpreted as a confidence interval for a coarse cell or the global integral. The full CV extraction has support everywhere the candidate density does at this resolution. The overlay’s coverage fade is authored display opacity, not numerical confidence and not a correction for CV supposedly diluted by ocean.

Candidate encoding and support checks, 2026-09-22: app/public/data/soil_plain_512_v2/cube_meta.json (channels, group_support, validation.support). The source research and ETH DOI citations above apply to both the historical extraction and this candidate; these channel and display choices are this project’s own.

Marine measurements: research only

A separate research pipeline now holds 934 normalized records, not sampling sites. Two separate regional experiments use 96 complete 0–5 cm cores across seven held-out groups: 31 CCZ cores in four areas and 65 HAUSGARTEN cores at three stations. For a depth-only model versus a training-only intercept baseline, held-out natural-log1p RMSE is 1.646 versus 1.221 in the CCZ (worse), and 0.394 versus 1.031 at HAUSGARTEN (promising within limited support). These are this project’s calculations, not results published by the source authors or a pooled seven-group global model. No public marine layer, global predictions or uncertainty intervals are produced.

The three-station HAUSGARTEN result does not establish global transfer; taxonomic completeness, missing profiles and depth extrapolation remain limitations. No absent population measurement is replaced with zero. Each model experiment and prediction retains its target definition, population-accounting status, study/source and flags; HAUSGARTEN’s taxon sum is not relabelled as a whole-population census. Full audit, fold predictions, source checksums and offline rerun commands: docs/superpowers/results/2026-09-19-marine-experiment.md and pipeline/out/marine/. These research outputs are separate from the viewer’s terrestrial field.

Elevation, and a land mask that took three tries

Relief and bathymetry come from ETOPO 2022 at 60 arc-second resolution, 21,600 × 10,800 (about 1.85 km/px at the equator), CC0 from NOAA NCEI. Elevation is stored raw and signed, −10,752 m to 8,157 m in this averaged grid, with no log encoding and no clamping of negatives — the seafloor is content, not a defect. The declared −99999 nodata sentinel turns out never to appear: an exhaustive scan of all 233,280,000 source pixels found zero sentinels, zero NaNs, zero infinities, in both the bed and surface rasters. Six tiers were baked, 64 to 2,048 faces; the viewer loads 256 (39.1 km/texel) for first paint, then 1,024 (9.77 km), then 2,048 (4.89 km). The baked land, ocean and absolute volume integrals all sit within 0.11% of the source grid.

NOAA National Centers for Environmental Information (2022), ETOPO 2022 Global Relief Model, doi:10.25921/fd45-gt74 — product page ncei.noaa.gov/products/etopo-global-relief-model. One caveat the citation should carry rather than hide: that DOI is registered against the 15 arc-second model, and NCEI distributes the 15″, 30″ and 60″ grids under it with no separate DOI per resolution — so the 60″ bed grid used here comes from the same 2022 release but is not itself separately DOI’d. CC0, stated in NOAA’s own metadata record. The exhaustive nodata scan, the min/max, the six baked tiers and the 0.11% integral agreement are this project’s own, measured 2026-08-17: app/public/data/elevation_plain_2048/cube_meta.json (source, nodata_audit, validation) · pipeline/fetch/etopo.py · tier order at app/src/viewer.ts.

One thing was thrown away on purpose. The shipped raster is bed elevation — bedrock, with the ice sheets removed. The companion surface raster was downloaded and read, but never baked into any channel. It exists solely to answer one question, and answering it correctly took three attempts.

The question is: which pixels are land? Bed elevation's own sign is not an answer, because ice sheets routinely sit on bedrock below sea level. Probing the baked atlas directly: Vostok reads −245 m, the Byrd Subglacial Basin −913 m. Under a naive bed ≥ 0 rule, West Antarctica opens up as a hole in the continent.

Attempt one replaced it with an ice-thickness test — is surface − bed greater than a metre? — which shipped, and was wrong, because floating ice also has real thickness. It classified open ocean under floating sea ice as land. In the render this appeared as a hard-edged rotated rectangle around Greenland: the polar-stereographic extent of the BedMachine Greenland source mosaic, reprojected onto a sphere and visible as a rectangle because a rectangle is what it always was.

Attempt two introduced a simplified flotation test — but kept a surface ≥ 0 OR clause alongside it, on the reasoning that ordinary dry land should trivially pass. That clause was wrong for a genuinely counterintuitive reason: a floating ice shelf has positive freeboard by construction. Ice is less dense than water, so part of a floating column stands above the waterline. Positive surface elevation therefore does not establish grounding. Measured on this grid, roughly 1,000,000 of 233,280,000 source cells — about 0.43% of the cells, concentrated between 60°S and 85°S across the Ross, Ronne-Filchner, Amery and Larsen C shelves — were classified as land only because of that clause, sitting over bed depths of −100 to −3,000 m. These latitude–longitude cells have unequal areas: their count is not a measured percentage of Earth’s surface. Surface minus bed is also not the true ice thickness over a floating shelf, where it includes the water cavity.

Attempt three is the mask rule now implemented: bed + 0.917 × (surface − bed) > 0, that is, when the draft it would sink to reaches past the seafloor under the rule’s assumed geometry. The coefficient 0.917 corresponds to 917/1000: an ice-to-fresh-water approximation, not a universal ice-to-seawater density ratio. This mask has not been validated against a complete observed grounding-line dataset and should not be used as one. For ordinary ice-free ground the thickness term vanishes and the rule reduces exactly to bed > 0, so above-sea-level dry land is untouched. Ten geographic probes now come out right — Vostok, Byrd, Dome A and the Greenland summit all read land at G = 1.0; the mid-Pacific, mid-Atlantic, Baffin Bay, the Arctic north of Greenland and the Ross Ice Shelf all read ocean at G = 0.0.

For physical flotation modelling, compare the PISM marine ice-sheet documentation and its separate ice and seawater density parameters. They do not establish this project’s 0.917 coefficient as a seawater constant. The bed and surface rasters are ETOPO 2022, doi:10.25921/fd45-gt74. The rule as implemented and all ten probe readings (Vostok −245 m, Byrd −913 m and the rest) are this project’s own readings of its own baked atlas, 2026-08-17: pipeline/build/bake_elevation_cube.py (RHO_ICE_OVER_RHO_WATER, is_grounded, compute_land_mask, and the module docstring’s probe table) · app/public/data/elevation_plain_2048/cube_meta.json (validation.land_mask.probes).

The two rules disagree measurably. Counting only bedrock above sea level gives 27.63% of Earth's surface as land; the flotation mask gives 28.98%. The difference is roughly 6.9 million square kilometres in the two classifications. That subtraction is not a measurement of grounded-ice area: the masks have different definitions, different code paths and the limitations just described.

Measured by this project, 2026-08-17, and already labelled in the sentence above: the two fractions come from app/public/data/elevation_plain_2048/cube_meta.json (validation.land_mask.global_land_fraction = 0.28977; validation.baked_stats.land_area_fraction = 0.27631; total_area_m2 = 510,064,471,909,788), and the km² figure is this page’s own subtraction of those three — not read from any file, and not published anywhere.

The mask has one accepted failure, documented in the sidecar so nobody “fixes” it by accident: endorheic basins below the datum — Death Valley at −86 m, Turpan, the Dead Sea — read as water. Resolution was never the cause. With no ice present the flotation test reduces exactly to bed > 0, so a basin below sea level is classified as water however finely it is sampled; being sub-texel only ever hid the consequence. It no longer hides it: the sidecar's “sub-texel at every tier” note was written when 1024 was the finest tier at 9.77 km per texel, and at 2048's 4.886 km Death Valley's ~15 km spans about three texels. Repairing it would mean rasterising coastline vectors, adding a geospatial dependency this pipeline deliberately does not have.

Badwater Basin at 282 feet (about 86 m) below sea level: US National Park Service, Death Valley National Park. The mask behaviour, the accepted-limitation ruling and the three-texel recomputation are this project’s own: pipeline/build/bake_elevation_cube.py (compute_land_mask docstring, KNOWN ACCEPTED LIMITATION) and the same note in app/public/data/elevation_plain_2048/cube_meta.json under channels.G. The three-texel figure is computed here from km_per_texel = 4.88649579980971 at the 2048 tier; the docstring’s own “sub-texel” wording predates that tier and has been corrected in the same commit as this page.

Built-up surface, and the sample sites

City extent comes from the JRC's GHSL built-up surface product, GHS_BUILT_S_E2020_GLOBE_R2023A at 30 arc-second resolution, epoch 2020, under the catalogue’s European Commission reuse notice. Its values are built-up area in square metres per cell, not a fraction, so converting requires dividing by each cell's own latitude-dependent physical area — which is why decimation here is an area box-sum followed by per-output-cell normalisation, not a mean of areas. Total built-up area is conserved to a ratio of 0.99940 between source and baked cube. The product clips short of the poles at 89.0996°, and 1,640 texels of the 2,048-face cube fall beyond that; they are set to zero built-up as a display convention outside the product’s coverage, not a measurement that no structures exist.

Pesaresi, M. & Politis, P. (2023), GHS-BUILT-S R2023A, European Commission Joint Research Centre, doi:10.2905/9F06F36F-4B11-47EC-ABB0-4F8B7B1D72EA — product page human-settlement.emergency.copernicus.eu; documentation GHSL Data Package 2023, doi:10.2760/098587; the release’s own reference publication is Pesaresi et al. (2024), International Journal of Digital Earth 17(1). The 89.0996° clip is the product’s. The 0.99940 conservation ratio, the 1,640 zeroed texels and the box-sum-then-normalise method are this project’s own, measured 2026-08-17: app/public/data/urban_plain_2048/cube_meta.json (source, validation, coverage) · pipeline/fetch/ghsl.py. The multi-gigabyte source archive is deliberately not linked.

And then the measurements. The sample-site layer is the van den Hoogen et al. 2020 database (Scientific Data 7:103), released CC0 on figshare: 6,825 georeferenced soil-sample records, not 6,825 independent sites. It ships as 6,825 unpadded 13-byte records — latitude, longitude, total individuals per 100 g dry soil, biome index — 88,725 bytes in total. Everything else the source CSV carries (per-group counts, sampling method, depth, DOI, data provider) was dropped.

Three caveats travel with those points and all three are in the sidecar. The model published in Nature used 6,759 samples; the CC0 release contains 6,825; both numbers are correct for different things and are not interchangeable. The updated release adds 66 samples from Ireland; repeated records can share a location. Extraction efficiency — how completely a method recovers the nematodes actually present — varies by method and the source paper discusses incomplete recovery. That can bias observed counts low; it does not make every downstream model estimate a guaranteed lower bound. And the sampling is wildly uneven: Temperate Broadleaf Forests alone accounts for 2,175 of the 6,825 points, while Tropical Dry Forests has 11 and Flooded Grasslands has 7.

Getting even the published biome table to reproduce required replicating an undocumented quirk in the authors' own analysis: biome codes arrive as near-integer floats needing rounding, and every sample south of 60°S is forcibly recoded to “Antarctica”. Skipping that override was the difference between reproducing the published Tundra row (n = 148, median 2,695) and getting n = 651.

van den Hoogen, J. et al. (2020), A global database of soil nematode abundance and functional group composition, Scientific Data 7:103, doi:10.1038/s41597-020-0437-3; the data itself is Nematode_abundance_dataset, figshare doi:10.6084/m9.figshare.11733897, which is the CC0 item this pipeline actually downloads — the wrapping figshare collection is CC BY, not CC0, and the distinction matters. The sample counts and extraction-method caveats describe source-data limitations, not a guarantee about every prediction. The 13-byte record layout, the 88,725-byte total and the replication of the authors’ undocumented sub-60°S recoding are this project’s own work, 2026-08-16: app/public/data/nematode_samples/samples_meta.json · pipeline/fetch/nematode_samples.py · pipeline/build/bake_nematode_samples.py.

In the August 2026 inventory, the seven raster atlases fetched by the viewer decoded to 519,831,552 bytes, against 88,725 bytes of sample records. The soil raster supplied model predictions wherever it had valid support, not a census of all land. These sample records establish sampling locations, not a measured percentage of Earth's land area. Away from those sites, abundance is modelled. Pressing s toggles markers for those sample records, with the far hemisphere hidden and overlapping records potentially occupying the same screen position.

Measured by this project on 2026-08-17, over the eight directories app/src/viewer.ts fetched in app/public/data/ at that time · app/src/hud/copy.ts (the s binding) · app/public/data/nematode_samples/samples_meta.json. That sidecar also records a 0.0002%-of-land estimate, but a point count alone does not establish sampled area; it should not be treated as a measured coverage fraction. The source paper reports no such figure.

Layer Source Native grid Derived output Coarsening
Nematode density van den Hoogen 2019
ETH rasters
43,201 × 21,121, 30″ (0.93 km/px) August legacy: 128-texel faces — 78.2 km nominal, 44.0–99.5 km actual
Full-local candidate: 512-texel faces — 19.55 km nominal mean; local viewer status
Legacy ~84×
Candidate ~21× nominal
Elevation + bathymetry ETOPO 2022, 60″ bed
NCEI product page
21,600 × 10,800 (1.85 km/px) 2,048-texel faces — 4.89 km/texel ~2.6×
Built-up surface GHSL GHS-BUILT-S E2020
JRC product page
30″, 21,384 rows (0.93 km/px) 2,048-texel faces — 4.89 km/texel ~5.3×
Soil-sample records van den Hoogen 2020
figshare, CC0
6,825 points 6,825 points none

Sources, in table order. Nematode density: van den Hoogen et al. 2019, doi:10.1038/s41586-019-1418-6, rasters at ETH doi:10.3929/ethz-b-000354035. Elevation and bathymetry: ETOPO 2022, doi:10.25921/fd45-gt74 (NCEI product page). Built-up surface: GHS-BUILT-S R2023A, doi:10.2905/9F06F36F-4B11-47EC-ABB0-4F8B7B1D72EA. Soil samples: Scientific Data 7:103, with the CC0 data at figshare doi:10.6084/m9.figshare.11733897. The native grids are the publishers’. The legacy tiers and coarsening factors are this project’s own, measured 2026-08-17 from app/public/data/*/cube_meta.json, nematode_samples/samples_meta.json and pipeline/out/total_persqm_meta_512x256.json. The September candidate’s face size is recorded in app/public/data/soil_plain_512_v2/cube_meta.json; its nominal pitch and coarsening are geometric calculations, not ecological resolution.

A screen-aware limit, not invented detail

The public viewer now stops magnifying the soil atlas once its widest ground-level texel would span eight CSS pixels in the central view. The cutoff uses the actual camera projection and viewport size, so a laptop and a phone can stop at different altitudes. It stays the same throughout the sweep: removing the terrain does not suddenly permit a blurrier view. A quiet “Maximum detail for this dataset” hint explains the stop. This is a visual-quality choice, not a claim that each texel is an independent observation or that the model is ecologically accurate at that scale. It does not add terrain tiles or finer measurements.

This project’s display policy, added 2026-09-22: app/src/core/zoomQuality.ts. The estimate uses (2R/N) × focal_length_in_CSS_pixels / altitude, with N = 512 for the accepted soil atlas. It bounds the largest plain-cube texel at the central ground view; it is not a per-fragment error bound for the finite-height, two-wall volume.

Source credits and dataset rights are collected in Credits & rights; the original records are linked below.

Rights records checked 2026-09-19. ETH density rasters: In Copyright — Non-Commercial Use Permitted (InC-NC 1.0), the rights statement registered against both doi:10.3929/ethz-b-000354035 and doi:10.3929/ethz-b-000354394, verified in their first and second DataCite records; direct ETH page access was blocked during this check. InC-NC explicitly says it is not a licence. ETOPO 2022: CC0, declared in NOAA’s own metadata record at doi:10.25921/fd45-gt74. GHSL: the dataset catalogue specifies the European Commission reuse notice, requiring source acknowledgement. The accompanying GHSL Data Package 2023 report is CC BY 4.0; that document licence should not be substituted for the dataset’s stated conditions. Sample points: CC0 1.0, registered on the figshare dataset doi:10.6084/m9.figshare.11733897 (the collection wrapper is CC BY). These citations document provenance; they do not by themselves establish permission for every use of a derivative.

Section III

How the image is produced

Nothing on screen is a photograph. The density field the shader integrates is deliberately not a three-dimensional volume: it factorises into a direction and a depth, ρ(dir, z) = A(dir) · g(z) — a cube map of areal density multiplied by an analytic depth profile. WebGPU's default maxTextureDimension3D is 2048 against 8192 in 2D. In the installed three.js loader, supported uncompressed KTX2 formats can become 3D textures, while its compressed-format branch rejects nonzero pixel depth. This is a limitation of that loading path, not a claim that all volume toolchains are unsupported. More importantly, the soil abundance raster represents a 0–15 cm column, not resolved vertical layers. The vertical distribution drawn here is modelled, not measured.

The limits are normative: W3C WebGPU, §3.6.2 Limits gives maxTextureDimension3D a default of 2048 against maxTextureDimension2D 8192. Binomial LLC, Basis Universal documents mipmaps, arrays, cubemaps and cubemap arrays; the version-specific three.js loading paths are in KTX2Loader.js, tag r185. The container format is Khronos KTX 2.0. The 0–15 cm abundance-column scope is a property of van den Hoogen et al. 2019. The decision to refuse the volume, and its wording, are this project’s own: docs/superpowers/specs/2026-08-15-nematode-earth-design.md §4.1–4.3.

The original design proposed three rendering regimes for an orbit-to-organism descent. The current public zoom limit keeps the view in Regime 1, the shell, a volumetric raymarch. The following close-range systems are prototype work, not a completed public descent. Regime 2, the particles, is a compute-instanced splat system designed to take over across a band from 33.16 km down to 3.32 km — a band that is derived rather than chosen: the shell caps its rendered optical depth so the rim never blows out, and that cap first bites the global-mean density at a scale height of 5,526.7 m, i.e. an altitude of six scale heights. (That figure is computed from the design-time mean τ = 0.047, not a current-atlas measurement.) The weighting transition ends a decade lower. Conservation would require both representations to sample the same extinction field; the current particles still use a synthetic field while the real shell uses the soil atlas. This is an experimental comparison, not a demonstrated energy-conserving transfer of the real data.

Regime 3 is not built. The spec's module table lists regimes/Proxies.ts (5 m → 1 cm) and regimes/Hero.ts (the single organism); neither file exists. The spec is blunt about why it is hard: below about 5 m the g = ρ·I framework — instanced splats each carrying one scalar intensity — stops being valid, because an assumed representative 957 × 41 µm nematode — a figure this project could not source anywhere — has a side-on to end-on projected-area ratio of 29.7, and an orientation-independent intensity cannot smoothly meet a geometry-shaded animal. A long investigation into what looked like a catastrophic Regime 2 failure at 1.2 cm altitude ended by ruling that it was Regime 2 running unopposed far past where the spec says its model stops being valid, visible only because both regimes meant to have taken over are unbuilt. Regime 2 itself is honestly labelled a foundation pass: a 200,000-instance budget against 800,000 candidate cells, bound to the synthetic field rather than the real atlas, not the spec's four-million budget.

The g = ρ·I splat framework is Max, N. (1995), Optical models for direct volume rendering, IEEE TVCG 1(2), 99–108, which app/src/regimes/Blend.ts already cites by name in comment. The 957 × 41 µm body size has no source at all: it is an assumed representative soil nematode, stated bare in this project’s own spec, and the 29.7 projected-area ratio is arithmetic on that assumption, so it inherits the same status. Everything else — the altitude band, the 200,000-instance budget, the unbuilt Regime 3 — is this project’s own record: app/src/regimes/Blend.ts (REGIME2_TOP_ALT, REGIME2_FULL_ALT, and its own note on the spec tension) · docs/superpowers/specs/2026-08-15-nematode-earth-design.md §7.7–7.8, §9 · app/src/regimes/ (contains only Blend, Particles, SamplePoints, Shell, SplatBlur) · docs/superpowers/results/2026-08-17-regime2-deposit-investigation.md.

The march

A back-face mesh supplies fragment coverage and ray direction. The shader calculates the spheroid intersections analytically and marches front-to-back with up to 128 samples per segment. An enabled far-wall segment gets its own loop. Each step samples the atlas, applies the authored vertical profile and taper, and computes transmittance exp(−σ·dt). Contributions accumulate through the remaining transmittance; either loop can terminate once it falls below 0.003.

Everything else in that loop is precision discipline. The intersection runs in “sphere space”: origin and direction are pre-multiplied by diag(1/a, 1/a, 1/b), turning the WGS84 spheroid into a unit sphere and an exactly-analytic two-root problem. The spheroid is a requirement here, not a refinement: the true surface sits +7.1 km above a mean sphere at the equator and −14.2 km at the poles, up to 142% of the regime handoff altitude. The chord is computed directly as 2s and never as the difference of two ~3 × 10⁷ m ray parameters, and the roots are formed through the stable c/q branch. The outer bound tapers with a smoothstep across the last e-fold rather than truncating, because a hard cut leaves a visible alpha ring at the exact focal point of the composition. Every texture read inside the loop uses an explicit LOD, because the transmittance break makes control flow non-uniform and WGSL's derivative-uniformity rule is an error by default.

WGSL’s derivative-uniformity rule is an error by default: W3C WebGPU Shading Language, §Uniformity. The spheroid is WGS 84 (NGA.STND.0036), defining parameters at NGA. The stable c/q branch is the standard cancellation-avoiding form of the quadratic; Goldberg, D. (1991), ACM Computing Surveys 23(1), 5–48 is the citable treatment. The intersection was cross-checked against CesiumJS IntersectionTests.rayEllipsoid. The 128 steps, the 0.003 break threshold, the smoothstep taper and the +7.1/−14.2 km figures are this project’s own: app/src/regimes/Shell.ts (intersection, march loop, explicit .level(0) sampling) · docs/superpowers/specs/2026-08-15-nematode-earth-design.md §7.1–7.2, §10.

There is one recent structural addition. Once the sweep has removed all matter, a ray that would have hit solid ground keeps going, crosses the hollow interior, and re-enters the density on the far side of the planet. That second crossing is marched as its own segment through the same per-step code, gated on two conditions that must both hold: matter fully dissolved (while it exists it genuinely occludes the far wall) and altitude at or above the top of the Regime 2 band, since the partition assumes exactly one density column per direction and an uncounted second one would over-weight the shell by up to 2×.

This project’s own code and its own reasoning; nothing external is being cited. app/src/regimes/Shell.ts (ShellFarWallOpts, and the gate on sweepState.matter with shellPartitionShare) — the two conditions and the up-to-2× over-weighting are stated there.

From abundance to opacity

The number that connects the ecology to the picture is an assumed mean projected area per animal: E[A] = 1.49 × 10⁻⁸ m², about 14,900 µm². This is a project modelling parameter, not a measured global nematode silhouette. Optical depth at nadir in that model is τ = E[A] · N_A — abundance per square metre times one animal's silhouette — and depends on the total column rather than how it is spread vertically. For independently Poisson-placed opaque silhouettes, expected coverage is 1 − e^(−τ). Real nematodes are not known to satisfy that idealization: orientation, clustering, body dimensions and transparency all matter. The shader also needs an authored depth profile to draw oblique rays and the limb.

app/src/math/optical.ts stores E_A as a fixed constant. Its design rationale used 0.6426 × E[L·D_max], with E[L·D_max] = 2.31 × 10⁴ µm² and a chosen 30% adult / 70% juvenile weighting, referring to biomass in Table 1 of van den Hoogen et al. 2019. Biomass alone does not determine projected area. No reproducible body-size calibration or statistical interval is supplied here, so the earlier confidence-interval claim has been removed. The coverage formula follows from the zero-event probability of a Poisson process; its assumptions are not observations about nematode positions.

The shader converts τ into a peak extinction with σ₀ = τ / (Hs·(1 − e^(−Hmax/Hs))). This normalizes an ideal, truncated exponential column before additional display adjustments. The actual shader caps τ, tapers the outer edge, takes finite steps and can terminate early: its image is not an exact conservation measurement. The extraction’s separate numerical conservation checks are described above.

For a thin exponential shell, the tangent-to-nadir path ratio is approximately Q = √(2πR/Hs), about 35.4 at the opening’s authored 32 km scale height. The display caps optical depth at 4/Q ≈ 0.113 to keep the rim readable. This expanded shell is not a measured distribution of animals above the ground or a depth profile inside soil. The visible rim is an artistic rendering of a column model, not a prediction of a physical nematode atmosphere.

The Chapman function and its one-sided asymptote ch(x, π/2) = √(πx/2), which app/src/math/optical.ts invokes by name in comment, are Chapman, S. (1931), Proceedings of the Physical Society 43(1), 26–45. Beer–Lambert extinction is textbook and needs none. The 32 km scale height and the 4/Q cap are this project’s own choices and computations: app/src/math/optical.ts (sigma0, limbRatio, saturationCapTau) · app/src/math/descent.ts (H_S_MAX = 32000) · docs/superpowers/specs/2026-08-15-nematode-earth-design.md §7.3–7.4.

One more honesty gate lives in the same stretch of shader. Over ocean and the polar no-data gap the atlas's red channel decodes to a numerical floor, not a measurement. The rendered soil atlas has no marine coverage; the marine research pipeline is separate. The coverage helper is now a zero-only gate: zero coverage contributes nothing, while nonzero coverage leaves the sampled τ unchanged before the cap. An all-cell mean already includes dilution by its supported area and must not be multiplied by coverage again: mean density 50 with coverage 0.5 remains 50, not 25.

That the source is a terrestrial soil model with no marine coverage is a scope fact about van den Hoogen et al. 2019. The gate itself is this project’s own code and its own honesty decision: app/src/regimes/Shell.ts (zero-coverage gate; nonzero coverage does not rescale an all-cell mean).

Six flat faces on a round planet

The atlas is a cube map: six RGBA16Float faces, sampled by direction, letting the hardware pick the face and filter across the seams. Cube rather than equirectangular because equirectangular destroys the poles. R holds natural-log density — the August atlas’s supported values spanned roughly 6 × 10⁵ to 2 × 10⁷ per m², a range that linear 8-bit encoding would crush. A carries valid-model support, not an ocean mask; B carries bootstrap CV. R, A and B come off one fetch, so the uncertainty overlay costs no extra texture fetch in the hottest loop. The candidate’s G numerator requires its separate group-support mask; its B is a mean of native pixel CVs, not aggregate-count uncertainty. The channel contract above distinguishes these encodings from the legacy cube.

The interesting geometry is that a cube face is a flat, evenly spaced grid projected outward onto a sphere. The ray to a corner texel is longer and strikes the sphere more obliquely than the ray to the centre texel, so equal squares of grid subtend unequal sky: solid angle falls off as (1 + u² + v²)^(−3/2), giving an exact 3√3 = 5.196 ratio between a face centre and its extreme corner. The August atlas's own sidecar measured 5.114 at texel centres. In ground units, one texel of that legacy 128-face cube was an equivalent square 99.5 km on a side at a face centre and 44.0 km at a corner. So the headline “78.2 km/texel” is a face-average, not a uniform resolution — and at the corners that atlas was already finer than the equirectangular grid it was baked from. Rebaking that same coarse input could not restore lost source detail. This historical limit does not apply to the candidate’s finer extraction grid; its 19.55 km nominal mean likewise is not a uniform ground footprint.

The cube-map face-selection and (u, v) convention the geometry rests on is Khronos, OpenGL 4.6 Core Profile Specification, §8.13 Cube Map Texture Selection; the (1 + u² + v²)^(−3/2) solid-angle falloff and the exact 3√3 = 5.196 corner ratio follow from that convention by elementary calculus rather than from any standard, and no document states them. (Related treatment: Manson, J. & Schaefer, S. (2012), Parameterization-Aware MIP-Mapping, Computer Graphics Forum 31(4), 1455–1463.) The measured 5.114 and the legacy 128-face kilometre figures are this project’s own measurements of its own atlas, 2026-08-17: app/public/data/cube_plain_128/cube_meta.json (texel_ground_stats: worst 99.53 km, best 44.01 km, RMS 72.03, solid-angle ratio 5.114) · pipeline/build/bake_cube.py · app/src/field/loadCube.ts.

The terrain and city atlases load as progressive ladders: elevation at 256 → 1024 → 2048 faces, urban at 512 → 1024 → 2048. Tiers are fetched sequentially, not in parallel, because they compete for the same connection and fetching the coarse tier alongside the sharp one delays the very thing it exists to make fast; sequencing also makes “a later tier never loses to an earlier one” true by construction. Each landing tier rebuilds the materials that sample it and only then disposes the superseded texture.

Floating origin

At 6,371 km from the planet's centre, one f32 ULP is exactly 0.5 m. The original prototype targeted a descent to 1 cm; the public view now stops at its dataset-quality limit. The floating-origin architecture remains: the camera sits at the render origin and the world translates around it, with the subtraction done in f64 on the CPU and only the small residual handed to the GPU. Scroll is logarithmic in altitude, with a softened inward approach at the public quality limit.

This has a subtle consequence inside the shell shader, and the code documents it precisely. Under a floating origin, TSL's cameraPosition builtin reads exactly (0,0,0) — useless as the ray origin, which must be the camera's position relative to the planet's centre, so that arrives as an explicit uniform. The ray direction, positionWorld − cameraPosition, needs no fix at all: the builtin is exactly zero, so the subtraction is a no-op and the direction falls out of the now-small, now-precise world position directly.

The binary32 significand the 0.5 m ULP follows from is IEEE Std 754-2019, doi:10.1109/IEEESTD.2019.8766229; Goldberg 1991, ACM Computing Surveys 23(1), 5–48 is the freely readable treatment of the same ground. TSL is documented at the three.js Shading Language wiki. The ULP arithmetic at 6,371 km, the floating-origin architecture and the observed cameraPosition = (0,0,0) behaviour are this project’s own: app/src/core/ScaleCamera.ts (worldToRender) · app/src/regimes/Shell.ts (ray setup comment) · docs/superpowers/specs/2026-08-15-nematode-earth-design.md §7.2, §8.1.

Two pieces of craft

The August faceting came from the filter. The legacy veil was reading as polygonal. At roughly 31 screen pixels per texel, the visible structure came from the reconstruction filter. Hardware bilinear is C0: linear inside each texel cell, with a gradient discontinuity across every cell boundary. Magnify that and every crease in the field falls exactly on the texel grid — measured, 100.0% of the field's second-derivative mass landing on the boundary lines, against a 6.1% uniform baseline. The fix warps the texel coordinate through a smoothstep before sampling: in texel-centre space the map is p → floor(p) + smoothstep(frac(p)), which fixes every texel centre (so the reconstruction still passes through the baked values) and has zero derivative on both sides of every cell boundary (so it no longer creases there). C1 reconstruction for a few ALU, with the filtering itself left in the texture unit. Crease mass drops to 10.8%, and peak-to-mean curvature from 74.5 to 9.0.

The elegant part is the seam argument. The warp is applied component-wise with no per-face branching, and it does not need any, because the warp function is odd: W(−c) = −W(c) follows from smoothstep(1 − f) = 1 − smoothstep(f) and the mirror symmetry of the texel grid, so it commutes with every signed permutation a cube-map convention can apply. And it cannot open a seam, because it fixes ±1 exactly: at a face edge c = 1 gives a fractional part of 0.5, and 0.5 is a fixed point of smoothstep. The major axis stays the major axis, so no direction is ever moved onto a different face; a direction exactly on a seam stays exactly on it and is warped identically from either side. The warp preserves the seam set, but can move a direction along a seam; it is not pointwise the identity there.

Measured by this project, 2026-08-17. The warp construction, the seam proof and every figure here — 100.0% crease mass against a 6.1% uniform baseline, 10.8% after, peak-to-mean curvature 74.5 → 9.0 — are the project’s own; no external source states any of them, and smoothstep itself is a standard shading function rather than a citation. app/src/field/loadCube.ts (smoothstepTexelWarp) · app/test/cubeFilter.test.ts — including a negative control that must report the 6.1% baseline on a texel-free field, so the instrument cannot be stuck high.

The banding was quantisation, and the dither had to be relative. A second, independent defect: the veil's entire on-screen range spans about eleven 8-bit codes at the default 8× exposure, so those codes render as wide flat plateaus with hard contours between them — terraced rather than faceted. Fixing one defect and not the other leaves the complaint standing. The fix is an ordered dither (interleaved gradient noise, three ALU, no texture), applied as one shared scalar on the whole premultiplied vec4 rather than per channel: the march's colour and alpha are algebraically the same accumulated quantity, so a single factor keeps the premultiplication exact and dithers luminance only, where per-channel noise would dither the hue of a deliberately near-monochrome veil.

The amplitude is relative — a fraction of the fragment's own value — not an absolute offset, for two independent reasons. First, it has to vanish where the veil does: the shell writes premultiplied radiance over empty space, and a signed absolute offset would sprinkle noise (and negative radiance) across the whole sky, whereas a relative one is exactly zero wherever the accumulated column is zero. Second, it has to survive the exposure control, which is a renderer property the shader cannot see. Across the 1×–64× range the absolute linear step corresponding to one 8-bit code moves by about 50×, while the relative step is far flatter. The chosen 0.02 was derived against a CPU model of the real chain — three.js's ACES filmic fit including the /0.6 pre-scale and both matrices, then the sRGB transfer function, then 8-bit rounding — and lands between 0.24 and 1.47 codes peak-to-peak across the whole exposure range: about the one code an ordered dither wants, never several. Measured effect: the longest identical-code run collapses from 28 px to 4 px, and locally-averaged error from 0.237 to 0.063 codes. Notably the count of distinct levels barely moves, 11 to 12 — which is why that obvious metric was rejected as the instrument.

Interleaved gradient noise is Jimenez, J. (2014), Next Generation Post Processing in Call of Duty: Advanced Warfare, SIGGRAPH 2014 course Advances in Real-Time Rendering, credited by name in app/src/field/terrain.ts. The tone curve modelled is the ACES filmic fit three.js actually ships — Stephen Hill’s ACESInputMat / RRTAndODTFit / ACESOutputMat, which three.js cites in its own source — and not the one-line Narkowicz curve that often goes by the same name. The transfer function is sRGB, IEC 61966-2-1:1999 (IEC webstore record; the standard itself is paywalled). The 0.02 amplitude, the 0.24–1.47 code range, the 28 px → 4 px run length, the 0.237 → 0.063 error and the 11 → 12 level count are this project’s own measurements, 2026-08-17: app/src/field/terrain.ts (VEIL_DITHER_AMPLITUDE = 0.02, veilDitherScale) · app/test/veilDither.test.ts.

Both fixes shipped with tests that carry the pre-fix arm and a control that must report the baseline — a discipline the project arrived at the hard way, which is the subject of the next section.

Section IV

What we got wrong

Almost none of the defects in this project announced themselves. There was no stack trace, no failing test, no red console line. Each produced output that looked entirely plausible — a planet, a coastline, a glow, a passing gate — and each was found only when somebody measured something nobody had measured before. Read together they share a cause, and the sidecars and commit messages say so in nearly the same words each time: an instrument that returns the same answer whether the system is healthy or broken.

Defect 01A hard-edged rectangle around Greenland

The first land-mask rule treated ice as land whenever ice was present at all: surface − bed > 1 m. Floating sea ice has real thickness, so open water under it was classified as ground, and the artefact drawn on screen was a hard-edged rotated rectangle around Greenland — the outline of the BedMachine Greenland mosaic's polar-stereographic extent, reprojected onto the sphere. That shape is why the bug was misleading rather than obvious: a rotated rectangle is the signature of a reprojection, so it read as a rendering error, and the data was the last place anyone looked.

Investigating it surfaced a second, larger error hiding inside the naive fix — the surface ≥ 0 clause described in Section II, which quietly classified about 0.43% of source cells as land incorrectly. That is a cell-count fraction, not a surface-area percentage. Global area-weighted land fraction fell from 0.2925 to 0.2898 after both changes; the current mask still has the limitations in Section II.

The mosaic whose polar-stereographic extent drew the rectangle is IceBridge BedMachine Greenland v5, NASA NSIDC DAAC, doi:10.5067/GMEVBWFLWA7X, method paper Morlighem et al. (2017), Geophysical Research Letters 44(21), doi:10.1002/2017GL074954 — it reaches this project only indirectly, through ETOPO 2022, which incorporates it. The land fractions and the whole bug narrative are this project’s own, 2026-08-17: pipeline/build/bake_elevation_cube.py · app/public/data/elevation_plain_*/cube_meta.json (channels.G; global_land_fraction 0.28975–0.29045 across tiers), fixed in a single commit recorded in this repository’s history.

Defect 02A gate that passed on data it should have rejected

The bake has a hard-fail gate: global area-weighted land fraction must land inside [0.285, 0.299] or the script raises before writing anything. The flotation fix re-baked four tiers — 64, 128, 256, 1024 — and missed 512. The stale tier kept the discredited rule's value of 0.2925058, which sits comfortably inside the accepted band. The named probes did not catch it either: at that moment the probe table held seven points, all of them grounded ice, dry land or deep open ocean, and not one standing on floating ice. Both instruments reported “pass” on an atlas built by a rule already proven wrong.

It was caught by noticing the omission rather than by any check, and fixed in the very next commit; the tier now reads 0.28975 and the probe table has ten points, three of them — Baffin Bay, the Arctic Ocean north of Greenland, and the Ross Ice Shelf — added specifically because they are floating ice and must read as ocean. The loader gained an independent second check that reads the atlas bytes rather than the sidecar's prose, on the explicit reasoning that a stale tier's own documentation is exactly the thing that would be lying. Its band is deliberately far looser: it is not trying to re-run the pipeline's gate, only to catch an atlas carrying no mask at all.

This project’s own defect record; there is nothing external to cite. pipeline/build/bake_elevation_cube.py (gate band) · the stale elevation_plain_512/cube_meta.json preserved in this repository’s history (0.2925058141116531, 7 probes) against the current file (0.28975, 10 probes) · app/src/field/loadCube.ts (assertLandMaskPopulated). The before-and-after comparison is recoverable from the repository’s history, not from any public URL.

Defect 03A feature multiplied by zero from the day it was added

The cube loader applied one re-encoding step to every atlas it loaded: add the natural log of a physical constant to the red channel, R −= 18.02. That is exactly right for the nematode density atlas, whose red channel is a log density that has to become a log optical depth. It is silently destructive for everything else.

The urban atlas holds built-up surface fraction in [0, 1]. Every texel on Earth became about −18. The shader that turns that into city lights is clamp(x, 0, 1) raised to a gamma — so city lights evaluated to exactly zero, on every fragment, in every frame, from the commit that introduced them until the fix fifteen commits later. Nothing threw and nothing warned. It read as a tuning problem, because a feature that renders nothing is indistinguishable from a feature whose gain is too low. The data had been fine the whole time: probing the atlas directly gives Tokyo 0.398, Cairo 0.216, mid-Pacific exactly 0.000. The same offset was landing on the elevation atlas as a flat −18.02 m bias — negligible against 8,849 m peaks, but it moves the shoreline off the datum both the colour ramp and the land mask are defined against.

The loader now dispatches on the sidecar's own field key and throws on one it does not recognise. A silent default is what let this live; a newly baked atlas now has to declare its encoding before it can be loaded at all.

This project’s own defect record and its own probes of its own atlas, 2026-08-17: app/src/field/loadCube.ts (needsTauEncoding) · app/src/field/terrainNodes.ts (cityLightIntensityNode). The fifteen-commit span was counted here and the Tokyo 0.398 / Cairo 0.216 / mid-Pacific 0.000 readings measured here; both are recoverable from this repository’s history and from the shipped atlas, and from nowhere public.

Defect 04The ocean rendered as “measured empty”

The legacy August density cube encoded log(max(density, floor)) with the floor set to 1.0 — a numerical-stability placeholder, chosen only so that log(0) = −∞ never reaches a filterable float texture. The veil's shader read that red channel and nothing else. Over open ocean and the polar coverage gap it therefore rendered the floor as though it were a measurement.

The rendered dataset is a terrestrial soil model with no marine density layer; the project now has a separate experimental marine research pipeline. Before the gate, the veil's honesty over 71% of the planet rested on how small an arbitrary constant happened to be. A slightly different floor would have painted the ocean with fabricated density, and the shader had no business depending on that choice in either direction. The fix removes the dependency rather than tuning it: the alpha channel carries coverage, exactly 0 over no-data texels. The current helper uses it only to suppress zero-coverage samples. Multiplying fractional coverage into an all-cell mean would dilute it a second time, so supported samples retain their density. The full local extraction and its candidate are separate from this renderer correction; local viewer status is recorded above.

That one is worth naming because it was later used prospectively. When the model-uncertainty overlay was added, unsupported areas of the legacy B channel could read 0 — precisely the value a ramp anchored at zero paints with its most certain colour, which would have asserted that the ocean is the best-measured surface on Earth. Coverage for that overlay is driven by valid-model support, never by the uncertainty channel itself: supported predictions and unavailable data must stay distinct. The coverage fade is authored display opacity, not numerical confidence; the candidate’s support-normalized B is not CV diluted by ocean.

That the underlying dataset is a terrestrial soil model with no marine data is a scope fact about van den Hoogen et al. 2019. The floor encoding, the fix and the uncertainty-ramp thresholds are this project’s own: app/src/regimes/Shell.ts (zero-coverage gate) · app/public/data/cube_plain_128/cube_meta.json (channels.R, channels.A) · app/src/field/terrain.ts (UNCERTAINTY_CV_LOW 0.09, UNCERTAINTY_CV_HIGH 0.35), with the fix recorded in this repository’s history.

Defect 05Ten hypotheses, and the step that was skipped nine times

At the bottom of the descent, roughly 100,000 accepted particles were depositing onto six pixels at the exact centre of the screen. Ten hypotheses were refuted before the real explanation arrived, and every wrong turn had the same shape.

The single-instance probe was placed at camera-forward × 2000 m, which projects to exactly NDC (0,0) — the screen centre both when projection works and when it collapses everything to the centre, so the one test able to distinguish those could not. The readback helper defaulted to a 128×128 centre crop, so an off-axis splat landing at x = 1058 reported “peak 0, argmax (−1,−1)”, indistinguishable from being dropped. The diagnostic readout intermittently reported a pre-descent camera state after a fast descent, so window bounds and particle counters came from different frames, and several earlier conclusions built on those readings were withdrawn outright. And clip.w — upstream of every symptom and downstream of every attempted fix — was not measured at all until the tenth round.

What finally broke it open was not a better theory. It was validating an instrument against a known-good input: the off-axis probe, unambiguously in front of the camera, reports clip.w = +2000.000 at a test distance of 2000. Once the sign was trusted, “100% of particles are behind the camera” became a finding instead of another artefact.

Two real bugs came out of it. The splat quad spanned a 1×1 pixel square with its four vertices sitting exactly on the four target pixel centres, so three lost the rasteriser's fill-rule tie and one pixel received what should have gone to four — an average 4× energy loss. And a guard whose comment claimed it pushed behind-camera quads to a “degenerate, off-screen” position did the opposite: dividing by 1e6 sends a point a few hundred metres out to NDC ~5e-4, which is the screen centre, where additive blending stacked every one of them. The headline symptom, meanwhile, was not a bug at all — a camera locked to nadir plus an isotropic candidate box means “above ground” and “behind the camera” become the same half-space once altitude falls below the sampling window, and those measurements were being taken three orders of magnitude below the documented floor of the model being measured.

The rasterisation tie-break that cost the splat three of its four pixels is specified behaviour: W3C WebGPU, §Rasterization. Everything else is this project’s own investigation, 2026-08-17 — the ten refuted hypotheses, the clip.w = +2000.000 probe, the 1×1 quad and the 1e6 behind-camera divide: docs/superpowers/results/2026-08-17-regime2-deposit-investigation.md · app/src/regimes/SplatBlur.ts, with the four fixes recorded in this repository’s history.

Defect 06And one where the reasoning, not the code, was wrong

A page about instruments that cannot fail should include the case where our own arithmetic was the instrument.

The commit that added the 2048 rung to both atlas ladders justifies it twice. For elevation: the 1024 atlas is screen-matched at about 21,500 km, the piece opens at 11,500 km, so the opening frame was magnified about 1.9× — “the one place the softness was structural rather than incidental.” For urban, two paragraphs later: it “gains less at the opening altitude, where 1024 was already screen-matched.”

Both cannot be true, because the two ladders are the same geometry. The sidecars are explicit: km_per_texel is 9.77299159961942 in both 1024 tiers and 4.88649579980971 in both 2048 tiers. Redoing the arithmetic from the repo's own constants — 50° vertical field of view, device pixel ratio capped at 2, opening altitude 1.15 × 10⁷ m — a 1024 face-centre texel is 12.44 km across and subtends 1.87 screen pixels at the opening frame. Identical for urban. The figure the commit quotes for elevation is right; the sentence about urban contradicts it.

In the August framing, the opening pose sat at longitude 0, latitude 0, exactly a cube face centre — the coarsest texel on the whole cube — so the face-centre figure is the right one for that frame, not a pessimistic bound. And the practical consequence is that the urban rung helps at precisely the altitude the elevation rung does, including the signature image, rather than only “on descent” as claimed. The decision to bake it was correct. The reason recorded for it was not, and reasons are the part that get reused. No commit in this repository corrects that sentence; this page is the correction.

This project’s own recomputation, and already labelled as such in the paragraph above. The contradiction is in a commit message in this repository’s history; the constants are in app/public/data/elevation_plain_1024/cube_meta.json and urban_plain_1024/cube_meta.json (km_per_texel); the redone arithmetic used the August app/src/viewer.ts (vertical FOV 50), app/src/core/Renderer.ts (pixel ratio capped at 2) and app/src/core/ScaleCamera.ts (OPENING_POSE). The 12.44 km and the 1.87 screen pixels describe that framing, not every screen. The September opening uses 10°N geocentric latitude, 10°W longitude and responsive framing.

Defect 07The shape to look for

The most recent example is a day old and sits in the interface, not the data. The heads-up display gained a detector for whether its own text was being clipped, written as scrollHeight > clientHeight. Overflow out of a flex container is not reachable by scrolling, so scrollHeight stays pinned to clientHeight and that test reads false whether or not anything is being cut off. It was caught because the DOM reported the Cobb quotation visible while a screenshot showed it gone — and it happened inside a pass whose entire subject was that failure mode. Measured off the child elements' own boxes instead, the same viewport reports 98 pixels of overflow.

The behaviour the broken detector relied on is specified: MDN, Element.scrollHeight states that when the content fits without a vertical scrollbar, scrollHeight equals clientHeight; normatively W3C CSSOM View Module, Element.scrollHeight. The 98-pixel overflow measurement and the defect narrative are this project’s own, 2026-08-17: app/src/viewer.ts (clip detector), fixed in a commit recorded in this repository’s history.

None of this is a claim to rigour; it is a list of things that were wrong for a while. What survives is a single question worth asking of any check, in a pipeline or a shader or a stylesheet: what would this report if the thing it is checking were broken? If the honest answer is “the same thing”, it is not a check.

Section V

Colophon

The web stack

The piece is a static site with no application backend. The globe is drawn by three.js 0.185.1 through its WebGPU renderer and TSL, the node-graph shading language that compiles to WGSL — every shading module imports from three/webgpu and three/tsl rather than the classic WebGL build. Around that sit TypeScript 5.9.3 in strict mode (with noUncheckedIndexedAccess, which forces an explicit check every time an array index is read), Vite 6.4.3 as bundler and dev server, Vitest 2.1.9 as test runner, and @webgpu/types 0.1.71 for the parts of the API three.js does not wrap. Node 22 and pnpm 10 build it. There is no UI framework, no state library, and no CSS toolchain; the HUD is hand-written markup and typed copy constants.

Project homes, so a reader can check what each of these is: three.js (release r185; the shipped package is 0.185.1, a patch publish on that tag, pinned exactly in app/package.json) · TypeScript and noUncheckedIndexedAccess · Vite · Vitest · @webgpu/types · Node.js · pnpm. The exact resolved versions are this project’s own reading of its own lockfile and cannot be attested externally: app/package.json declares ranges, and 5.9.3 / 6.4.3 / 2.1.9 are what they resolved to in app/node_modules/*/package.json — versions read 2026-08-17. app/tsconfig.json · app/src/hud/copy.ts.

Vite builds two production HTML entry points: viewer.html, the interactive piece, and about.html, this static methods page. The build emits the viewer again as index.html, so the site root opens the exhibit. A separate falsification harness remains available in development but is excluded from the public release.

The interactive viewer requires a usable WebGPU adapter. If one is unavailable, it provides a static poster, an explanation and a methods link. The methods page itself needs no GPU. Browser version alone does not guarantee that the necessary adapter and driver are available.

Multiple HTML entry points are a documented Vite feature: Vite, Building for Production — Multi-Page App. The viewer checks WebGPU availability and adapter initialization rather than assuming support from a browser name. The fallback is in app/viewer.html and app/src/viewer.ts; the development-only harness has its own gate. The harness and its four GPU experiments are this project’s work: app/vite.config.ts · app/src/experiments/report.ts · app/src/main.ts.

The Python pipeline

Everything under app/public/data/ is baked offline by pipeline/, a uv-managed Python project (requires ≥ 3.11) with a deliberately small dependency list: numpy, tifffile, imagecodecs, requests, and pytest for development. That list is notable for what it does not contain. There is no GDAL, no rasterio, no pyproj, no geopandas — the usual geospatial stack is absent entirely.

The pipeline reads TIFF headers and selected byte ranges without requiring the usual geospatial stack. The older extractor made HTTP range requests; the current conservative extractor can also read complete local TIFFs through local_range.py, which is how the September soil product was made. Remote retries are bounded and resumable downloads reuse verified blocks; server rate limits are not treated as invitations to retry aggressively. Historical throughput is a property of those recorded runs, not a permanent claim about ETH. All the projection maths — WGS84 geodetic/geocentric conversion, the cube-map face projection, the equi-angular warp — is hand-written.

Dependency homes: uv · NumPy · tifffile · imagecodecs · Requests · pytest, all declared in pipeline/pyproject.toml. The formats the hand-written parser implements against: TIFF Revision 6.0 (Library of Congress format record), BigTIFF, OGC GeoTIFF 1.1 (19-008r4) and RFC 9110 §14, Range Requests. The 403-on-default-clients behaviour and the 70–120 KB/s throttling are this project’s own observations of one server over one period, and the absence of GDAL, rasterio, pyproj and geopandas is this project’s own choice, evidenced by that dependency list. pipeline/fetch/tiff_header.py · pipeline/fetch/range_client.py · pipeline/build/wgs84.py · pipeline/build/eac.py.

The tests, and what they assert

Suite, measured 2026-08-17 713 TypeScript tests · 217 Python tests 39 files via pnpm test; 217 more via uv run pytest in pipeline/. Both figures move as the project does — they are a measurement on a date, not a constant. Counted by this project on 2026-08-17 by running both suites and reading the totals off the runners — pnpm test in app/ and uv run pytest in pipeline/. A measurement of this repository on a date, with no external counterpart.

The suite includes numeric examples, validation failures, source-wiring checks and geometric properties. Passing it does not validate the ecological model or replace GPU and browser checks. Examples from the test names: the dissolve front “never increases as the front advances” and “erodes low phi before high phi — it is a front, not a crossfade”; the terrain mesh's displacement floor “is never pierced by the mesh three.js actually builds”; the cube-map filter warp “is continuous ACROSS a seam” and “never moves a direction onto a different face”; the count estimate “is exactly 0 at altitude 0 — a genuine edge case (zero visible ground area), not a bug”. Even the HUD is under test: its copy must never nest parentheses, must mark negative numbers with a real minus sign rather than a hyphen, must document exactly the keys the viewer handles with “no ghosts, no omissions”, and — pointedly — must keep “every measured figure across the finding: a copy edit may not quietly drop the unflattering ones”.

Quoted verbatim from this project’s own test names — the only provenance these have, and the right one: app/test/dissolve.test.ts · app/test/groundHeight.test.ts · app/test/cubeFilter.test.ts · app/test/countEstimate.test.ts · app/test/hudCopy.test.ts.

The Python side is built the same way. The GHSL bake carries a hard-fail gate that stops with an AssertionError rather than printing a warning, and it exists because the urban bake was once silently zeroed by a sign-handling bug that compared abs(lat) > grid_lat_min against a negative bound — true for every texel on Earth. At the time, the mass-conservation ratio was written into the sidecar for a human to notice and never actually checked. The gate now runs three independent assertions, on the reasoning that a ratio-only check could pass a degenerate 0/0 case, and the corresponding test constructs exactly that trap: a fixture with ratio_baked_to_source = 1.0, annotated “would look 'perfect' on a naive ratio-only gate”. The gate's result is written into every shipped cube_meta.json, so the data carries the record of its own validation.

This project’s own gate, its own historical bug and its own test: pipeline/build/bake_ghsl_cube.py (assert_built_up_area_valid) · pipeline/build/test_ghsl.py · app/public/data/urban_plain_2048/cube_meta.json (wholesale_zeroing_gate). Nothing here is externally citable; the repository paths are the primary provenance rather than a stand-in for one.

One test-suite detail is worth stating because it is precisely the failure mode this project keeps hunting. Pytest's default norecursedirs includes a literal build pattern, assumed to be packaging output. This project's bakers live in pipeline/build/. In the August check, the default collected 19 tests and reported success; the override in pipeline/pyproject.toml collected 217. Neither errored. A green suite that silently ran 9% of itself is the same shape of problem as a bake that silently zeroed.

The default containing the literal build pattern is documented: pytest, Configuration Options — norecursedirs. The 19-versus-217 collection counts are this project’s own, measured 2026-08-17 by collecting under both settings, against the override in pipeline/pyproject.toml ([tool.pytest.ini_options] norecursedirs, with the reasoning in comment).

The build, and the brotli step

pnpm build is rm -rf dist && tsc --noEmit && vite build && node scripts/precompress-data.mjs. The typecheck is a gate, not a formality — it must pass before Vite is allowed to run. The last step is the interesting one.

Cloudflare's default response compression works from a content-type allowlist of about 48 types. application/octet-stream — what an unrecognised .bin extension serves as — is not on it, and the atlas .bin files are the overwhelming majority of this app's wire bytes. So the build compresses them itself: the script finds every dist/data/**/*.bin and overwrites it in place with brotli at quality 11, the maximum. This costs build time rather than per-request CPU time. app/public/_headers then declares Content-Encoding: br on /data/*.bin, which is what actually tells a browser those bodies are encoded. The two files move together — ship one without the other and every atlas fetch either breaks loudly on a byte-length mismatch or serves undeclared brotli as if it were float data.

Historical atlas compression, complete build of 2026-08-17 537,418,389 → 55,519,887 bytes 73 .bin files, 9.68× smaller, 89.7% saved. The ratio varies enormously by content: the built-up atlas compresses about 29×, because most of the planet is zero; elevation manages about 6×; the sample-site table about 2.6×. Measured by this project over app/dist against app/public/data on 2026-08-17, with every file verified to brotli-decode byte-for-byte back to its source, and corroborated by an independent measurement of the same build. These are properties of one build of this project — not of brotli itself (RFC 7932), and not of any published benchmark.

This has stopped being merely an optimisation. Cloudflare Pages caps individual files at 25 MiB, and a raw 2,048-face is 33,554,432 bytes — 32 MiB. Without the brotli step the build is not just heavy, it is undeployable. That consequence is our own derivation from two separately documented numbers; nothing in the repo states it yet, and the deploy doc's own limits table still records “8 MiB largest, pre-compression”, which predates the 2,048 tiers and is stale.

The cap is documented: Cloudflare Pages platform limits — “The maximum file size for a single Cloudflare Pages site asset is 25 MiB.” The 33,554,432-byte face is measured here (app/public/data/elevation_plain_2048/face_4.bin on disk, 2026-08-17), and the conclusion that the build would be undeployable without the brotli step is this project’s own derivation from those two numbers: nothing in the repository states it, and the local deploy note (docs/deploy-cloudflare-pages.md) still records a stale “8 MiB largest, pre-compression” table.

Two details of that script are the same argument the rest of the project makes, applied to a build tool. It refuses to no-op. If the glob matches zero .bin files, the script does not shrug and exit clean; it prints “Refusing to silently no-op on an empty match (would ship uncompressed data)” and exits 1. A build step that quietly does nothing when its input has moved is indistinguishable from a build step that worked, right up until half a gigabyte ships raw.

And one check was deliberately removed for failing quietly. An earlier version tried to skip files that already decoded as valid brotli, as defence against double compression. It produced a real false positive: RGBA16Float texture data is not random — narrow float16 exponent ranges, long runs of the zero/floor encoding over ocean — and a genuinely raw, full-size face decoded as some syntactically valid garbage brotli stream. The consequence was that a real file got skipped while _headers still claimed it was encoded. That failure is silent, where the bug it guarded against is loud, so the check is gone; rm -rf dist at the head of the build is the guard that stayed. The lesson the comment records is not that more checks are better: this one could fail without ever saying so, which is worse than not having it.

Cloudflare’s default compression and its content-type allowlist: Cloudflare, Compression — the served list enumerates roughly four dozen types and does not include application/octet-stream; it is overridable via Compression Rules. The _headers mechanism is Cloudflare Pages, Headers. Brotli is RFC 7932, and quality 11 is a deliberate departure from the streaming default documented at Node.js zlib, BROTLI_PARAM_QUALITY. The brotli false-positive discovery and the refuse-to-no-op rule are this project’s own: app/scripts/precompress-data.mjs · app/public/_headers · docs/deploy-cloudflare-pages.md.

Deploying, and one trap

The site is deployed to Cloudflare Pages. Its release is built with pnpm build from app/, which type-checks, builds, precompresses, and verifies the output directory app/dist. Vite copies _headers copied verbatim from public/ by Vite. Hashed assets and the atlas get max-age=31536000, immutable; the entry HTML gets max-age=0, must-revalidate so a deploy is visible on the next load. Because the atlas paths are not content-hashed, that immutable cache is a real tradeoff paid in discipline: any rebake that changes what a path's bytes mean has to ship under a new directory name, or a returning visitor can serve stale data for a year.

The trap: do not use vite preview to sanity-check data loading after a production build. Preview serves dist/ directly with no _headers support, so it hands the browser brotli bytes with no Content-Encoding declaration, and the app rejects them as a byte-length mismatch. This looks exactly like a data-corruption bug and is not one. Use pnpm preview, this project's header-aware release preview, to check the compressed build locally. pnpm dev serves uncompressed source assets and is useful for development, but does not test the release encoding.

On the first live Pages deployment, a request explicitly advertising Brotli received Content-Encoding: br. The transmitted atlas face matched the built Brotli asset byte-for-byte, and its decoded contents matched the source face. This checks the deployed binary path; it does not substitute for a device-by-device performance test.

Vite CLI, vite preview serves the build directory as plain static files and implements no _headers convention, which is what strands the hand-written Content-Encoding (RFC 9110 §8.4); the Pages build fields are Cloudflare Pages build configuration. The observed byte-length-mismatch failure is this project’s own, 2026-08-17. The live Brotli header and decoded-byte comparison were repeated against the Pages deployment on 2026-09-26. The header-aware local preview is implemented in app/scripts/preview.mjs. app/public/_headers · app/scripts/precompress-data.mjs (header comment) · docs/deploy-cloudflare-pages.md.

Who built it

Ethan Soch developed the visualization and engineering with coding assistance from Claude Code and, for subsequent revisions, Codex, using agents working in parallel from written plans. That is visible in the repository's shape rather than in any credit string: the plans are written as numbered tasks with explicit “Create / Consumes / Produces” contracts so that independent agents can hold non-overlapping pieces of the codebase; tasks needing real hardware are individually flagged “Requires GPU or network — not closed-loop verifiable by a subagent”; and the session reconciliation document schedules whole sessions against each other on the grounds that one “can run in parallel”. A separate directory holds the per-task reports the agents wrote back.

The test suite's density, and its habit of asserting properties rather than values, is downstream of the same arrangement. When the thing checking the work is another instance of the same model, the checks have to be things that can actually come out false.

The tool is Claude Code (documentation). The plans, the task contracts and the per-task agent reports are recorded in this repository — docs/superpowers/plans/2026-08-16-session-*.md, 2026-08-16-sessions-2-6-reconciliation.md, .superpowers/, and .gitignore’s note on .claude/ as agent scratch — and are not published anywhere a reader can open them.

Section VI

References

Every published source cited above, in one place, because a methods page should let a reader see all of its sources at once rather than hunting them through the prose. What is not here is as much of the point: the figures this project measured itself have no entry, because they have no external reference. Those notes say so where they stand.

Literature

Datasets and rights statements

Standards and specifications

Software, tooling and documentation