# Changelog

## 0.51.1 - 2026-11-13

Tests only: the package is unchanged by this release.

- **The ride spec's lost-context test no longer runs out of time** (MODULES-1191). "A lost context comes back with the ride" was the tail of a test of three rounds of six ride switches that takes half of its 60 seconds on its own; it is now a test of its own (about 10 seconds) and the leak test keeps its rounds.
- **The glide test ends on the page's clock** (MODULES-1062). "Switching bodies glides" waited real seconds for the clock to carry the glide and the let-go of the pictures; it owns the clock and runs the page's time through, as the other ride tests do.
- **freezeClock's widening is held by a test** (MODULES-1064). When a loaded machine has run the page's clock past the 3 second margin, `freezeClock` reads the time again and asks with 4 and then 16 times the margin; a test with a fake page now holds that, and that any other answer is given back at once.
- **The satellites buffer test reads the buffers after the draw** (MODULES-1065, 1086). "Taking a group away frees its buffers" counted the GL buffers after a fixed 800 ms; it now reads the draw count in the same turn as the change, waits for the draw that follows and for the view to be still, and then counts.
- **The glide into the above view is counted on the page** (MODULES-1190). `ride-above.gl.ts` counts each glide at every animation frame (an earlier fix, e545a3d); checked again with 5 repeats under CPU throttle 4 and with the glide taken out of the product, which fails it.

## 0.51.0 - 2026-11-13

- **The ridden satellite's own orbit grows out of the camera** (MODULES-1340). In Ride along the orbit ahead, seen edge-on, was a hard bright stroke. Its opacity now rises from nothing at the camera to the path's whole look about 300 km along it (`RIDE_PATH_FADE_KM`, a smooth rise worked out in the ribbon shader from each point's distance to the camera: no extra draw, nothing drawn at rest, and every other path unchanged). The ribbon now reaches the camera for it instead of stopping 64 km short.
- **The ridden satellite's group orbit line is left out** (MODULES-1340). While a satellite is ridden, the group's own orbit line for it is not drawn, nor the lines of objects on the same orbit (the modules of the ISS), because the ribbon draws its path in the `selected` look; with `selected-path` off the ridden satellite has no orbit line, which is what that switch means. The other satellites keep their lines, and all of them come back when the ride ends. `stats.satellites.orbitLines` counts the group orbit lines drawn.
- **A test that a painter's model brings no light of its own** (MODULES-1293). The ISS model test now counts the lights each live GL program was made for and wants every lit one made for the scene's one Sun; with the strip switched off it fails. Test only.

## 0.50.0 - 2026-11-13

- **The catalogue search folds kana** (MODULES-1268). `findInCatalogue` folds hiragana to katakana and small kana to full-size on both sides of the comparison (and half-width katakana by NFKC), so `はっぶる` finds `ハッブル`, in satellite names and group labels; the long-vowel mark is left alone. `foldKana(text)` is the same fold, exported from `@johnmorrisdotca/chikyu-earth/satellites` for a page's own search box.
- **A painter's model no longer adds a program to every lit material** (MODULES-1293). The scene now owns one Sun light, always there, and a satellite model made by `setSatellitePainter` is lit by it: a light the model carries (directional, point, spot, hemisphere, area) is switched off when the model is added, and its colour and strength are worn by the scene's Sun while the model is shown (an ambient light is left). Before, a model with its own light changed the number of lights in the scene the first time a ride showed it, and three kept a second program of the same code for each lit material (the clouds, the plain bodies) until it was let go: one more program at the end of a long run than at the start. The ride-along guide says a painter must not add lights and what to do to keep its look. The soak's warm-up now rides the ISS outside until its model is drawn, runs a clock past the satellites' speed limit and shows the package's own drawing once.
- **A short cross-fade when `light` changes to or from `lit`.** The Earth's night lights, and in the realistic view the direction of its light, move between the two looks over 300 ms instead of cutting, in the frames of one loop that ends by itself (nothing is drawn at rest). A reader who asked for reduced motion gets the cut. `stats.lightFade` is `{ mix, fading }`.
- **`path-priority` says whether a dot or a path is heard first** (MODULES-1332). Where a satellite's dot and a path lie under the pointer, `dots` (the default, as before) is the dot's, which at the Low level, with thousands of dots crowding a line, can leave a path unheard. `path-priority="paths"` (the property `pathPriority`) hears a path of the page's before a dot, except a dot of a satellite whose path is listed or that is chosen or ridden, which still wins. Press and hover follow the same order, and one press still has one meaning. On both elements.

## 0.49.0 - 2026-11-13

- **Satellites far from today, as an estimate** (MODULES-1296). `estimate-far` (the property `estimateFar`, or `createSatellites(sets, { estimateFar: true })`; off by default) keeps placing a satellite beyond 30 days from its elements: the same elements carried forward or back by the same SGP4 code, drawn lighter than a dimmed one, with `estimated: true` and `estimatedDays` (how far the moment is from the elements', in days) in `placeSatellite`, `satelliteInfo` and the details of `chikyu-satellite-click` and `chikyu-satellite-visibility`, and `stats.satellites.estimated`. The docs say what an estimate is (where it would be had its orbit not changed) and where it is worst (low orbits, months away). Never before an element set's `LAUNCH_DATE` (else the year of its `OBJECT_ID`) or after its `DECAY_DATE`, both new optional fields that `parseElements` keeps; a satellite SGP4 cannot carry that far, or brings below about 120 km, is left out and not counted as placed.

## 0.48.0 - 2026-11-13

- **Paths of a page's own, a quiet chosen orbit, and a hit test for a path line** (MODULES-1289). `selected-path="off"` (the property `selectedPath`) stops the package drawing the chosen satellite's own orbit; ring, name and ride stay. `setPaths(list)` (the property `paths`) draws up to 16 orbits at once, each `{ id, style }` (`id` a NORAD number or `group:index`, the last 16 kept), and `setPathStyles(table)` (the property `pathStyles`) changes the named looks `selected`, `hovered`, `favourite` and `path`, each a colour, a width of 0.5 to 8 px, an opacity and a dash: they differ by width and dash as well as colour. All the paths and the chosen orbit are one draw call, with a real width and dashes, and nothing is drawn at rest. `path-hit` (the property `pathHit`, 8 px, 0 to 40, off at 0; a touch has twice the reach, at least 16) makes `chikyu-path-hover` (a mouse) and `chikyu-path-click` (a press or a tap) say which path is under the pointer, `{ id, ref, style, x, y, distancePx, pointer }` with the same `ref` as `chikyu-satellite-click`; `pathAt(x, y, radiusPx?)` asks the same for any point. One press means one thing: a dot, then a path, then the sky. In a ride, the ridden satellite's own orbit is drawn in the `selected` look, and the hit test is off there unless `path-hit` is set. `stats.paths`. On both `<chikyu-space>` and `<chikyu-earth-realistic>`. The chosen satellite's orbit is now 2 px wide (the `selected` look; it was 1 px).
- **Three browser tests no longer fail on a saturated machine** (MODULES-1319). The full-screen at-rest and ride-look hidden-tab freeze tests wait for the page's own out-of-sight signal and count draws once they have held still; the ring test records the turn and its first draw in the page; the ride-size frame comparison holds everything that can arrive and leaves the stations' own orbit lines out. Tests only; the package is unchanged by them.

## 0.47.0 - 2026-11-13

- **The demo's Find box keeps a Japanese query.** A name in kana or kanji used to be dropped before the catalogue was asked, so `ハッブル` found nothing. It now asks the catalogue, and a satellite the package knows by a short name is listed by that name (Hubble, not only HST).
- **A satellite hidden by the Earth** (MODULES-1243). `placeSatellite` adds `occluded`: true when the line from the camera meets the Earth before the satellite, false in front, false at the limb, and false when the satellite is only behind the camera (`behind` is unchanged). The package's own satellite names, stations included, are drawn at 45 percent opacity with no ring while occluded, and restored as the satellite comes out. `dim-occluded="off"` (the property `dimOccluded`, on by default) leaves those names out. `earthHides` is the same test, for a page that places its own names.
- **A share of the Earth's turn on the space view** (MODULES-1223). `follow` on `<chikyu-space>` is a number from 0 to 1. 0, the default, holds the stars, which is what `camera="space"` already does, so a page that sets nothing changes nothing. 1 turns with the Earth. A number between takes that share. Changing it keeps the longitude under the middle of the view. `follow-ease` is how many seconds the change takes (0.4 when left out, 0 for none, and at once when the reader asks for reduced motion). It follows a fast, reversed or paused clock, and nothing is drawn while the clock is stopped and `follow` is not changing. A step of the clock longer than half a turn now keeps the Earth's real turn (a day is a full turn), so a fast clock moves the ground at the Earth's own rate. `centreLongitude` reads the longitude under the middle, and `shownTime` is the moment of the draw it belongs to.
- **The place under a point** (MODULES-1265). `placeOf(lon, lat)` in `@johnmorrisdotca/chikyu-earth/place` returns the country, a country the point is only near, the sea or ocean, the continent and the nearest city. The countries are the line globe's outlines, Natural Earth at 1:110m, indexed on a 15° grid. A point inside an outline is `country`. A point outside every outline and within 50 km (`PLACE_COAST_KM`) is `near`, because that coarse coast is the wrong place to claim a country. The sea is the nearest named sea, gulf, bay or ocean within its reach (`SEA_REACH_KM`); nothing is named when none reaches. The continent follows the country's group, named as on the sea-names list. Australia the country is that continent. A point at least 2,500 km closer to another continent's point (eastern Russia, French Guiana) uses the nearer one. Pacific island countries the outlines group as Oceania are `oceania`, which is not one of those seven. The nearest city is the caller's lists, the same three tiers as `here-city`, and towns under 100,000 only when `towns` is passed. `alongTrack` reports each change of country, nearby country or sea along a ground track, at the sample that entered it. A call is about 0.14 ms once the grid is built.
- **A faint orbit while the pointer rests on a satellite** (MODULES-1234). On `<chikyu-space>` and `<chikyu-earth-realistic>`, resting on a satellite shows its name and draws its orbit at about a third of the brightness of a chosen satellite's orbit (`hover-path`, on when `names-on-hover` is on; `hover-path="off"` turns the orbit off, `names-on-hover="off"` turns the name off). The colour and the opacity are `--chikyu-hover-path` and `--chikyu-hover-path-opacity`. The path is worked out once from the elements already loaded. It fades out when the pointer leaves (at once when the reader asks for reduced motion). A chosen orbit is unchanged. A touch does not rest, so nothing new is drawn, and nothing is drawn while the pointer is still and no satellite is under it.
- **Frame the ridden satellite, zoom inside a ride, and a viewpoint switch that fades** (MODULES-1316). `ride-model-share` (property `rideModelShare`, option `modelShare`, 0.02 to 1.2: the model's radius as a share of the picture's height; 0.22 along the way it goes, up from 0.17, 0.17 above, 0.10 looking down) and `ride-model-seat` (`rideModelSeat`, `modelSeat`, 0.5 to 1.4: where its middle sits from the top; 0.86 along the way it goes, down from 0.90) frame the model, so with the defaults the body and a good part of a wing are in view in Ride along, and a page can go to a close framing (1 and 1). `ride-zoom` (`rideZoom`, 0.5 to 40; the field of view is 60 degrees over it, the least `rideFov` now allows is 1.5) zooms in a ride, and `stats.ride.groundKm` (`{ across, tall }`, kilometres of ground below the satellite) says how much ground the picture spans. All are settable while riding, glide in 0.4 s (a jump under reduced motion), cost one draw for the change and nothing at rest. Switching `ride-viewpoint` between `outside` and `inside` now fades the model over 0.4 s as the camera closes on it (and back), and `stats.followModel` reports `share`, `seat` and `weight`.

## 0.46.6 - 2026-11-13

- **A beam from the chosen satellite to the ground below it** (MODULES-1309). `beam` on `<chikyu-space>` (off unless set; the property `beam`) draws a soft, additive cone of light from the satellite marked with `selectSatellite`, or the one ridden, down to its footprint on the ground: a lit ring and a faint fill, the circle from which the satellite is above `beam-elevation` degrees (25), worked from its height (`footprintAngle`, `footprintKm`), cut off by the limb, in Ride along and Ride above as well. `beam-cells` (up to 91) adds spot cells in a hexagonal pack, each with a thin shaft of light (an illustration, not any operator's plan), `beam-cell-size`, `beam-color` and `beam-strength` set the look; `stats.beam` says the footprint's radius in kilometres. It is part of the draw that moves the satellite: nothing at rest, nothing rebuilt on a clock step, no shimmer. Guide: `docs/guides/beam.md` (and its Japanese twin), and a "Satellite beam" button in the demo.

## 0.46.5 - 2026-11-13

- **The ridden satellite's model shrinks as a ride above it rises, and the package's drawings are better** (MODULES-1306). In a ride above (`view: "above"`) the model was a fixed 17 per cent of the picture at any height, so from 6,000 km it was a huge block. The new option `modelSize: "distance" | "fixed"` (attribute `ride-model-size`, property `rideModelSize`; `distance` is the default) keeps the model at that size up to 150 km, shrinks it as one over the height, lets it down smoothly from 1,000 km to nothing at 2,000 km, where the ordinary mark (ring and name) takes over (`aboveModelShare`, `MODEL_HANDOVER_PX`); `fixed` is the old size at every height. A page's painter is told the size through `update({ radiusPx })` and `stats.followModel` reports it. The chosen satellite's ring and name stay off its model in both modes while it is drawn and return at the hand-over or when the ride ends (`modelOver`, `stats.satellites.selectedRing`). The generic drawings are redrawn with framed thin panels, a bus with a radiator and a camera, a dish, a long panel for a constellation, and a new `cubesat` kind (FLOCK, DOVE, LEMUR, SPIRE and similar names); every part of every kind is inside the model's disc (the flat kind's panel was not, which was the stray slab), tested in `test/generic-satellite.test.ts` and, pixel by pixel outside the reported box, in `e2e/ride-size.gl.ts`. Names under the model: while the model is drawn the package's own names (places, cities, seas, countries, stars) keep clear of its box, and `chikyu-ride-model` (`detail: { box, radiusPx, x, y }`, `box` null when none) tells the page when the box has moved by more than a pixel or has come or gone, for its own labels. **Behaviour change:** `distance` is the default; set `ride-model-size="fixed"` for the old size (upgrading guide).

## 0.46.4 - 2026-11-13

- **Cloud-free ground from NASA's Landsat mosaic** (MODULES-1263). `tiles-finer="gibs"` now reads NASA's Landsat annual true-colour mosaic (`Landsat_WELD_CorrectedReflectance_TrueColor_Global_Annual`, 30 m, no cloud, land only, the year 2000) instead of a daily picture, which was often solid cloud over the ground. It is off unless a page sets it. Streets, fields and rivers show at 150 km where our level 5 is a blur. The daily MODIS Terra picture stays as `tiles-finer-layer="today"`; `landsat` is the default's short name. The mosaic has one picture a year, so no day is searched for; `tiles-finer-date` names another year it has (1984, 1985, 1988 to 1990, 1998, 1999). Where it has no data (the oceans, Antarctica, the far north, a tile that is all black) our own tiles stay, silently. Tiles now carry transparency: black and nearly black pixels (no data, and the mosaic's sea) are clear, so our blue sea and our picture show through, and a daily picture's black wedges between passes are no longer drawn black. The colours are brought to the look of our own pictures by a gain fitted over six places on land (0.76, 0.66, 0.55), so the finer land does not look like a sticker. The credit line adds the Landsat data's own line. The grid support takes the 31.25 m matrix (levels 0 to 11). It is old (2000) and made of separate scenes, so a straight scene edge shows here and there.

## 0.46.2 - 2026-11-13

- **Finer than the package's own tiles, from NASA's imagery service** (MODULES-1263, step 2). `tiles-finer="gibs"` on `<chikyu-earth-realistic>` and `<chikyu-space>` (off unless set) reads a daily true-colour picture in the browser, and only when the view is closer than the tiles already underneath. The layer is MODIS Terra (the VIIRS layer has no days after 2026-11-02), and the day is the most recent one with a picture: the page asks for one tile, the one under the middle of the view, for each day in turn from the UTC day before the one on show back at most 10 days, one at a time, and keeps the answer for the session; if no day answers it says nothing and keeps the package's own tiles, and it never fetches the capabilities file. A day before the layer's first day asks nothing. The clouds are left in, and a daily picture has black wedges between satellite passes: a wholly black tile is not shown, a partly black one is. A page can name the layer and the day rule (`latest`, the default, `previous-day`, `shown` or one day). A tile that is missing, black, or still out after two seconds stays out, the coarser picture remains, and that tile is not asked for again while it is in view. The 48 tile and 72 MB limits, and six requests at a time, are unchanged. A tile fades in over a third of a second, or at once for a reader who asked for less motion, and then nothing is drawn for it. The credit line shows NASA's acknowledgement while those tiles are on screen. `gibsTiles` is the same source from `@johnmorrisdotca/chikyu-earth/door`. A map source may now name its own grid; the package's own folder is unchanged.

## 0.46.1 - 2026-11-13

- **Ride along keeps the satellite at the bottom, large, sharp and steady** (MODULES-1303). In an outside ride along (`view: "from"`, `look: "horizon"`) the satellite's middle is at 90 per cent of the picture's height and its model is drawn 17 per cent of the height in radius, so it sits at the bottom middle with part of it below the bottom edge; the page's model is told that real size (`update({ radiusPx })`) so it can be drawn sharp. Looking down (Ride above) it is at the centre. Its attitude is the track frame (long axis along the way it goes, top straight up) at every frame; a moment with no level speed keeps the last good frame instead of dropping the model. The ridden satellite's model does not depend on the satellite layers (`showSatellites`, a focus that hides the others), and its ring and name are left off, since they would cover it. `stats.followModel` gains `radiusPx`, `box` and `axes`. The page must call `setSatellitePainter` with its models before `ride`, and `ride(ref, { view: "from", look: "horizon" })` (outside is the default); the satellite must stay in a group set with `setSatellites` (removing the group ends the ride). `e2e/ride-model.gl.ts` holds the tests.

## 0.46.0 - 2026-11-13

- **A satellite's streak keeps its short look at any clock speed and any Earth size** (MODULES-1282). Above 60 times real time each satellite is a streak along its orbit for the stretch one frame spans; at 10 minutes a second that is a few millimetres, but at an hour a second it was a long straight line across the globe, the stretch also grew when frames came slowly, and on a small Earth the streaks and the dark rim of the dots stayed as long and heavy as on a large one, so thousands of them blackened it. Now a streak is never longer than the smaller of 0.025 of the Earth's drawn radius (about 160 km of orbit, what a low satellite covers in a frame at 10 minutes a second, so it shrinks in proportion as the Earth is drawn smaller, down to a dot) and `satellite-streak-max`, new on `<chikyu-space>` and `<chikyu-earth-realistic>` (the property `satelliteStreakMax`), a ceiling in CSS pixels, 8 when the page says nothing; `off` or `0` draws the whole stretch, as before. It is a length on the screen and not seconds of travel, so a low and a high satellite are drawn equally long. A streak is also always one frame at 30 a second, whatever the frames really take, so its length does not depend on the frame rate; it ends at the satellite and points back along its orbit. The marks lose weight as the Earth is drawn smaller: from a drawn radius of 150 pixels down to 40 the streaks are fainter and the dark rim of the dots fades until it is gone, at normal speed too, and a crowd of satellites that would cover more of a small Earth's near side than a limit (6% for dots, 35% for streaks) is drawn fainter in proportion, so 16,000 satellites leave a small Earth no more washed than a whole one; a whole Earth is drawn as before. `stats.satellites` has `longestStreakPx`, `streakCapPx`, `weight`, `fade` and `earthPx`; `Satellites.arc` takes the cap, in Earth radii, as an optional last argument.

## 0.45.0 - 2026-11-13

- **Sharper Earth tiles: day level 5 and night level 4, from NASA's 500 m maps** (MODULES-1263). `scripts/make-earth-tiles.py` builds the day map's level 5 (32768 × 16384, 2,048 tiles, 22.8 MB) from the full-resolution Blue Marble: Next Generation (86400 × 43200, eight 21600 × 21600 panels) and the night map's level 4 (16384 × 8192, 512 tiles, 2.3 MB) from the full-resolution Black Marble 2016 colour map, so the whole pyramid is 3,412 files and 35.4 MB (it was 852 and 10.3 MB). Levels 0 to 4 of the day map and 0 to 3 of the night map are unchanged (the same code and sources; tiles sampled from every level are identical to the published ones). The panels are resized one panel at a time with their neighbours' edges around them (the far panel across the antimeridian), so the 11 GB map is never in memory (about 4 GB at the most) and the tiles equal, to the pixel, a resize of the whole map; `selftest` checks that on a made-up map, joins, antimeridian and poles included. The build takes about 3 to 4 minutes and downloads 688 MB once; the sources and their SHA-256 are in `scripts/earth-tiles-sources.json`. A level is still never built from a source that does not fill it. The folder source (`earthTiles`, what the `tiles` attribute makes) named the keys of a tile from the package's levels 3 and 4 alone, so with a level 5 in the manifest the view chose level 5 and then asked for level 4 tiles: it now names them from the levels its manifest has (the package's 3 and 4 before the manifest is read or where there is none), and a test holds it. The zoom limit the element sets when it finds the tiles is no longer fixed: it is now as many times 5 as the finest day level is wider than 4096, so 40 for a set that reaches level 5 (it was fixed at 20; a set that stops at level 4 still gives 20); it is only raised, so a source with fewer levels added later does not lower it and send the view back to fit. The 48 tile and about 70 MB limits hold at the finest level (`e2e/tiles.gl.ts`). `pages.yml` keeps NASA's source files between runs while `scripts/earth-tiles-sources.json` is unchanged (a change to the script alone downloads nothing), and the built tiles while the script and the sources are unchanged. `earthTiles().need()` now names keys from the manifest's own levels (a detail of 4096 or less can name levels 0 to 2 where it named level 3 before). Without `EARTH_TILES_ALL=yes` the script (`pnpm tiles`) makes only day 0 to 4 and night 0 to 3 from the two whole pictures and does not download the panels, and its output is what was published before, byte for byte (the manifest and 80 sampled tiles compared); a download is tried three times (after 5 s and 20 s) before the script stops. The Pages site publishes day levels above 4 and night levels above 3 only when the repository variable `EARTH_TILES_ALL` is `yes` (`scripts/site.ts`): a loader up to 0.43 that reads a manifest with a level 5 wants it and fetches the level 4 tile for each quarter of it, a wrong picture on every page that reads the demo's tiles (the website's hero does), so the variable is set once those pages have the newer loader. Guide, its Japanese twin and NOTICE updated.

## 0.44.0 - 2026-11-13

- **A ride shows the satellite** (MODULES-1236). Riding a satellite put the camera at it, so the reader never saw the thing ridden. `ride` has a new option `viewpoint: "outside" | "inside"`, with the attribute `ride-viewpoint` and the property `rideViewpoint` on `<chikyu-space>` (and `Riding.viewpoint`), **`outside` by default**: with `view: "from"` the camera is 25 km behind and above the satellite looking along (the satellite a little below the middle), or 25 km straight above it looking down (the satellite at the middle), with the same look-around as before. A satellite the page has no model for is drawn from a small drawing of the package's own by kind (`satelliteKind`, `genericSatellite`: a bus with two panels, a dish for a communications satellite, one long panel for a constellation, modules for a station), about a fifth of the picture's height across and so not to scale (the demo says so under the picture). `inside` is today's ride, camera at the satellite and no drawing. `outsidePose` (pure) is the camera. Switching is one eased glide that keeps the ride and the clock; nothing is drawn at rest, and 20 switches leave the GPU's objects flat (`e2e/ride-outside.gl.ts`). **Behaviour change:** a ride of a satellite is now outside unless asked otherwise, and `follow` and `above` draw the package's drawing instead of a dot where the page has no model; see the upgrading guide. A body is always ridden from inside.
- **Plain catalogue rows, found in Japanese too** (MODULES-1216). `catalogueRows()` in `@johnmorrisdotca/chikyu-earth/satellites` returns one row for every group and every satellite, with English and Japanese names, for a page to index. The Japanese name is the short name where the package has one (the ISS, Tiangong as `天宮`, Hubble as `ハッブル`); otherwise it is the English name, which is the same spelling in Japanese (Sentinel-2A). `aka` lists the catalogue's own other names (HST for Hubble, and a designation written in parentheses). `findInCatalogue` also matches a Japanese name and a group's Japanese label as typed, folding only case and width, and an English or numeric query returns the same entries as before.
- **Names of oceans, seas and continents** (MODULES-1230). `sea-names` on `<chikyu-earth>`, `<chikyu-earth-realistic>` and `<chikyu-space>` (off by default; the property `seaNames`) names the oceans and the continents while the Earth is small on the screen, and the seas, gulfs and bays once its radius is at least 280 pixels (`SEA_RADIUS`). Water is written with space between the letters. A city name is placed first and keeps the space where only one name fits. Nothing is drawn again at rest. `seaNamesFor` and `layoutSeaNames` are in `@johnmorrisdotca/chikyu-earth/realistic`.
- **A here marker can name a town under 100,000** (MODULES-1212). After the capitals, the cities of a million and the cities of 100,000 have answered, `here-city` reads the smaller cities of the nearest city's country, and of one more country when that country also has a city of those three tiers within the limit. Each country is one file (`citiesOf`), loaded once. A nearer town within the limit wins. **The optional peer `@johnmorrisdotca/kuni` is raised from `>=1.6.1` to `>=1.8.0`**, the first version with `citiesOf`; a page that turns `here-city` on needs kuni 1.8.0 or later (wakusei-planets and uchusen-rockets, the family packages that use this one, do not depend on kuni). The towns come from kuni's own cities (NOTICE.md records the source). Nothing is loaded while `here-city` is off, and nothing is drawn again at rest.
- **The held-clock check counts in one turn** (MODULES-1272). `e2e/date-play.demo.ts` took the log of `chikyu-timechange` in one call and gave the date in others, so a one-second tick between them was read as a second telling (seen once on the desk Chromium). The length is taken in the same turn of the page that gives the date; the test still proves once, held, and nothing more. No change to the package.

## 0.43.0 - 2026-11-13

- **One satellite group at a time** (MODULES-1215). `focusSatelliteGroup(name, options)` on `<chikyu-space>` and `<chikyu-earth-realistic>` shows one group that has been set and deals with the others: `others` is `"dim"` (the default; the same dimming an old element set uses, so no new object) or `"hide"`. `frame` (true by default) pulls the camera back with the view's own zoom until the group's orbits fit. The distance is the greatest apogee, from mean motion and eccentricity, and it stops at 8 Earth radii. `null` restores each group's own shown state and the camera. A group that has not been set returns `{ ok: false, reason: "not-set" }` and changes nothing. `focusedSatelliteGroup` is the name or `null`. `satelliteGroups` adds `emphasis` and `placed`, and keeps `count`. `chikyu-satellite-focus` is sent with `{ group, count }` when the choice changes. The demo has a row, "One group". Nothing is drawn at rest.
- **A ring appears when the satellite comes into the picture** (MODULES-1213). `ringSatellites` keeps the satellites it was asked to ring. One that is outside the picture gets its ring on the first later draw that shows it, and nothing is drawn at rest just to wait. `placeSatellite` adds `edge` (`"top"`, `"right"`, `"bottom"`, `"left"` or `null`) and `behind` (true when the satellite is behind the camera), and no longer answers `null` for a satellite that is merely out of the picture: it returns the place outside the picture, so check `.visible`.

## 0.42.0 - 2026-11-13

- **The "you are here" marker can take the nearest city's name** (MODULES-1077). `here-city` on `<chikyu-space>` and `<chikyu-earth-realistic>` (off by default; the property `hereCity` is `false`, `true` or a number of kilometres) names each `kind: "here"` place with the nearest city within 100 km (`HERE_CITY_KM`; a number on the attribute is that limit, at most 20,000). The name follows the page's language. The cities are kuni's capitals, the other cities of a million and the others of 100,000, loaded only when this is on and a `here` place is set; a smaller town keeps the label the page gave. `places` itself is not changed. Nothing is drawn again at rest.
- **Satellites nearest a place, a point in the sky, or another satellite** (MODULES-652). `nearest`, `within` and `closeApproach` in `@johnmorrisdotca/chikyu-earth/satellites` answer from the group's SGP4 positions (`exact`), once per call and never on a timer. `by: "space"` returns kilometres with a rough uncertainty (1 km at the epoch, and 1 km more for each day the elements have aged). `by: "sky"` returns the angle in degrees. `closeApproach` samples the span and then refines the closest moment to a tenth of a second (the closest sample alone was 172 km off a true 100 km in the test, two satellites 7 km/s apart); its uncertainty is the elements' own, not the sample step. A satellite straight overhead is its height away. `ringSatellites` on `<chikyu-space>` rings the ones a page names. One call places each satellite once: about 0.15 ms for one, so a few thousand is on the order of a second.
- **Distance and the route between two places** (MODULES-679). `route` on `<chikyu-earth>`, `<chikyu-earth-realistic>` and `<chikyu-space>` (absent by default; the property is the two places or `null`) draws the line between them. `routeInfo` gives the WGS84 geodesic (`kilometres`, Vincenty), the great-circle distance on a sphere of 6371.0088 km, the initial and final bearings, and a flight time at 900 km/h. The line is split at the date line. Nothing is drawn again at rest. There is no flat world map in this package: the line globe is the flat drawing, and `routeRuns` is there for a page that draws its own.
- **Bodies are made only when they are big enough to see** (MODULES-1192). `<chikyu-space>` made the painter's drawing of the Sun, the Moon and every planet in every view, with their mapped pictures, however small or far from the view. It now asks the painter for a body only when the body is in the view and at least 6 CSS pixels across its radius (`BODY_MAKE_PX`); a smaller one, or one out of the view, is a plain sphere of the right colour (the Moon is the view's own Moon), and a body that has shrunk below 3 pixels or left the view is let go of its pictures after four seconds (`BODY_KEEP_MS`), so one that comes and goes is not made again and again. Measured in the default Earth view (Nov 10, centred on -100,40): the pictures loaded went from 10 (the Sun, the Moon and the eight planets, 150,446 bytes) to 1 (the Moon, 16,974 bytes); `stats.bodies.mapped` says how many drawings are the painter's. wakusei-planets' `credit` therefore narrows by itself: an Earth view with no CC BY body in it shows no CC BY line, Jupiter adds Nestaeric's credit, the Sun adds Solar System Scope's, and no line is written while the painter holds nothing. Nothing is drawn at rest and the GPU objects are flat across moves. Tests: `e2e/space-bodies.gl.ts`, `e2e/space-credit.gl.ts`, `e2e/space-full.gl.ts`.
- **Reduced motion gathers the pictures that arrive** (MODULES-1195). Since bodies are made only when big enough (MODULES-1192), a body that came into view made its pictures arrive one by one, each asking for a draw: a reader who asked for reduced motion got about 8 draws in half a second, and 1.75 draws a second riding the ISS at 60x against the one step a second the clock makes. The Earth's maps, its finer tiles and a body's pictures now ask for at most one draw a second (the first after a quiet second at once, those that follow when the second ends), and none while the clock steps at least once a second, whose next step shows them; without reduced motion a picture is drawn as soon as it arrives, as before. `e2e/ride.gl.ts` measures from the start of the ride again (the three seconds `dbae5d8` let pass first are gone): 1.25 draws a second, where the code of 0.42.0 reads 1.75.
- **The realistic Earth's first draw is waited for, not 5 s** (MODULES-1194). `e2e/air-visible.gl.ts` gave the first draw 5 s and timed out on a loaded Mac; it now waits on the element's own draw counter, within the test's own time. Held back by 8 s in the page, the old wait fails at 5 s and the new one passes. A test change only; the package is unchanged.
- **The view says when its pictures are still to come** (MODULES-1195). `stats.bodies.pending` is how many pictures asked of the painter have not yet arrived, and one more while a gathered draw waits for its second. Five realistic-Earth tests (`drag`, `ride-face`, `sky-names`, `sky-pick`, `space`) read "rest" after a fixed wait, and on the CI image the pictures of a body that had come into view arrived after it (an extra draw at rest, a picture taken with a plain sphere where the other had its map); they now wait until `pending` is 0 and the draw count has held for longer than the gather window.
- **The soak counts what the same view holds, once it has settled** (MODULES-1192). `e2e/space.soak.ts` wanted the GPU objects at the end equal to those at the start, but bodies are let go four seconds after they leave the view and the opening view comes out at 63, 66, 69 or 72 buffers and 8 or 9 programs depending on the path to it, each steady for five seconds. It now returns to the opening view (orbits and labels as it opened), stops the controls' Auto-turn, waits until the element's own counts of the bodies it holds (`stats.bodies`) and of the programs, buffers and textures have not moved for five seconds, and then asks that no texture or program is more than at the start and the buffers are within one geometry (3 buffers, 4 GPU objects) of it (a body let go without its geometry disposed takes the soak from 60 textures to 87 and from 330 GPU objects to 416). The first form of this wait still failed in CI (17 textures against 9, MODULES-1198): the demo's Auto-turn kept turning the Earth's view while it settled, and Jupiter and its moons came into its background at some yaws, so the count depended on the yaw it was taken at. Not a leak and not a late release: the bodies are made and let go as designed. The first draw is waited for up to 30 s, not 5 s (a run on a loaded Mac timed out there, as in MODULES-1194). The freeze test waits one second more after the picture opens, for the gathered draws of a reader who asked for reduced motion. A test change only.

## 0.41.0 - 2026-11-12

- **The credit under the space view follows the painter's credit** (MODULES-1158). wakusei-planets' painter (0.39 and later) carries `credit: { en, ja }` for the pictures of the bodies the view holds, and the view makes the Sun, the Moon and every planet in each view, so the line names all their pictures in an Earth view as in a Jupiter view (more than is big on the screen is safe, less would be the fault); so `<chikyu-space>` reads it again whenever a body drawing asks for a redraw (a picture arrived, a window of tiles changed, a body was made) and writes the line only when its text changed, never at every frame; no credit, no line. Pass the painter as it is: `{ ...painter }` reads `credit` once. A page that writes the credit itself (`bodies-credit="off"`) is sent `chikyu-bodies-credit` when it changed, with `detail` `{ en, ja }` or `null`. The demo drops its own `PLANET_CREDIT` and uses the painter's; its full-screen page follows the event. Tests: `e2e/space-credit.gl.ts` (a painter of the test's own; and wakusei-planets' own, wrapped to log the bodies made and the reads of its credit after they are made: every body is made, the Sun's and Jupiter's CC BY 4.0 credits are in the line, and it is the painter's credit as it is now). Lazy making of the bodies out of view, which would narrow the credit, is a separate ticket. The credit line is at most four lines high and scrolls: with every body made, wakusei-planets' credit is some twenty lines and covered the whole view (it hid the ground from the drag, air and follow tests in CI).

## 0.40.0 - 2026-11-12

- **Names of different layers never overlap** (MODULES-1072). On `<chikyu-space>` and `<chikyu-earth-realistic>` each layer placed its names alone: city names ignored the places, the markers' labels ignored the places' names, and star names ignored every layer's names and rings, so a name could sit over another layer's. The layers now lay out in a fixed order, each keeping clear of the boxes of those before it: the places' names, rings and marks with the ringed satellites, then the markers' labels, then the cities' names, then the stars' and constellations' names (the countries' names, which already kept clear of the others, come after the cities'). A star whose name box or ring touches an earlier box is left out and the next star is named. The order is the draw's: the realistic Earth's places are laid out before its markers and the sky after the cities, as the space view's sky is after its cities. `OverlayHost` has an optional `taken()` (the places' boxes, which `attachMarkers` reads), `CityLayoutOptions` has `taken`, and a satellite's ring is among the boxes the places take. Boxes are handed over when names are laid out, which is when the view changes; nothing is laid out or drawn at rest. Tests: `test/label-overlap.test.ts` and `e2e/label-overlap.gl.ts`.
- **A glide is counted on the page, not polled** (MODULES-1190). `e2e/ride-above.gl.ts` watched for the camera's glide into the above view by polling `stats.ride.gliding`, and a short glide could be missed (seen in CI on 2026-11-12). The page now counts each glide at every animation frame and the test reads the count; it fails when a view change never glides. A test change only; the package is unchanged.

## 0.39.0 - 2026-11-12

- **The painted trail follows the orbit at any clock, and costs nothing until it is used** (MODULES-1188). A month laid down at once, or a fast clock, took samples too far apart and drew chords across the map: samples are now at most a third of a trip apart. A clock run backwards laid down nothing for the older end, so the trail shrank: it now fills it in. A coverage swath over the date line was cut at the edge of the map: it now wraps. Switching to a satellite that paints nothing left the old picture on the globe: the cleared picture is sent. The trail's two megabytes and its picture on the graphics card were made in every view, painting or not: they are made when the first satellite is painted, and `clearPaint()` gives them back.
- **Sharp ground when riding above a satellite, and the model there** (MODULES-1184). `<chikyu-space>` takes `tiles` (attribute and property, as `<chikyu-earth-realistic>` does) and lays the finer map tiles over its Earth: the level is chosen from the pixels a unit of ground takes under the camera, so from 150 km above the ISS the ground is the finest level (4) and from 3,000 km it is level 3, where it was one blurred 4096 picture; only the tiles under the camera are loaded (at most 48, freed after four seconds), a view of the whole Earth asks for none, and nothing is drawn at rest. `stats.tiles` has the tile set's state and `chikyu-tiles` is sent once when a set has been read. `TileCamera` has an optional `perspective` (`TilePerspective`, new in `/realistic`) for a camera with a real place, which `tilesInView` and `pointOnEarth` use in place of the disc; a disc is read as before. The satellite's model (`setSatellitePainter`) was already drawn in the `above` view as in `follow`; the tests now say so at 150 km (`e2e/ride-above-model.gl.ts`, `e2e/ride-above-tiles.gl.ts`). The demo's space view uses its tiles.
- **A press on a named star or a constellation figure tells the page** (MODULES-1179). `chikyu-sky-pick` is sent on `<chikyu-space>` and `<chikyu-earth-realistic>` when a reader presses or taps one. A star's detail is `{ kind: "star", hr, name, designation, x, y, pointerType }` (`name` as drawn, `x` and `y` CSS pixels inside the element, `pointerType` `mouse`, `pen`, `touch` or `keyboard`). A figure's detail is `{ kind: "constellation", abbreviation, pointerType }`. Each named star and each figure in view is a button, so a keyboard reaches it and Enter picks it, and the pick is announced; the keys `C` and `Shift`+`C` (the next and the previous figure) send it too (`pointerType` `keyboard`). Nothing is drawn at rest.
- **A build without the sky cultures** (MODULES-1185). `@johnmorrisdotca/chikyu-earth/space/no-cultures` and `@johnmorrisdotca/chikyu-earth/realistic/no-cultures` are `<chikyu-space>` and `<chikyu-earth-realistic>` with no sky culture but the IAU's: nothing under `hoshi-stars/cultures` is imported, so a site's bundler no longer needs a stub for it, and `constellation-culture` is `iau` whatever a page sets (one warning). The default entries are unchanged: they bring in `western`, `japanese` and `chinese`, a dynamic import each. How: the elements' code moved to `element-base.ts` in each folder; `space/element` and `realistic/element` are now that code plus `sky/cultures.ts`, which sets the table the sky layer reads (`setCultureLoaders`). A test reads each entry's imports and finds no `hoshi-stars/cultures` in the two new ones and all three in the default ones, and the usage test bundles the new entries with every such import refused.
- **The demo takes every planet picture at the widest width again** (MODULES-1175). The demo's `wakusei-planets` is `^0.38.0`, which stops at the widest picture its package ships when a page gives a `textureBase` and no `farBase`, so the demo's cap of 1024 on the painter (and its 404s for 2048) is gone.

## 0.38.0 - 2026-11-12

- **Paint a satellite's path on the Earth** (MODULES-1167). `paint` on `<chikyu-space>` and `<chikyu-earth-realistic>` is `{ id, length, swath }`. `id` is a NORAD catalogue number or `group:index`. `length` is `1d` (the default), `1w` or `1m` of simulated time. `swath` is `track` (the point under the satellite, the default) or `coverage` (the ground where the satellite is at least 10° above the horizon, from its height). `clearPaint()` takes the trail off. Changing the satellite clears it. The trail is one equirectangular texture on the globe. It is stamped only while simulated time moves, one upload a frame, and nothing at rest or while painting is off. A part older than `length` fades out. The date line and the poles are split so the line does not cross the map. The demo's satellite card has Paint, Clear, and 1 day, 1 week, 1 month.
- **No hitch from the once-a-second satellite pin** (MODULES-1171). Above 60 times real time each satellite's place is placed by SGP4 about once a second; that ran for the whole group in one frame (about 1.6 ms for 2,251 satellites, about 12 ms for 17,000). It is now spread over the frames: a slice of the group each frame, in proportion to the time the frame took (a thirtieth at 30 frames a second), each satellite turned from its own pin time, so every satellite is still pinned about once a second and no frame runs SGP4 for the whole group. A jump of the clock (a date typed in, a scrub) still pins the whole group at once, so a place is never turned across days. `Satellites.pin(ms, first?, count?)` takes a range (the whole group by default, as before) and keeps each satellite's pin time; an eccentric orbit, which `arc` places by SGP4 itself, is no longer pinned too. Measured on the update of a satellite group at a steady 60 and 30 frames a second, 17,000 made-up satellites, three runs each, before and after: at 600 times the 99th percentile of the update fell from 8.6 ms to 4.4 to 5.2 ms and the longest from 12.7 to 15.5 ms to 6.3 to 8.4 ms; at 3600 times from 8.4 to 9.0 ms to 5.9 to 6.1 ms and from 9.5 to 17.8 ms to 6.4 to 7.9 ms. The 90th percentile rose by about 0.5 to 0.8 ms (2.3 to 3.8 ms to 3.1 to 4.4 ms), since the same work is now done a little every frame. The demo's own catalogue, all 14 groups, is 4,084 satellites.
- **Place dots cost less, and a missing ring is told only when a place is left out** (MODULES-1165). The fallback circles (when the three.js parts have no `Points`) no longer ask for a compositor layer each, skip a move that did not change, and are projected once a frame. They fade at the Earth's edge and are dimmer at night, as the rings in the picture are. `stats.places.sprites` counts only the rings in the one draw call (0 in the fallback); `stats.places.dots` counts the circles drawn in the page instead. `chikyu-places-unavailable` is sent once, and only when places in sight had no room (`omitted`), not merely because `Points` is missing; its `detail.reason` names `PLACE_DOTS` and `detail.omitted` says how many places had no room. A browser test checks that `place-groups` and `placeGroups` turn the gathering off and on as each other's mirror, in both views.
- **The passes page's world map has half the points** (MODULES-807). Its 720 by 360 map drew all 10,000 points of the country outlines, more than it can show, and in Chromium drawing on a software GPU the map held up the page's frames after it opened. Each ring is now thinned in the browser to within half a map unit of the original (Douglas-Peucker, less than a pixel at the size the map is shown), and the path is written to one decimal: about 5,300 points and 58 KB, from 10,371 and 112 KB. Measured on the Mac in Chromium with SwiftShader and GPU rasterization (three opens each, the longest time with no frame after the page opened): desk 1.4, 2.2 and 0.36 s with the full outline, 0.29 s each with the thinned one, 0.16 to 0.19 s with no map at all; phone 0.43 s once with the full outline, under 0.07 s otherwise. NOTICE.md says the map is a derived drawing of Natural Earth's outlines.

## 0.37.0 - 2026-11-12

- **A satellite's owner country as an ISO code** (MODULES-1112), for a page that puts a flag on a satellite card. `satelliteInfo` and the click event's `info` have `ownerCountry`, an ISO 3166-1 alpha-2 code (`CN`, `US`, `PK`), when the elements carry an owner code (`COUNTRY_CODE` or `OWNER`) and the owner is one country. An organisation (`ESA`, `ISS`, `ITSO`, `SES`, `GLOB`, `EUME`, `NATO`, `AB` and the like), several countries, an unknown owner, or a code the list does not give to one country (`CIS`, the former Soviet registration) has none, and the field is left off. New in `@johnmorrisdotca/chikyu-earth/satellites` and `/catalogue`: `ownerCountry(code)` and `OWNER_COUNTRIES`, every code of the catalogue's owner list, each row checked. Data only: no flag, no new dependency.
- **City names can be taken off and put back, and a font is measured once** (MODULES-1097). Removing `<chikyu-space>` or `<chikyu-earth-realistic>` while a tier of city names is still loading no longer leaves a second canvas and a second names box when it is put back: a load that arrives after the layer is gone does nothing, and neither does its error. The font used to measure the names is read again only when the style, the size or the language changes, not on every draw. A font that finishes loading after the space view has measured its body-name boxes is measured again.
- **Satellites stay on the picture when the clock runs faster than a minute a second** (MODULES-860). Above 60 times real time they were hidden, because two SGP4 samples would be too far apart to interpolate. Each satellite is now a short streak along its orbit for the stretch one frame spans: one SGP4 sample about once a second, then turned by its mean motion, on `<chikyu-space>` and `<chikyu-earth-realistic>`. `satellite-tint="orbit"` (off by default) colours them by orbit class. Dots grow as the Earth is drawn larger and shrink as it is drawn smaller, and a dark rim keeps a pale dot readable on the bright ground. `stats.satellites.placed` is how many are drawn, `segments` how many streaks, and `epochMs` the newest element set's moment. New on `Satellites`: `pin`, `arc`, `classColour` and `newestEpochMs`; `tooFast` stays true above 60 times, so a page that read it as "hidden" should read `placed` or `segments` instead. **A page that hands over its own three.js parts (`setThreeLoader`) should add `LineSegments`** for the streaks (the demo's `three-subset.ts` has it); without it the satellites above 60 times are dots alone, with one console warning, and nothing else changes. An orbit with an eccentricity of 0.02 or more (a Molniya, a transfer orbit) is placed by SGP4 itself on every frame there, because turning it at the mean motion put it kilometres off its path.
- **Face a way again while riding** (MODULES-1105). `face("ahead" | "behind" | "left" | "right" | "down" | "up")` turns the camera there in half a second (at once when the reader asked for less motion) and keeps the zoom. Ahead is along the way it goes, behind is the opposite, left and right are across that way, down is straight at the Earth and up is straight away from it. In the above view, down looks straight down at the satellite. `facing` is that way until the view is turned or tipped, and `chikyu-ride-face` is sent when it changes. Keys, while the element is focused: W, S, A, D, R and F. The arrow keys stay with the view controls. The demo has a Face row and the address keeps `face`.
- **Facing, made safe** (MODULES-1105 review): following a planet or the Moon there is no way to face, so `face()` answers `false` and nothing is told; a held key's repeats do not start the glide again; a key typed in a field inside the element, or in editable text, is left to it.

## 0.36.0 - 2026-11-12

- **kazoku-ui 0.41.0, a dependency of this package** (`^0.38.1` to `^0.41.0`, for MacBook browser runs in CI's own Playwright image): a page that installs chikyu-earth now gets kazoku-ui 0.41. What it changes for this package's elements: in Safari a trackpad pinch over a view zooms the view and no longer the whole page (kazoku-ui 0.40.2); `<kazoku-view-controls>` writes a pace, direction or axis read from the address back to its attributes (0.40.0, 0.40.1), which matters only to a page that reads them. The elements' own attributes, events and defaults are unchanged.
- **The planets and the Moon in the space view have their pictures** (MODULES-850). With wakusei-planets' painter (`setBodyPainter`), every planet, Pluto, the Sun and the moons that have a surface picture are drawn from it in the default look too (the view passes `mapped: true` in the painter's context; it was the shaded look until `bodies="painted"`), and the Moon is the painter's, so it is drawn like the planets (the view's own NASA Moon until it arrives, with `bodies="plain"`, and with no painter). Each drawing is told the camera and the view's size (`update({ ..., view })`, `BodyView` is new in `/space`), so a planet or the Moon big on the screen takes wakusei-planets' finer map tiles for the part in view, and the Sun's glow faces the camera. A painter may carry `credit: { en, ja }`, which the view writes under the picture while it draws the bodies (`bodies-credit="off"` takes it away). `stats.bodies` adds `held` (the moons kept, shown or gone from the view for less than four seconds), `moon` and `tiles`; the test of the moons let go at rest reads `held`, since with their pictures the moons share the planets' shaders. The demo uses wakusei-planets 0.36.0 with its tiles and the credit; NOTICE.md lists the pictures' sources, four of them CC BY 4.0. Tests: `e2e/space-full.gl.ts`.
- **`<chikyu-space>` works full screen** (MODULES-848). `immersive` (new attribute and property, as on `<chikyu-earth-realistic>`): the element fills its box in any shape with the Earth and its glow inside the shorter side, a plain wheel zooms (out past the Moon to the planets, and back), and a drag anywhere, a touch drag too, turns the view round the Earth; without it kazoku-ui's rules stand. The full-screen page takes `look=space`. Browser tests: the element and its canvas are the window to a pixel at 1440 by 900, 390 by 844 and 2400 by 700; the wheel goes out until the Moon is in view and back; a drag from a corner turns; `checkGestures` is green but for the wheel's pan; the freeze test adds the full-screen space view at rest and on a 5K screen.
- **The grid and country names on the Earth** (MODULES-1150). `<chikyu-earth-realistic>` and `<chikyu-space>` take `grid` (the property `grid`) and draw the meridians and parallels on the Earth: every 30 degrees while its radius on the screen is under 220 CSS pixels (`GRID_FINE_RADIUS`), every 15 above; the equator brightest, the tropics and polar circles bright (the IAU's tilt, `EARTH_TILT`), the prime meridian warm; under the clouds, light by day and dim by night, turning with the Earth. One batch of lines (one draw call; 3,240 segments, a 95 kB buffer, made once). They take `country-names` (a bare attribute for 40 at most, or a number up to 120; `countryNamesStyle` and `--chikyu-country-*` for the look) and name the countries in sight at the middle of the part of each in view, sized by it, in the page's language (chizu's English and Japanese names), never over each other or over the names of cities, places, a page's markers (`OverlayHost.claim`, which `attachMarkers` now calls) and the space view's bodies, inside the Earth's disc (so clear of the star names), never from the far side, more as the Earth grows. chizu's `world-geo` is loaded only when it is set (shared with `borders`); `chikyu-country-names-unavailable` and `chikyu-grid-unavailable` say when either cannot be made. Each element's code grows by 3.7 to 3.9 kB gzipped; nothing is drawn at rest. `stats.grid` and `stats.countryNames` have the counts; the pure parts (`gridLines`, `countrySpots`, `layoutCountryNames` and the rest) are in `@johnmorrisdotca/chikyu-earth/realistic`. The demo has Grid and Country names buttons (`grid=on`, `country-names=on` in the address). New guide: The grid and country names on the Earth (English and Japanese).
- **Any number of places on the live 3D Earth** (MODULES-863, the drawing parts). `places` on `<chikyu-space>` and `<chikyu-earth-realistic>` now takes up to 5,000 places (`MAX_PLACES`, was 200). The first `PLACE_MARKS` (32) in sight, `here` first and then in the order given, stand up out of the ground with their names as before; every other place is a ring lying on the ground, all of them one draw call (three.js `Points`, made only while a ring is shown, its buffers written again only when the places or their groups change), so a thousand places add one draw call to a frame and nothing at rest. Places closer than about 24 pixels on the screen are gathered into one larger ring with their count, in cells fixed to the ground so the groups turn with the Earth (`groupPlaces`, `groupCell`, `PLACE_GROUP_PX`); the reader's own place is never gathered. A place may have a colour of its own (`color`: a hex colour, `rgb()`/`hsl()` with numbers, or a colour's name). Places on the night side are drawn at half strength and their names a little dimmer, still readable (`layoutPlaces` takes `sun` and each shape says its `night`); nothing is dimmed with `light="lit"`. `goToPlace(idOrLabel, { smooth })` turns the view so a place is in the middle, at a pace a reader can follow, or at once for a reader who asked for less motion; in the space view only while the camera looks at the Earth. `stats.places` adds `marks`, `sprites` and `groups`. A click on the globe or on a place is not part of this release: it waits for a decision (MODULES-1082).
- **Borders on the Earth** (MODULES-864). `<chikyu-earth-realistic>` and `<chikyu-space>` take `borders` (`countries`, `regions`, or bare for both; the property `borders` as `{ countries, regions }`) and draw the borders on the land as thin lines that turn with the Earth, above the clouds and under the air, by day and by night. Only edges two shapes share are drawn, never a coast. The countries are chizu's `world-geo` (Natural Earth 1:110m, public domain), loaded with a dynamic import only when a set is switched on (166 kB minified, 44.3 kB gzipped; a page with the line globe has it already). The regions (provinces, states) come from the page's own `borderData.regions(code)`, asked only for the countries the view shows once the Earth's radius on the screen is 900 CSS pixels or more (`BORDER_REGIONS_RADIUS`); chizu's own regions are drawn for flat maps and cannot be laid on a sphere yet (MODULES-1142). Each set is one batch of lines (one draw call); the 3,012 country segments are a 72 kB buffer; the element's code grows by 1.9 kB gzipped; nothing is drawn at rest. `chikyu-borders-unavailable` is sent when the shapes cannot be loaded, and the Earth goes on without them; `stats.borders` has the counts. The pure parts (`sharedEdges`, `shapeBoxes`, `codesNear`, `readBorders`) are in `@johnmorrisdotca/chikyu-earth/realistic`. The demo has a Borders button (`borders=on` in the address). New guide: Borders on the Earth (English and Japanese).
- **Place grouping has an off switch, and no place is lost without `Points`** (MODULES-863). `place-groups="off"` (and `placeGroups = false`) leaves every place its own ring instead of gathering crowds into one ring with a count; gathering stays the default. When the three.js parts handed over lack `Points`, the picture cannot draw the rings of the places that are not markers of their own: they were dropped without a word. The places' layer now draws them itself as small circles in the page (at most `PLACE_DOTS`, 600), the element sends `chikyu-places-unavailable` once, and `stats.places.omitted` counts the places in sight that had no room. `readPlaceGroups` and `PLACE_DOTS` are exported from `/markers`.
- **Satellite names are kept from one frame to the next** (MODULES-1096). The names drawn beside the satellite rings are cached for each satellite and language: a frame reads the page's language once rather than once for each satellite, and no longer works out an orbit just to read a name that does not change. The cache is dropped when the language changes, when `satelliteNames` is set and when a group is replaced. Nothing a page can see changes.
- **Two flaky tests are steady** (MODULES-1149, MODULES-1154). The satellite-label test waits for the other view's names before it compares them, and the freeze test reads the frames and the draw calls in one call. Tests only; the budgets are unchanged.
- **A country-names load that ends after the element let go is ignored** (MODULES-1150). The layer no longer makes its box again, or tells the page of a failure, when the outlines arrive after `dispose`.

## 0.35.0 - 2026-11-12

- **The figures follow a sky culture** (MODULES-1125). `constellation-culture` is `iau` (the 88, the default), `western`, `japanese` (the 88 by their Japanese names, then the traditional figures such as Subaru, the Pleiades) or `chinese`; the lines, the hovered and picked figure and its name follow it, and the events carry `id`, `kind` and `culture`. The value is exactly what the page sets (a Japanese page keeps the IAU's figures unless it says `japanese`); an unknown value is `iau` with one warning. Each culture's data is a dynamic import of its own, fetched only when asked for. hoshi-stars' `createFigureLines` takes no culture yet, so the lines of a culture are laid out here from `figures(culture)`.
- **Say which constellation was picked, reveal its name on hover, and an option to name every constellation** (MODULES-1108). A mouse resting on a figure (its lines, or inside it) lights it and fades its name in at the middle of the part of it that is on the picture, inside the frame, off the Earth and clear of the star names; a click or tap picks it and the name stays until another pick or a click on empty sky, `Escape` or the property set to `null` (`C` and `Shift`+`C` pick with the keyboard). `chikyu-constellation-hover` and `chikyu-constellation-pick` are sent with `{ abbreviation, name, english, japanese, culture }` (`null` when let go), and `constellation` reads or sets the pick. The name sat above the figure's whole box, which includes the part off the picture, so a figure that ran off the top had its name left near its bottom. `constellation-names` (off by default) writes every figure's name in view, quieter than the star names, in the page's language, with no overlap. The hit test runs once a frame at most, only after the pointer has moved, and the layer is drawn again only when the hovered figure changes. A pick is read out by a visually hidden polite live region (a hover is not). A pick set before a sky culture has arrived is kept until it has.
- **A page can mark places where the sky's names must not go** (MODULES-1124). `<chikyu-space>` and `<chikyu-earth-realistic>` take `keepClear` (a list of rectangles in the element's pixels, or of page elements) and the attribute `keep-clear` (a CSS selector). A star name that touches one is left out, a star whose point is in one is not named, and the picked constellation's name moves clear of it; the lines are still drawn. The boxes are read when the list changes or the page is resized or scrolled (the names are laid out again at the next frame, once however many events), never at each frame.
- **Ride above a satellite** (MODULES-1138). `ride(ref, { view: "above" })` puts the camera on the line from the Earth's centre through the satellite, `distanceKm` over the zoom above it, looking straight down at it with the way it is going at the top of the picture. The satellite stays in the middle while the clock moves it and the Earth turns beneath; a drag turns the picture about it and tips the camera back or ahead of it; the zoom changes the height; a satellite model is drawn there as in the follow view. It glides from and to the other views (a jump for reduced motion) and draws as the follow view does. `aboveAxes` gives the camera's place and top. The demo has an "Above it" button and the address `rview=above`.

## 0.34.1 - 2026-11-11

- **The sky is behind the Earth: constellation lines no longer cross it** (MODULES-1103). The lines were drawn over the Earth's disc (in a ride, across the whole globe). Each line is now cut exactly at the Earth's edge, the air's rim included, in the picture's own camera, in the space view and in a ride at any height, on the day side and the night side. A star whose point, ring or name box touches the Earth, the Moon or the Sun has its name and ring left out (a name only partly on the Earth was shown before), and the figure under the pointer is not lit over the Earth.
- **The element is its own stacking context** (MODULES-1104). `<chikyu-earth>`, `<chikyu-earth-realistic>` and `<chikyu-space>` are each their own stacking context (`isolation: isolate`), so nothing inside the element (the sky's labels, its lines, its markers) takes part in the page's own stacking: it paints as one piece, where the element sits in the page.

## 0.34.0 - 2026-11-11

- **You are here, and places on the Earth** (MODULES-927). `<chikyu-space>` and `<chikyu-earth-realistic>` take `places`, a list of `{ id, lon, lat, label, kind }` (attribute as JSON, or property), and draw each as a marker standing out of the ground: it turns with the Earth, is hidden on the far side, fades at the edge and keeps its size in pixels at any zoom. `kind: "here"` is the reader's place (taller, brighter, a quiet pulse at its foot); a `favourite` is quieter. `places-look` is `beam` (the default), `pin` or `ring`; colours come from `--chikyu-place-here` and `--chikyu-place-favourite`. Names sit at the top of the markers, `here` first, measured in the page's font and never over one another or the bodies' names. Nothing is drawn again at rest: the places are laid out with the picture, and the pulse is a CSS animation, stopped out of sight and for a reader who asked for less motion. `stats.places` says how many are drawn and named. The package never asks for the reader's place and stores or sends nothing; `nearby` (in `/markers`, with `readPlaces`, `cleanPlaces`, `orthoView` and `layoutPlaces`) rounds a place to about 10 km before a page draws or keeps it. `placeLabels` takes boxes already used by another layer. The demo has "Show where I am" (asked only on the press, rounded, never put in the address) and the three looks. New guide: "You are here, and places on the Earth".
- **Favourite places** (MODULES-942, as John decided on 2026-11-11: the package renders the list it is handed; the page owns the picker and keeps the list). Any place without `kind: "here"` is a favourite, drawn quieter than the reader's own place. The demo offers six example cities as favourites and keeps the ones chosen in its address (`fav=Tokyo,Cairo`); the reader's own place is never put there. The places guide says how a page builds and keeps the list.
- **No location is asked for on load** (MODULES-1071). `<chikyu-earth>` and `<chikyu-earth-realistic>` asked the browser for the reader's location when they opened with no `center`, before the reader had done anything. They no longer ask at all: without `center` they open on 0,0. A page that wants to centre on the reader asks on a press of its own (the demo's "Centre on me") and sets `center`. See the upgrade guide. The embed page's `center=me`, which the embedding page chooses, now asks from the page itself, once, and gives the answer to the look that is shown (on the realistic and space looks it used to apply the answer to the hidden line globe only).
- **City names on the Earth** (MODULES-937). `<chikyu-earth-realistic>` and `<chikyu-space>` take `city-names` (bare is 24 names at once, a number is that many, 1 to 80; absent, none) and name cities from kuni's `cities` (an optional peer, `>=1.6.1`, loaded only when it is set, one tier at a time): the capitals from an Earth 60 pixels in radius, the other cities of a million from 170, those of 100,000 from 420, the most populous first with a bonus for capitals. A name goes right of its dot, then left, above, below, never over another and never off the picture; a city that is not facing the viewer, or is within about 7 degrees of the limb, is left out. The names are English, or Japanese on a Japanese page where kuni has the name (`name.jaShort` first when kuni gives it, so Tokyo is written as the city and not as the prefecture). The property `cityNamesStyle` has the font, size, weight, colour, outline and the dot's colour and size. Only the layer is drawn again, and nothing at rest; `chikyu-city-names-unavailable` is sent when kuni is not there and `stats.cityNames` has the counts. The pure parts (`layoutCities`, `cityTiersFor`, `cityRank`, `cityNameText`, `nameWidth`, `readCityNames`) are in `@johnmorrisdotca/chikyu-earth/realistic`. The demo has a City names button (`city-names` in the address). New guide: City names on the Earth (English and Japanese).
- **Ring and name the satellites of a group.** `labelSatellites(group)` rings every member of a small group (the stations) and writes its name beside it in the page's language (`SHORT_NAMES` in `/satellites`: the ISS, Tiangong and Hubble; `satelliteNames` for a page's own), at most 80. The names are laid out after the places' names and never over them, a body's name or one another. `placeSatellite(ref)` says where a satellite is on the screen and whether it can be seen, and `chikyu-satellite-visibility` is sent when a ringed one comes into view or goes out. Nothing is drawn at rest.
- **Follow a large satellite as a 3D model** (MODULES-861). `setSatellitePainter({ has, make })` hands `<chikyu-space>` the page's own models (the package ships none): a satellite followed with `ride(ref, { view: "follow" })` that the painter has a model for is drawn as that model, held in the middle of the picture at a size that reads (`MODEL_RADIUS_SHARE` of the view's height), pointed the way it flies (`satelliteAxes`, `modelMatrix`) and lit by the Sun, with the Earth turning and sliding beneath; one with no model stays a dot. `largeSatellites()` lists the satellites of the groups set that have a model, and `followNext(step)` hops between them. `stats.followModel` says where the model's middle is drawn. The demo follows the ISS, Tiangong and Hubble as made-up models of boxes and cylinders (`demo/station-models.ts`), not pictures of the real ones.

## 0.33.2 - 2026-11-11

- **kazoku-ui 0.38.1** (KAZOKU-UI-133). The view controls keep a pace of 1 in the address when the page starts at another, so the line globe's 1× (the Earth's real rate) survives a reload; the test of it is switched on (it was `fixme`).
- **Riding with the horizon look: a drag looks round on the spot, the horizon level** (MODULES-1030). A sideways drag is now a turn about the local vertical (the line from the Earth's centre through the satellite) all the way round, and an up or down drag only tips the camera, from straight down to 20 degrees above the horizon: no roll. Before, the drag turned the camera about its own tipped axis, so the Earth's edge ran diagonally across the picture and a long drag swung it into a corner. The `down` look is as it was. The turn is added up change by change from the controls' wrapped yaw (`rideTurnDegrees`, passed to `ridePose` as `turn`), so a drag really goes the whole way round at any zoom and a change of zoom does not swing the heading, and the controls' tilt is held to the range that does something (`rideTiltLimits`), so a drag back moves the view at once. New in `@johnmorrisdotca/chikyu-earth/space`: `rideFov`, `rideTurnDegrees`, `rideTiltLimits`. `stats.camera` has the camera's turn (`quaternion`). Tests: the camera maths (`ridePose`) over a whole turn, and a browser test that the camera's turn and the Earth's edge in the picture are level at 90, 180 and 270 degrees.
- **A ride opened from an address keeps the turn the address carries** (MODULES-1030). The riding camera's heading is added up from the controls' changes, and starting a ride set it to nothing, so a link with `ride=iss&yaw=-21` opened looking another way than the view that was dragged to that yaw; the ride now starts from the yaw the controls already hold.
- **A link to the demo's realistic Earth or space view keeps its Auto-turn pace** (MODULES-900). Opening a 3D look reset the pace to 1×, so `?look=realistic&pace=2` (or a reload after choosing 0.5× or 2×) opened at 1×; the look a link opens on now keeps the pace it names, and a look chosen later starts at its own. The line globe's 1× was left out of the address by kazoku-ui's view controls (KAZOKU-UI-133); kazoku-ui 0.38.1, which this release takes, keeps it, and the test of it is on.
- **A test that runs the page's own clock pays for the frames it asked for** (MODULES-897). `page.clock.runFor` fires a span's animation frames all at once, and the software GPU then needed 20 to 40 s to draw them, which the next page to open waited for: the satellites and embed tests timed out that way in CI. `timed()` now waits for the GPU before the clock runs on.
- **The demo's gesture check has room to finish** (MODULES-933). Thirteen gestures with screenshots in software GL take up to 39 s of a 60 s limit in CI, and a run cut off there reads as failed gestures; it now has 120 s, three times the most seen, so a real slowdown still fails.
- **The map-tiles freeze test waits for the tile sweep's frame before it counts rest.** The tile set lets the coarser tiles go 4 s after a zoom and draws the sphere once more when one of them was on it; when the finer tiles took about 2 to 3.5 s to come, that frame fell inside the count and the test failed (2 runs in 3 on a busy Mac, whatever the kazoku-ui version). It now waits for the page to let them go and for that frame, and has 150 s for its six rounds.

## 0.33.1 - 2026-11-11

## 0.33.0 - 2026-11-11

- **The data door names licences in Japanese** (KAZOKU-UI-105): `src/data-door.ts` copied again, unchanged, from kazoku-ui's template: a licence may carry `nameJa` for a Japanese credit line.

- **CI's browser jobs run in the Playwright image and need no apt mirror** (KAZOKU-UI-100). The runner's apt mirror stopped answering on 2026-11-11 from about 13:50 UTC, and every browser job failed in its setup before a test ran. The demo and usage jobs (`ci.yml`) now run in `mcr.microsoft.com/playwright:v1.64.0-noble`, the lockfile's Playwright version, which has the browsers and their system libraries. `.github/actions/playwright` (the family's, kazoku-ui's copy is canonical) checks the libraries with `ldd` first and runs apt only when one is missing, skips the browser cache in the image, works without `sudo`, and warns when a workflow's image and the lockfile name different Playwright versions. The Pages deploy stays on the runner: its `python3 -m venv` has no `ensurepip` in the image.

- **The meteor showers checked against the IAU Meteor Data Center, and linked to their parent bodies** (MODULES-932). Every row of `METEOR_SHOWERS` was held against the Data Center's lists of all and of established showers (read 2026-11-11; it states no licence and asks to be cited, which NOTICE.md and the guide do). The radiants and speeds agree with the Data Center's solutions of 100 meteors or more within 2 degrees and 2 km/s except three, which took its figures: the April Lyrids' speed is 47 km/s (was 49), the alpha-Monocerotids' 62 (was 65) and the eta-Eridanids' radiant is right ascension 42, declination -13 (was 41, -11). The Data Center lists no maximum date and no rate, so the dates and rates stay the IMO's. New in `@johnmorrisdotca/chikyu-earth/meteors`: `METEOR_LINKS` (each shower's IAU name, `established` or `working` status, parent body, the solution it was checked against and where each figure comes from), `parentBodyOf(code)`, `showersOfParent(designation)`, `showerSource(link)` and `IAU_MDC` (where the lists are, when they were read and how to cite them). Fifteen showers gain a parent body (the Data Center's origin column names one for 26 in all; the delta-Aquariids' two solutions name different bodies and are given none). The guide, in English and Japanese, has a section on it.
- **The Earth-orbit catalogue: the data side** (MODULES-932). New entry point `@johnmorrisdotca/chikyu-earth/catalogue`, with no data, no DOM and no dependency. `classOfElements`, `orbitShape` and `orbitClass` give the class of an orbit (low, medium, geostationary, highly elliptical or other) from its mean motion and eccentricity, with the thresholds stated in `CLASS_LIMITS` and `CLASS_LABELS`; `readKind` gives the kind of an object (payload, rocket body, debris, unknown) from the catalogue's object type; `legend`, `CLASS_COLOURS` and `KIND_COLOURS` give a colour and a legend for each, in English and Japanese; `FLEETS`, `fleetOf` and `countFleets` find Starlink, OneWeb, GPS, Galileo, GLONASS, BeiDou, Iridium and the stations by name. `packCatalogue`, `unpackCatalogue`, `gzipBytes` and `unpackAny` write and read a packed file of up to 200,000 objects (about 95 bytes an object, about 37 gzipped) that holds six-digit and longer catalogue numbers, and `readCatalogueRecords` turns OMM JSON or CSV with Space-Track's GP fields into records. The data door's `packedElementsFrom` and `readPackedFrom` read such a file from an address you choose, once, politely. The repository's `scripts/catalogue.ts` and the scheduled `.github/workflows/catalogue.yml` make the group files (`payloads`, `rocket-bodies`, `debris`; `working` and `inactive` instead of `payloads` when the repository variable `CATALOGUE_WORKING_LIST` is `celestrak`, off by default) and `manifest.json` for the demo's site; the workflow is switched off until the repository variable `CATALOGUE_PUBLISH` is `yes`. New guide: The catalogue of objects in Earth orbit (English and Japanese).

- **The names of the brightest stars and faint constellation lines over the sky** (MODULES-926). `<chikyu-space>` and `<chikyu-earth-realistic>` take hoshi-stars' own attributes `star-names` (a count of the brightest stars in view and not covered; bare is 10), `star-names-magnitude` and `constellation-lines` (the 88 figures at a strength from 0 to 1; bare is 0.16), none of them by default: nothing is loaded until one is set, then hoshi-stars' `sky-labels` (an optional peer, `^0.30.0`) is imported. The names are laid where the stars of the page's own sky are, through the picture's camera, and are left out where the Earth, the Moon or the Sun covers the sky (the cover argument of hoshi's `update`); they never overlap, are English or katakana by the page's language, and take their look from the property `skyStyle` (hoshi's `LabelStyle`) with Michroma loaded as for the name on the Earth. A mouse lights the figure it rests on and a finger the one it touches, with its name; only the layer is drawn again, and nothing at rest. `star-names` is a most, not a count: at the opening size the Earth covers most of the space view, so about two named stars are in view on average (a smaller `earth-size` leaves room for all twelve); the names are written again when the page's language changes after the element was made (the family's `kazoku-languagechange`, or the next draw); `chikyu-sky-unavailable` is sent when hoshi-stars is not there, and `stats.sky` has the counts. On the realistic Earth the sky is the directions seen along the picture's own axes. The demo has Star names and Constellation lines buttons (`star-names` and `constellation-lines` in the address). New guide: Names on the stars and faint constellation lines (English and Japanese).

## 0.32.0 - 2026-11-11

- **The Earth's name written on the globe, as the family's body label** (MODULES-923). `<chikyu-earth-realistic>` and `<chikyu-space>` take the family's plain attributes `body-label` (`painted`, `etched`, `outline` or `burned`; absent, off), `body-label-strength`, `body-label-repeat`, `body-label-latitude`, `body-label-facing`, `body-label-font` and `body-label-fallback-font`, and the property `bodyLabel` (an object with the same options, or `null`). It writes `EARTH` (`地球` on a Japanese page) on the globe with kazoku-ui's shared `body-label`, so it turns with the Earth and the surface shows through the letters; the default is the family's, Michroma, painted, half strength, once. Off unless set: nothing of it is fetched or made until `body-label` is first set, then the family's label is loaded and Michroma (64 kB) only when the page names no font of its own. No name while the Earth is under 24 pixels in radius or a ride hides it; nothing is drawn at rest. `chikyu-body-label-unavailable` is sent when the three.js handed over lacks a part the label needs (`ThreeParts` gains the optional `CanvasTexture`, `SphereGeometry`, `MeshLambertMaterial`, `SRGBColorSpace`, `NormalBlending` and `AdditiveBlending`). `stats.bodyLabel` has `on`, `text`, `made` and `showing`. New in `@johnmorrisdotca/chikyu-earth/realistic`: `readBodyLabel`, `bodyLabelText`, `BODY_LABEL_ATTRIBUTES`. New guide: A name on the Earth (English and Japanese).

- **CI installs Playwright's browsers in bounded, cached steps** (KAZOKU-UI-100). A slow package mirror held `playwright install --with-deps` for the whole job limit on 2026-11-09 and 2026-11-10, so no test ran and the failure read as a test failure. `.github/actions/playwright` (the family's, kazoku-ui's copy is canonical) caches the browsers by Playwright's version, then installs the system libraries in a step of their own: two tries, each cut off after 7 minutes, and a failure that says it is the runner's package mirror and that nothing was run. Free: GitHub-hosted Linux runners and the cache.
- **`pnpm docs:check` reads a guide's front matter as strict YAML** (KAZOKU-UI-102). A title or description holding a colon and a space without quotes passed the old line reader while GitHub showed "Error in user YAML" above the page. `scripts/docs-site.mjs` (the family's, version `2026-11-10-strict-front-matter`) now fails with the file, the line and a plain sentence on an unquoted colon, an unquoted " #", a value that starts with a YAML character (`[ { & * ! | > % @` or a backtick), a tab, an indented continuation, a key twice and an unclosed quote. It found one more bad guide, `docs/guides/ja/data-door.md`, whose title is now in quotes.

## 0.31.0 - 2026-11-11

- **The data door: sources of your own map and orbit data, with their licence and credit** (MODULES-902, step 3 of MODULES-831). New entry point `@johnmorrisdotca/chikyu-earth/door`: `EarthMapSource` (the Earth's map in tiles for the `day` or `night` layer; the family's `TileSource` of `MapPlace`, `ImageTile`), `earthTiles(base)` (the package's own folder of tiles as a source: what the `tiles` attribute now means), `mapKeys`, `tilePlace`, `tileKeyParts`, `ElementRecordSource` and `elementsFrom(url, info)` (orbit data through `fetchElements`), `createSourceBook`, `OWN_SOURCES` (`chikyu-pictures` and `chikyu-tiles`, written from `NOTICE.md`), `ownCredit`, and the family's `creditLine`, `validateSource`, `loadRecords`, `createTileStore` from `src/data-door.ts`, kazoku-ui's template copied unchanged (a test holds its hash). `<chikyu-earth-realistic>` takes `sources`, `addSource`, `removeSource`, `enableSource`, `data="own"` and `credits()`; `<chikyu-passes>` takes the same for orbit data (the newest epoch of a satellite wins), and its `credit` attribute stays and is followed by the line `credits()` writes, with the licences. `chikyu-creditschange` tells a page when the set of credited sources changes (not at each frame). Off (`remove()`, `enableSource(id, false)`, `data="own"`) aborts a source's loads, frees its tiles and drops its credit. A source is refused at once for an empty credit, no licence, a clashing id (or an id of the package's own) or a layer the Earth does not know; a tile that throws, is not a picture or has a size that is not a number is counted in `stats.tiles.failed` and never drawn. The tiles of a view share one budget, `TILE_BUDGET` (72 MB, the 48 tiles it has always held), and a tile that does not fit is refused and counted (`stats.tiles.refused`). With no source every picture is the same one. Every old attribute and function stays. One change: a tile that could not be fetched is no longer asked for again after 30 seconds; it is asked for again after the view has moved away from it and back, so a view at rest sends nothing. `stats.tiles` gains `heldBytes`, `refused` and `used`. New guide: Outside data, the data door (English and Japanese). The demo's Earth page shows the credit line under the view and reads `?data=own`.

## 0.30.0 - 2026-11-11

- **A strength setting for the meteors** (MODULES-906). `meteors-strength` (the property `meteorsStrength`) on `<chikyu-earth-realistic>` and `<chikyu-space>` is a number from 0 to 1 that scales how bright each streak is and how many are drawn, so a page can show them subtly. It is 1, the look they have always had, when the page says nothing; a number outside the range is brought to its nearest end and one that is not a number is 1. At 0 no streak is drawn, and the line under the picture, the survey of the sky and `chikyu-meteors` are as they were. Nothing that is real changes at any strength: the hourly rates and the showers' `zhr` are the same, and the line still says the streaks are an illustration. `stats.meteors` gains `strength` (and its `perSecond` is the streaks a second drawn, so it follows the strength). New in `@johnmorrisdotca/chikyu-earth/meteors`: `readMeteorStrength`, `METEOR_STRENGTH_DEFAULT`, and `streaksPerSecond(rate, strength)`. The demo has a Subtle, Medium and Full choice beside the Meteors button (`meteors-strength` in the address). The guide, in English and Japanese, has a section on it.

## 0.29.0 - 2026-11-11

- **The air is drawn 3 times its real thickness unless a page says otherwise, so the ring can be seen** (MODULES-904). At whole-Earth zoom the true 100 km shell is a line a pixel or two wide, and on a phone thinner than the old painted glow. `air-thickness` (and the property `airThickness`) on `<chikyu-earth-realistic>` and `<chikyu-space>` takes a number from 1 (the true thickness) to 5, and 3 when left out; the shell and the heights over which the air thins grow by it and the air is the same amount, so the physics and the colours do not change. While it is above 1 the element says so in a line under the picture, "The air is drawn 3 times its real thickness so it can be seen." (and in Japanese), which `air-label="off"` takes away. New exports `AIR_THICKNESS_DEFAULT`, `AIR_THICKNESS_MAX`, `readAirThickness`, `airTop` and `AIR_NOTE`. The demo has a True air thickness button on the realistic and space looks and on the full-screen page (`air-thickness=1` in the address). The cost is the same: a draw is the same program with one more uniform. Tests: `test/air.test.ts`, `e2e/air-visible.gl.ts`.

## 0.28.0 - 2026-11-11

- **The air is light scattered once, worked out in the shader** (MODULES-843). The realistic Earth and the space view draw the atmosphere as a shell 100 km thick (0.0157 of the Earth's radius), sampled along each ray toward the camera and toward the Sun in the fragment shader, with the samples packed where the air is thick: Rayleigh scattering (a blue haze that thickens toward the limb on the day side), Mie scattering (a glow toward the Sun), the reddening along the day and night line, and the thin lit ring seen from the night side looking toward the Sun are what the sums give, not things drawn. The surface under it is dimmed by what the air takes out of the light. The old rim in the surface program is gone. Our own code, from the published single-scattering model (Nishita and others, 1993; GPU Gems 2, chapter 16), no code taken from any project. `air="light"` (6 samples along the ray and 2 toward the Sun; the default on a small or slow device) or `air="full"` (12 and 4), on both elements. It costs nothing at rest, at most 30 frames a second as before. New in `/realistic`: `AIR_TOP`, `AIR_QUALITY`, `AIR_VERT`, `airFrag`, `airFor` and `AirSamples`. `ATMOSPHERE_OUTER` stays the room the page leaves for it. Guide in English and Japanese: `docs/guides/full-screen-and-camera.md`.

## 0.27.0 - 2026-11-10

- **The demo's line and thick globes open turning where it can be seen** (MODULES-898). Auto-turn opens on a new 1440× button (a day a minute, a turn in about a minute) beside 0.5×, 1× and 2×; 1× is still the Earth's own rate, `0.004178` degrees a second, and the package's elements and the embed page are unchanged. The 3D looks keep their own 6 degrees a second, and going back to a line look puts the 1440× back. A reader who prefers reduced motion still gets a still globe with Auto-turn ready. Tests: `e2e/globe-turn.demo.ts`, `e2e/speed.demo.ts`.

## 0.26.0 - 2026-11-10

- **The realistic Earth: a camera held in the stars, a full-screen mode, a better look and every satellite group** (MODULES-849, MODULES-843). `<chikyu-earth-realistic>` takes `camera="space"` (held in the stars, so the Earth turns beneath it as the clock runs, with the day and night line where the Sun really is) or `camera="sun"` (on the Sun's side, so the line keeps its place on the screen); `space` is now the default, so a view that opens playing shows the Earth turning (before, the camera rode the ground and only the clouds seemed to move); `ground`, the camera over a place on the ground, stays as the option. The cloud drift is one made-up eastward 1.5 degrees an hour that was always on, so it is now an attribute, `cloud-drift`, 0 by default (the cloud picture is one snapshot, not a forecast). `<chikyu-space>` takes `camera`, `earth-size`, `earth-x` and `earth-y` too, and its Earth is fitted to the shorter side of its box with the glow inside. `center` is where the camera looks when it is set (`sun`: the offset from the sub-solar point). New `cameraCentre`, `greenwichSidereal` and `CameraMode` in `/realistic`. `immersive` fills the element's box in any shape, makes a plain wheel zoom and a touch drag turn; Ctrl and the wheel, a pinch and the keys stay kazoku-ui's. The look: a thin bright limb with a faint halo, blue by day and orange along the terminator; a reddening Sun, a warm band and a blue hour at the terminator; a clear blue ocean with a hard glint, a broad sheen and the sky at grazing angles, hidden by cloud; cloud shadows on the ground; warm, softly spread city lights that cloud dims; all from the pictures the package already carries (NASA Blue Marble, Black Marble and cloud pictures: no new data, no code, art or data from any other site). The realistic Earth draws satellites with the space view's calls (`setSatellites`, `showSatellites`, `satelliteGroups`, `selectSatellite`, `selectedSatellite`, `satelliteInfo`, `chikyu-satellite-click`, `stats.satellites`): one draw call a group, so every group at once, at most 30 draws a second, nothing drawn while the clock holds, hidden behind the Earth. The 3D looks fill the demo's felt, Wide and the embed frame edge to edge (no square canvas inside the frame); Auto-turn opens on at a speed that can be seen (6 degrees a second) in them. The demo's Satellites row works on the realistic look and has a Camera row; a new page `fullscreen.html` shows the whole on a dark window (`?sats=all` for every group). The orthographic camera now sits 50 radii out (it was 5) so a geostationary satellite is never behind it. Guide in English and Japanese: `docs/guides/full-screen-and-camera.md`. Tests: `test/realistic.test.ts`, `e2e/camera.gl.ts`, `e2e/fullscreen.gl.ts`.

## 0.25.0 - 2026-11-10

- **The first screen says who it is for, and every demo page credits its sources** (MODULES-812). The README opens with a picture of the day and night Earth on a desk and the ISS passes on a phone, a sentence that it runs in the browser of a phone, a tablet or a computer with nothing to install, "Who it is for" for teachers and students, satellite spotters, researchers and developers, a "Try it now, nothing to install" row of links, "For teachers and families", a fuller "Limits" and "How to cite", with a new `CITATION.cff` (a test keeps its version and the README's equal to `package.json`'s: a release commit bumps all three). The footer of the home, sheets and passes pages names the sources and links NOTICE.md (English and Japanese), the code builder has the same line, and the two embed frames carry a credit (the globe frame in its top corner, naming only the sources its look uses; the passes frame under its list; `lang=ja` for Japanese). Tests: `e2e/credits.demo.ts`, `e2e/credits.gl.ts`, `test/frame-credit.test.ts`, `test/citation.test.ts`. NOTICE.md says that the demo's space view uses wakusei-planets' pictures.
- **Meteors seen from space** (MODULES-872). `<chikyu-earth-realistic meteors>` and `<chikyu-space meteors>` (the property `meteors` is a boolean; off by default, and nothing of theirs is made until they are switched on) draw short streaks where meteors burn, 110 km down to 85 km, on the dark side of the Earth and in its twilight, only while the clock runs and at any speed. Real, for the moment shown: how many there are from place to place (a background of 8 an hour, an assumed figure, leaning to the side that faces the Earth's way, plus each active shower's rate times the sine of its radiant's height), that none show where the Sun is up, the way a shower's meteors travel, their height and their speed. Illustration, and said so in a line under the picture in English or Japanese (`meteors-label="off"` takes it away): each streak's place and moment are random, a streak stands for many meteors (2.5 a second over a dark view with no shower, never more than 9), and a short one is lengthened to be seen. For a reader who prefers reduced motion there are none until the page sets a `speed` (a Play). All the streaks are one draw, 48 alive at most, nothing started or drawn while held, out of sight or in a hidden tab, and none in the space view while the Earth is under 40 pixels in radius. `chikyu-meteors` tells a page the strongest active shower, and `stats.meteors` the counts. The demo has a Meteors button (`meteors=on` in the address).
- **`@johnmorrisdotca/chikyu-earth/meteors`**: the year's meteor showers and the sums behind the picture, with no DOM and no dependency. `METEOR_SHOWERS` is the International Meteor Organization's Working List of Visual Meteor Showers from its 2026 calendar, 37 showers (the Antihelion Source left out), each with its dates, maximum, radiant, speed, population index, rate, names in English and Japanese and, where a source names one, its parent body; `showerRate`, `activeShowers`, `solarLongitude`, `pointBeneath`, `apexPoint`, `meteorSky`, `hourlyRateAt`, `darkness`, `streaksPerSecond`, `streakPath`, `placeVector`. New guide: Meteors seen from space (English and Japanese).

## 0.24.0 - 2026-11-10

- **The demo's views open moving** (MODULES-815). A link that says nothing about the clock (no `play`, no `speed`, no `time`) opens the space view and the realistic Earth running from now at an hour a second (`speed` 3600, the first step of the Time row where motion shows; real time looks frozen), with the date box running with it. They opened held (the space view) or following the real clock (the realistic Earth) before. Links that say something work as they say: `speed=0` and `play=off` hold, a date (`time`) is shown as it says and held until Play, a speed other than 0 with no `play` runs at it, and a reader's Pause, written to the address as `time`, stays held. A hold with no date to write (Back to a date that was "now" on the realistic Earth, Now pressed while held) is written as `play=off`. Changing look keeps the clock as the reader left it: a view that was running goes on running from the date reached, one that was paused stays paused. The line and thick globes already turn on their own when the page opens (the view controls' Auto-turn, at the Earth's own rate). **A reader who prefers reduced motion still gets a still view with Play off**: John has not decided whether that changes, and the one place to change is `OPEN_MOVING_WITH_REDUCED_MOTION` in `demo/demo.ts` (kazoku-ui's replay bar also turns Play off under reduced motion, so the change needs an option there first). Nothing is drawn while held, out of sight or in a hidden tab, and never more than 30 frames a second, as before. The package's elements are unchanged (`<chikyu-space>` still defaults to real time and `<chikyu-earth-realistic>` to following the real clock), and so is the embed page. Guide in English and Japanese: `docs/guides/time-and-play.md`. Tests: `e2e/date-play.demo.ts` (the space view and the globes) and `e2e/realistic-play.demo.ts`; "nothing at all opens held" became "opens moving".

## 0.23.0 - 2026-11-10

- **The date follows the clock, and the demo has Play, Pause and Back** (MODULES-784, MODULES-755). `<chikyu-space>` sends `chikyu-timechange` with `detail: { time, running }`: while the clock runs (`speed` not 0) four times a second at most however fast the picture is drawn (as often as the clock steps at real time), only while the tab is shown, and once with `running: false` when the clock holds, so a page can write the date it stopped on. `<chikyu-earth-realistic>` sends it too while its `time="now"` clock steps (every `live-seconds`) and once when it is given a date. `chikyu-time` stays as the every-step event and is documented so. Setting `speed` to 0 now keeps the moment the reader last saw, and the clock goes on from there.
- **The demo's Time row is kazoku-ui's `<kazoku-replay-bar>`** next to the date field, in place of the Time speed buttons: Play runs from the date shown and the box follows it (never while the reader is typing in it), Pause holds it and writes the date reached into `time`, Back to the date returns to the date chosen, and riding along starts the clock. `play=on` and `speed` stay in the address, and the date when the clock stops or the reader leaves. The space view opens held; `speed=0` links stay held, links that name a speed and no `play` keep running, and a reader who prefers reduced motion gets Play left off. Guide in English and Japanese: `docs/guides/time-and-play.md`. Test: `e2e/date-play.demo.ts`.

- **Play for the realistic Earth: `<chikyu-earth-realistic>` has a `speed`** (MODULES-799), with `<chikyu-space>`'s name and rules. `speed` is how many seconds pass for each real second (`0` holds, `3600` an hour a second, `86400` a day a second, negative runs backwards); the clock runs on from the date shown, and the Sun's light, the night side and the clouds follow it. Draws are at most 30 a second (as often as the Sun's turn moves a pixel, once a second at least, one step a second for a reader who prefers reduced motion), and nothing is drawn while it holds, is out of sight or is in a hidden tab. `chikyu-timechange` follows the same rules as the space view's: four a second at most while it runs, and once with `running: false` when it holds (a date set, or `speed` set to 0). Old links keep working: with no `speed`, `time="now"` still follows the real clock (the Sun and clouds put right every `live-seconds`) and a date still holds. `time` now reads the moment reached while the clock runs. New export `readSpeed`. The demo's Play bar runs the realistic look too: Play from `now` starts from the moment shown and writes it into `time`, Back returns to following the real clock when the date was `now`, and `play` and `speed` stay in the address. Guide section in English and Japanese: `docs/guides/time-and-play.md`. Tests: `e2e/realistic-play.demo.ts`, and the clock added to `e2e/freeze.demo.ts`.
- **A flaky test mended, and one empty draw removed** (MODULES-808). `e2e/tiles.gl.ts` "tiles that arrive one after another are a few draws" failed in CI with 7 draws against a limit under 7 (4 tiles, and the limit was the tiles requested plus 3). Measured frame by frame, with the tiles answered after different waits (the slow route that reproduces it: 7 or 8 draws in 4 runs of 10): the element draws at most once in a frame, never faster than 30 a second, and a tile that arrives in its own frame is one draw. The test was wrong in two ways. It counted from before the zoom, and the same zoom also swaps the package's own pictures for sharper ones (day, night, clouds and water, a draw each, up to four, within the first 100 ms and before any tile has arrived), which are draws the tiles did not ask for; and "requested plus 3" is a fixed number for a count that depends on how the arrivals fall across frames. It now checks the rule itself, for tiles answered at once, one after another and in clumps, watching the page's frames: at most one draw in any frame, no more draws than the frames that had something new to show (a tile arrived, or a sharper picture was swapped in) plus the zoom's own draw, and at most 30 a second. A second CI run of the new test showed the rule was not yet exact: 6 draws against 4 frames with news plus 1. The extra was a draw with nothing new in it. When a second tile arrived a few milliseconds after the first and before the draw the first had asked for, the draw gate set a timer and drew again 33 ms later, after the first draw had already shown both tiles. `Gate` has a new `drawn()`, which `<chikyu-earth-realistic>` calls at the start of every draw; from then on an ask made after a run and before its draw begins is dropped, since that draw reads the state as it is when it runs, so what arrives in one frame is one draw. A draw that never begins no longer holds asks back for more than the gap. The space view's gate is unchanged. Tests: `test/realistic.test.ts` and, with the frames listed in its failure message, `e2e/tiles.gl.ts`. The other tests that count draws (`e2e/realistic.gl.ts`, `e2e/freeze.demo.ts`, `e2e/markers.gl.ts`) count rest, bursts of asks in one task or a rate over a fixed time, none of them by how arrivals fall.
- **A flaky test mended** (MODULES-800). `e2e/ride.gl.ts` "a reader who asked for reduced motion gets a jump and one step a second" failed about 3 runs in 4 on a loaded Mac: `freezeClock` paused the page's clock 50 ms past the time it had just read, and by then the clock had moved on, so `pauseAt` threw "Cannot fast-forward to the past". The pause is now 3 s ahead of the page's own time, and the glide test uses the same helper. The same sweep: a hold (Pause, a speed of 0) leaves one last frame already queued, and drawing it is right, but on a loaded Mac it landed after the 800 ms the "nothing is drawn while paused" tests allowed (`e2e/date-play.demo.ts` failed 2 runs in 3; the freeze test of the space clock had the same wait). `untilStill` in `e2e/gl.ts` waits until the draw and frame-request counts are the same a second apart (and fails after 20 s if frames keep coming) before the test measures rest; the element was not at fault.
- **Two more flaky tests mended** (MODULES-804, MODULES-805); the element and its pages are unchanged. `e2e/passes.demo.ts` "the satellite, the days, all passes and the darker sky change the list" ran out of its 5 s waits in CI. The list was never slow (worked out in 30 to 150 ms): in the desk and phone Chromium projects, which draw WebGL in software, the page's own pictures were drawn by the same emulated GPU too, and the passes page's world map alone kept that GPU busy for 5 to 10 s, from about a second after the page opened, in which the page drew no frame and answered no click (a click took 6 s; the whole test, 9 to 12 s, now takes under 1 s). Those two projects now rasterize the page on the CPU (`--disable-gpu-rasterization`; WebGL is still drawn in software), and the test waits for the count the page sets when it has made the list (`#data-note[data-passes]`), for up to 20 s, not for the `days` attribute that changes the moment the button is pressed. `e2e/ride.gl.ts` "paused it rests, and out of sight or in a hidden tab it draws nothing while the clock runs" took 20 to 60 s of its 60: 15 s of its own waits, and up to 44 s of waiting for the software GPU to finish the 33 s of frames the test before it (the frame-rate test) had asked for, which the browser made this test wait for with its clock running. That test now ends with `drainGpu` (a one-pixel read, in `e2e/gl.ts`), draws 2.5 s windows instead of 4 s, and the paused, out-of-sight and hidden-tab checks are three tests on the test's own clock (about 6 s each); the out-of-sight and hidden-tab tests now prove the ride is drawing in sight at 60x first, and the hidden-tab test no longer leaves the globe scrolled out of sight (it was checking the same thing twice). "riding, stopping and riding again" spent 45 s of its 60 on fixed waits and now runs the glides and the four seconds on the test's own clock.

## 0.22.1 - 2026-11-09

- kazoku-ui 0.27: the globe and the space looks draw at most 30 frames a second while they move (KAZOKU-UI-91), as the family's freeze rule asks; nothing else changes.

## 0.22.0 - 2026-11-09

- **When can I see the ISS? Passes over a place** (MODULES-677). A new entry point `@johnmorrisdotca/chikyu-earth/passes` (pure, needs `satellite.js`): `findPasses(sets, observer, { from, to }, options)` gives the next passes of the ISS, Tiangong, Hubble or any satellite over a place: the start, highest point and end (UTC, with the compass word and degrees at each, the height and the distance), the part that can be seen, why a pass cannot be (`daylight`, `shadow` or `faint`), the Sun's altitude and the sky it makes (`civil`, `nautical`, `astronomical`, `night`: civil twilight or darker counts as dark enough, and the pass says which), whether the satellite is in the Earth's shadow, and a magnitude from the satellite's standard magnitude (worked out from a rough size for the ISS, Tianhe and Hubble; others through `magnitudes`). Only visible passes by default, `all: true` for all. Also `satelliteAt`, `passPath`, `groundTrack`, `skySvg` (the dome as an SVG string, north up and east on the left, the track solid where lit and dashed in shadow, in any words), `sunAltitude`, `skyAt`, `compassOf`, `magnitude`, `standardMagnitude`, `ESTIMATED_CROSS_SECTIONS` and `STANDARD_MAGNITUDES`. Each pass says how old its elements are (`elementAgeDays`, `stale` after two weeks; a pass more than 30 days from its elements is left out). Checked against Skyfield with the Python `sgp4` and DE421, whose numbers are kept in `test/recorded/` (249 passes of the ISS, Tianhe and Hubble over London, Sydney, Quito and Tokyo: every rise, highest point and set within 1 second, direction within 0.06 degree, height within 0.005 degree, 746 of 747 moments agreeing on sunlight; made by `scripts/passes-reference.py`), and by hand against a sky-watching site's published predictions on 2026-11-09 (all 249 found within 2 seconds, same compass words; none of its data is kept). The brightness is a model: `standardMagnitude(area, albedo)` from the Sun's magnitude, with rough cross-sections for the ISS, Tianhe and Hubble in `ESTIMATED_CROSS_SECTIONS`, good to a magnitude or two.
- **`<chikyu-passes>`** (`/passes/element`): the list of passes, the sky dome and the facts of the one pressed, in English and Japanese; `latitude`, `longitude`, `height`, `days`, `show`, `sky`, `satellite`, `from`, `min-altitude`, `time-zone` or `utc-offset`, `lang`, `selected`; the orbit data from the `elements` property or `elements-src` (read once, through `fetchElements`; never polled); it sends `chikyu-pass-select` and takes a `slot="ground"`.
- **The demo's page `passes.html` ("Passes over me") and `passes-embed.html`**: a place by the map, a search of cities and countries (kuni), the two numbers, six quick places or "My location" (asked for only on a press), the satellite, 3 to 10 days, visible or all passes, civil or darker sky; the list, the sky dome and the ground track on the globe of the pass pressed, all in the address; the code for every way a page is made (the family's embed panel) and the iframe. The orbit data are the demo's own files, read once; the scheduled build also writes `elements/bright.json` (the ISS, Tianhe and Hubble as OMM JSON). Guide in English and Japanese: `docs/guides/passes.md`; examples `examples/node/passes.mjs` and `examples/passes.html`, tested.

## 0.21.0 - 2026-11-09

- **kazoku-ui 0.26: a plain drag always turns, and lighter sheets for children** (KAZOKU-UI-87, KAZOKU-UI-86, MODULES-743). On the globe and the views that turn, a plain drag (and one finger) now turns at every zoom; the middle or right button, Ctrl or Command and a drag, Space and a drag, and the wheel move; the Move or Turn choice is gone. The printable sheets for children draw their outline at kazoku-ui's kid line, 1.2 mm (was 3), and the lines inside at 1 mm (was 2.5), so a sheet is lighter and the names have room; the header's Name is a line to write on.

## 0.20.0 - 2026-11-09

- **Wide is theatre mode** (MODULES-717). Wide gives the globe the page's own column, centred, out to where the side panel was; the page no longer stretches to the window's edges.
- **The demo has a Wide layout and shows its zoom readout** (MODULES-717). kazoku-ui's `<kazoku-wide-toggle>` (and the T key, and `?wide=on` in the address) gives the globe the page's whole width, 16:9 and no taller than 80% of the screen, with the bar under it and the controls below as a row of boxes; the line globe, the realistic Earth and the space view all grow to the room, stay round, and the 3D looks draw again at the new size inside the renderer's caps. On a phone it is one column and there is no button. The toggle speaks the page's language. The shared bar's zoom readout (`2.4×`, between zoom out and zoom in; tap it for Fit) is checked on the buttons, Ctrl and the wheel, and a pinch. Demo and tests only: the package's code is unchanged. kazoku-ui is `^0.24.0`.

## 0.19.0 - 2026-11-09

- **Printable sheets** (MODULES-686). A new entry point `@johnmorrisdotca/chikyu-earth/sheets`, pure SVG strings in millimetres, no browser and no dependency: `globeSheetSvg` (the globe to colour on three sides, the continents in 3 mm outlines with no border between two countries of one continent, Russia cut at the Urals, the continents and oceans named), `worldMapSvg`, `countrySheetSvg` (the country's outline, its capital as a star when given, a box to draw the flag, the continent and the countries it touches), `dayNightSvg` with `terminator` and `dayNightView` (the line between day and night is the great circle 90 degrees from the package's own `subsolarPoint`, the night side hatched with plain lines so black and white prints well), `seasonsSvg` (four Earths round the Sun, tilted 23.4 degrees, toward the Sun in June and away in December), and the helpers `continentLines`, `landShares`, `countryShape`, `countryCodes`, `thickPath`, `hatchPath`, `earthFacts`, `dayNightFacts`, `seasonsFacts`, `countryFacts`, `TITLES`, `SAY`, `PLACES`. A4, US Letter, A3, Tabloid; English and Japanese; `kid` type (3 mm outline, 2.5 mm lines, names 24 pt, facts 18 pt) or `normal`; three facts on every sheet. The demo has a new page, `kids.html` (a row of sheets, the paper, the type, a date and time, Print / save PDF with kazoku-ui's print part, and a flag from hata to check a drawing against, never on the sheet; capitals from kuni; both for the demo only), and the Pages build makes ready-made PDFs (`scripts/make-pdfs.mjs`). `@johnmorrisdotca/kazoku-ui` moves to ^0.22.0, `@johnmorrisdotca/kuni` and `@johnmorrisdotca/hata` join as dev dependencies. Guide in English and Japanese: `docs/guides/printable-sheets.md`.

## 0.18.0 - 2026-11-08

- **Every live view zooms, pans and turns by itself** (MODULES-643): `<chikyu-earth>`, `<chikyu-earth-realistic>` and `<chikyu-space>` carry kazoku-ui's controls through `carryControls`: drag, two-finger pinch, Ctrl and the wheel (a plain wheel at Fit scrolls the page), the keys, with no bar. `controls="none"` takes them off; `zoom-min`, `zoom-max`, `tilt-max` change the range; `element.controller` is the controller behind them. A `<kazoku-view-controls for="...">` on the element takes the hands over and reads the element's range. The ranges (tilt to either pole): the line globe 0.1 to 20 times (Natural Earth 1:110m, redrawn at each zoom; about 640 km across at 20 times); the realistic Earth 0.1 to 5, raised to 20 by the element itself when its `tiles` are found; the space view a millionth to 2.5, and 0.5 to 6 while riding from a body (the element sets and removes `zoom-min` and `zoom-max` itself, unless the page set them). The line globe's `setView` redraws the Auto-turn about once a second by itself, so a page no longer keeps that clock. The demo's bar is now `for` the element (not a wrapper), the code builder's preview frame and the example pages carry the hands, and `examples/controls.html` is the new pattern. The embed page takes the hands by default (as wakusei-planets' does): drag, pinch, Ctrl and the wheel, the keys, with a plain wheel at Fit scrolling the host page, in a frame of any size; `hands=0` makes it a still picture, `turn=auto` still turns it by itself and `turn=1` is accepted and does nothing more, and the code builder's preview frame and iframe code need no `turn`. `@johnmorrisdotca/kazoku-ui` (^0.21.1) is now a dependency, not an optional peer. Guide in English and Japanese: `docs/guides/zoom-and-pan.md`. Tests: `e2e/zoom.demo.ts` (demo, builder, embed, at desk and phone sizes), `e2e/zoom.gl.ts` (the 3D looks and the tile limit), the usage script's CDN, Vite and space examples; all through `e2e/hands.ts`.

## 0.17.0 - 2026-11-08

- **Sharp close zoom on the realistic Earth, from finer map tiles** (MODULES-645, the loader): `<chikyu-earth-realistic tiles="/tiles/">` (also `earth.tiles`) reads the tile set's `manifest.json`, picks the level from the zoom and the canvas (about one texel to a device pixel; day level 3 then 4, night level 2 then 3), loads only the tiles in view, six at a time, the middle first, and lays them over the package's pictures, which stay as the far view and the fallback. At most 48 tiles are held (about 70 MB of graphics memory); a tile that leaves view is kept 4 seconds and then freed, the oldest first when over the limit; the level drops when the tiles in view would be more. Each tile that arrives asks for one draw (30 a second at most, eight new tiles to a draw); nothing is drawn at rest or out of sight, a lost context comes back with the held tiles, and without the option, without a manifest or for a tile that fails the Earth is drawn as before. A device with no 4096 picture (`max-texture` under 4096, or 2 GB or less of memory) uses no tiles. `earth.stats.tiles` and the `chikyu-tiles` event say what it is doing. New pure parts in `/realistic`: `tileLevel`, `tilesInView`, `coveringTile`, `pointOnEarth`, `tileRect`, `tileColumns`, `tileRows`, `parseManifest`, `TEXEL_SLACK`, `TILE_LIMIT`, `TILE_KEEP_MS`. **The demo's zoom limit on the realistic look goes from 5 to 20** when its tiles are found (the finest tile level is 4 times the widest picture) and stays 5 when they are not. Tests: the level and tile maths (the antimeridian, the poles, a tile bigger than the box) in `test/tiles.test.ts`; a made-up tile set in `e2e/tiles.gl.ts` (requests, drawing over the base, freeing after zoom-out, night tiles, failed tiles, a lost context, batching); a tiles round in `pnpm test:freeze` (GPU objects flat over six zoom rounds). Guide in English and Japanese: `docs/guides/earth-tiles.md`.
- The demo moves to kazoku-ui ^0.21.0, whose default zoom range is 0.1x to 50x; the flat globe and the embed page keep their 1x to 5x with `zoom-min` and `zoom-max`.
- **Earth tile pyramid, the data** (MODULES-645, first phase): `scripts/make-earth-tiles.py` (`pnpm tiles`, `pnpm test:tiles`) cuts NASA's Blue Marble Next Generation (September 2004, with bathymetry, 21600 x 10800) and Black Marble 2016 (3 km, 13500 x 6750) into 512 px WebP tiles, day to level 4 (16384 x 8192), night to level 3 (8192 x 4096): 852 tiles, 10.3 MB. Seamless at the antimeridian, tested on a made-up map in CI. Built by `pages.yml` and served at `/tiles/` beside the demo; never in git, never in the npm package. Guide in English and Japanese (`docs/guides/earth-tiles.md`); sources and terms in NOTICE.md.
- **Why two packages** (MODULES-521): a guide in English and Japanese (`docs/guides/two-packages.md`), a README section and a Guides row say that chikyu-earth is for the Earth only, that the solar system is wakusei-planets', and that the dependency runs one way. Two tested examples: the two packages on one page (`examples/together/`, built and opened by `pnpm test:usage`) and every entry point bundled with wakusei-planets missing.
- Tests: the ride's glide is measured on the page's own clock, and the Auto-turn step of the drag-rule test turns by an angle read from the controller, not by a 1.5 s stopwatch; the docs site's browser test is the family's newer one (WebKit on a Mac is pressed with Alt+Tab) (MODULES-629).

## 0.16.0 - 2026-11-08

- **Space Shuttle flights and the Hubble visits** (MODULES-623), in `@johnmorrisdotca/chikyu-earth/satellites`: `missions()` (the 135 flights, STS-1 to STS-135, with orbiter, liftoff and landing in UTC, the people NASA lists, the main payload in English and Japanese, the catalogue number, and `hubble` on STS-31, 61, 82, 103, 109 and 125), `missionOf(id)` (`"STS-31"`, `"31"`, `31`), `missionElements(file)` and `missionPosition(sets, ms, flight?)` (latitude, longitude, height and speed of the craft at a moment, from the element set nearest in time, by the same SGP4 as `createSatellites`; nothing before liftoff or after landing; nothing from elements over two days away). New types `Mission`, `MissionPosition`, `MissionFile`, `Orbiter` and `HubbleVisit`. Facts: NASA's mission pages (public domain, read 2026-11-08, listed in NOTICE.md).
- **The demo replays them**: in the space look a Space Shuttle flights row (the Hubble visits and each orbiter's flights as buttons, then the shared replay bar at 600, 3600 and 21600 times real speed) puts the orbiter, and the telescope on its flights, on the globe over the flight's days. The address keeps `mission=` and `time=`. The element sets are `missions/<id>.json` on the demo site (134 files, about 3,100 sets, 410 kB, 180 kB compressed): Space-Track's `gp_history`, asked once with `scripts/missions.ts elements`, cleaned with `clean`; not in the npm package. Data from Space-Track.org (USSPACECOM).
- Tests: the facts held to the source list read from NASA (`test/recorded/nasa-sts-*.json`), the files to Space-Track's catalogue dates, and a replay's ground track against a second, independent propagator (two-body motion with the J2 drift, its own sidereal time): within 60 km for 90 minutes either side of each element set. `e2e/missions.gl.ts` plays it in the browser. A guide and its Japanese twin: `docs/guides/missions.md`.

- **Space-Track.org as the scheduled build's second satellite source** (MODULES-614). After CelesTrak's round, a group whose file is more than 12 hours old is asked of Space-Track's GP class for the catalogue numbers it already holds, at most once in 22 hours for each group, in one login with a six-second pause between asks, stopping at the first answer that is not 200. The login is the Actions secrets `SPACETRACK_USER` and `SPACETRACK_PASSWORD` (locally the same variables or `~/.config/spacetrack/spacetrack.env`), sent only in the login request's body and never printed or stored; without them the build says "CelesTrak only". A group's file and `manifest.json` carry `"source": "spacetrack"` and the demo says so under the globe with the citation "Data from Space-Track.org (USSPACECOM)". Terms and the section read: `docs/satellite-sources.md`, `NOTICE.md`. Demo site only: the package still ships no elements. Tests: `test/spacetrack.test.ts` on a recorded answer and a made-up Space-Track.
- The browser tests and the Chromium scripts take kazoku-ui's browser lock (kazoku-ui ^0.20.0, MODULES-619).

## 0.15.0 - 2026-11-04

"Put it in your page" is the family's embed panel, on the demo and on the code builder (MODULES-348). No change to the package's drawings.

- **The demo's "Put it in your page" and the code builder are kazoku-ui's `<kazoku-embed-panel>`** (kazoku-ui ^0.15.1). Nothing they had is gone, and a test counts it: the ten places, the three looks, the graticule, the four sizes (240, 320, 420, 560), HTML, module, React and iframe tabs with the same code, Copy (now "Copy code"), Open the embed page, Read the docs, the credit line, and the picture of the globe beside the code (on the builder the realistic look is shown by the embed page in a frame, as before).
- **Added by the panel**: Vue, Angular and Svelte tabs, a picker for the places, and a note on the iframe tab ("One iframe, no script of your own"). The demo's page, which had one fixed iframe and no Copy button, now has the whole panel; the realistic look shows there as the flat globe, so the page never runs a second WebGL view.
- **The code**: `demo/embed-code.ts` writes every tab (the shared snippets with this package's element and attributes) and `test/embed-code.test.ts` runs the module against a stand-in page, compiles the React, Vue, Angular and Svelte code, and holds every import to the package's exports and every attribute to ones the element reads. The HTML tab is now the script tags and the tag (it was a whole page), and the CDN address carries the version.
- `scripts/check-standard.mjs` is kazoku-ui 0.15's (the `embed-panel` item); the demo moves to `@johnmorrisdotca/kazoku-ui` ^0.15.1.

## 0.14.0 - 2026-11-03

The family's speed buttons, in the demo's two places that run time (KAZOKU-UI-46).

- **Auto-turn has 0.5×, 1× and 2×.** The demo's view controls come from kazoku-ui 0.14: under More, the Earth's Auto-turn takes the shared speed buttons (they were Slow, Medium and Fast), 1× being the Earth's own rate of 0.004178 degrees a second. The choice is the controls' `pace` attribute and the address' `pace`.
- **The space view's Time row is `<kazoku-speed-buttons>`**: `0 1 3600 86400 -3600`, read as multiples of real time (0× holds it still, 3600× is an hour a second, 86400× a day a second, −3600× runs back), in the same look as Auto-turn's. It replaces the page's own five buttons ("Paused", "Real time", ...); `?speed=` still keeps the choice and Now still puts it back to 1×.
- `kazoku-ui` is `^0.14.0` for the demo (the optional peer is unchanged). Tests: `e2e/speed.demo.ts` (the controls' buttons and the time row, desk and phone, Chromium and WebKit, with the config's reduced motion) and `e2e/speed.gl.ts` (a press sets the clock and the address; Now returns to 1×).

## 0.13.0 - 2026-11-03

The demo's elements refresh by themselves, every satellite shows its age, and you can bring your own source (MODULES-261, steps 3 and 4).

- **A scheduled build refreshes the demo's element files every six hours** (`.github/workflows/pages.yml`, `scripts/elements.ts fetch`): one download of each of CelesTrak's 13 lists and 5 single satellites, a six-second pause between asks, a user agent that names the repository and a contact, a list not asked for again within 110 minutes, and a stop at the first answer that is not 200 (CelesTrak's rules for software, read 2026-11-03), keeping every other group's last file. A push carries over the files already on the live site and asks CelesTrak for nothing. A check refuses to publish a set with an empty or missing group or one older than 30 days. No server runs per view: the browser reads files on Pages. The embed page reads the same files, and takes any group (`&satellites=gps,weather`).
- **Age and dimming.** The page says how long ago the files were downloaded and each satellite's age. A satellite whose elements are more than 14 days from the time shown is placed but drawn dimmer (`createSatellites` option `dimAfterDays`, `Satellites.dimmed` and `dimVersion`, `DEFAULT_DIM_AFTER_DAYS`), and the page says why (its place is less exact); one more than 30 days away is left out. **`DEFAULT_MAX_AGE_DAYS` is now 30** (it was 14, where the satellite was left out): the 14 days is the dimming now. Still one instanced draw for a group, and the dimming costs one number a satellite, copied to the graphics card only when one changes.
- **Tests on recorded and made-up elements, never a live request.** The browser tests are served the recorded stations and Starlink of 2026-11-02 (`test/recorded/`, `e2e/recorded.ts`) so no position moves as the demo's files are refreshed; the file maker, the polite downloader (a made-up CelesTrak that answers 200, then 403), the age check and the dimming are unit-tested (`test/elements.test.ts`, `test/satellites.test.ts`), and the demo's dimming and notes in `e2e/groups.gl.ts`.
- **`fetchElements(url, options)`** (`@johnmorrisdotca/chikyu-earth/satellites`) asks an address you choose, in the visitor's browser, for OMM JSON, OMM CSV or TLE text and returns element sets for `createSatellites`, with `skipped` (what it left out, and why), `retrievedAt` and `fromCache`. It has no address of its own, and it is polite by design: https only (http on localhost), no cookies or referrer, no redirects; the same address is not asked again within two hours (the answer already read is returned from the page or from `localStorage`); any answer that is not 200, or none, leaves the address alone for an hour and throws an **`ElementSourceError`** (`status`, `retryAt`), using the answer already read meanwhile; at most 20 million bytes and 50,000 sets. `forgetElements()` is for tests.
- **`parseElements(text)`** reads the three formats with no request (so it runs on a server): OMM JSON (an array or one object, numbers as numbers or text), OMM CSV (quoted names) and TLE (two lines or three, checksums checked, the epoch, the implied decimals and the designator turned into OMM's fields); a TLE read this way flies to within half a kilometre of the OMM it was written from.
- **The demo has "Your own source"**: paste an address, press Load; the satellites become a "Yours" group you can show, find by name and ride. Nothing is asked until the visitor presses the button (an address in the page's own address only fills the box). It says how many were read and from where, what was left out and why, whether the answer was just asked for or kept (and for how long it will not be asked again), or why it could not be used. English and Japanese.
- Tests: made-up fetch and made-up TLE with real checksums (`test/source.test.ts`); in the browser a made-up address that the test serves, a refusal, something that is not elements and an http address, with a check that the page asked nothing else (`e2e/groups.gl.ts`).

## 0.12.0 - 2026-11-03

More satellites to follow and ride (MODULES-261, steps 1 and 2): where the data may come from, a curated catalogue, and fourteen groups in the demo.

- **`docs/satellite-sources.md`: every source's terms read and quoted** (CelesTrak, Space-Track, SatNOGS DB, N2YO, AMSAT, NASA and ESA, Wikidata), each with a tier (green, grey, red) and whether it may be fetched by the visitor's own browser, snapshotted on the demo site, or redistributed in the package. CelesTrak stays grey; Space-Track's blanket approval for passing on basic data (TLEs, OMMs) with a citation is noted; the decisions that are John's are one ticket (MODULES-333). The package still ships no orbital elements.
- **A curated catalogue** in `@johnmorrisdotca/chikyu-earth/satellites`: `SATELLITE_GROUPS` (fourteen groups: stations, famous, science, Earth observation, weather, geostationary, GPS, GLONASS, Galileo, BeiDou, amateur radio, OneWeb, Iridium, Starlink, each with its CelesTrak list or catalogue numbers, an orbit kind, whether it sits still, and a line in English and Japanese), `CATALOGUE` (about forty satellites by NORAD number, from the ISS and Tiangong to Hubble and Vanguard 1, the oldest satellite still in orbit, each with a line in English and Japanese), `findInCatalogue` and `catalogueEntry`. JWST is left out on purpose: it is not in Earth orbit. No elements in it.
- **The demo's groups are buttons** (a coloured dot each; a group switched on says what it is, and the demo zooms out to a group that goes far from the Earth), with **Find** (a search box over the catalogue and the names of every satellite in the demo's files, plus ISS and Tiangong) and two new rides, **The chosen satellite** and **One from the last group**. The address keeps the groups (`sats=gps,weather`), the chosen satellite (`sat=<NORAD number>`) and the ride (`ride=chosen`). A chosen satellite shows its catalogue line beside its height, speed and age.
- **`demo/elements/`** (demo site only): one file for each group, made from one download of each CelesTrak list on 2026-11-03, `manifest.json` and `index.json`; `scripts/elements.ts` makes them from downloaded lists and fetches nothing. Starlink stays at every fifth satellite (about 2,200 dots in one draw call); the others are whole (the geostationary list has 569).
- **Moons that have left the view are let go even when nothing else is drawn.** The space view let go of a moon four seconds after it left the view, but only when the next draw happened; a view at rest draws nothing, so the moons of Jupiter and Saturn were kept (their shaders and pictures) until someone touched the view. It now asks for one more draw when the first of them is due. Test: `e2e/space.gl.ts`. This is why the space soak failed in CI on "programs" since 0.11.0 (the count was never growing: the moons kept after leaving the view made it differ from one moment to the next); the soak now also looks at the Earth, on the day the view opened on (which moons of Saturn and Jupiter are in the view depends on the day), in sight and drawing, before it counts; the count came back to what it was in three of three local runs and the one-minute soak in CI.
- Tests: the catalogue and the file maker (`test/catalogue.test.ts`, `test/elements.test.ts`) and the demo's groups, Find and Ride on **made-up** element files served in place of the demo's own, with a check that nothing is asked of any other site (`e2e/groups.gl.ts`).

## 0.11.0 - 2026-11-03

The real Sun, planets, Pluto and moons in the space view.

- **`<chikyu-space>` draws the real bodies through its `BodyPainter` seam with [wakusei-planets](https://github.com/johnmorrisdotca/wakusei-planets) 0.5.0** (an optional peer): `setBodyPainter(painter)` with `painter` from `@johnmorrisdotca/wakusei-planets/painter`, and `bodies="realistic"` or `bodies="painted"` (`plain` for the old spheres) on the element, the Sun with its glow, banded Jupiter, Saturn with Cassini's rings, Mars, Venus, Mercury, Uranus, Neptune and Pluto, lit from the Sun in the scene's own axes. One WebGL context, nothing drawn at rest, bodies drawn at the view's rate cap; a picture arriving later asks for a redraw; sharper pictures are fetched only for a body that is big on the screen and let go when it is not. The demo draws them by default (Planets: Shaded, Painted, Plain), the ride along too; the embed takes `&bodies=painted`.
- **Pluto** joins the planets: `PLANETS`, `BODY_NAMES` (the names beside the bodies and `body = "Pluto"`), its orbit, its size in both scales.
- **The moons, at their planets, when the camera is near.** A painter's optional `moons(planet, ms)` says where they are (wakusei-planets: Mars's two, Jupiter's four, Saturn's seven, Uranus's five, Neptune's three, Pluto's three, from JPL's mean elements); the view shows them once the planet is 4 pixels across, at least 2 pixels each, in their order round it, and lets them go four seconds after they leave the view. `zoomFor("Jupiter-moons")` is the zoom that frames a planet with its nearer moons. `stats.bodies` counts what the painter made.
- **The seam grew, and kept its old shape**: `make(three, name, context)` may return a promise; a drawing may have `update({ toSun, ms, radiusPx })` and `dispose`; `BodyPainter` has optional `moons` and `looks`; new types `BodyMoon` and `PaintContext`. A painter written for 0.10 still works.
- **The embed page shows the space view** when asked for it: the globe it hides stayed in the page (an author `display: block` beat the `hidden` attribute), so `embed.html?look=space` and `look=realistic` showed the line globe and left the real view below it, out of sight.
- **kazoku-ui 0.11.0** for the demo: the Centre button and the zoom slider.
- **A drag turns the globe while it is going on** (MODULES-254). The line and thick globe redrew its projection only when the pointer was let go (a move made only a cheap transform), so it stayed still and jumped on release. `setView(view, final, live)`: with `live` (a hand is on the view, which is anything but the Auto-turn) the projection is also redrawn while it turns, at most 30 times a second. The demo, the embed page and the guides pass `event.detail.reason !== "auto"`. Test: `e2e/hold.gl.ts`, a real pointer that goes down, moves and is not let go, in the line, thick, realistic and space looks with the Auto-turn on and off.
- **kazoku-ui 0.12.0** for the demo (MODULES-234): the horizontal layout with the zoom slider, the **Centre** button (zoom in, drag the globe far off, press Centre and it is back in the middle at Fit and the default angle; the pan is held so the globe cannot be lost, and because the globe fills its square the controls' default hold, "the picture keeps covering the view", is the right one, so `object-size` is left out), and **exact grab**: `grab-radius="fit"` on the flat globe, the Earth from space with its disc's radius (the demo and the embed page set it; the guides and the README's examples carry `grab-radius="fit"`), so the touched point stays under the pointer (a drag of 31 px moves the ground at the middle by 31 px). The space view keeps the fixed angle, because its radius changes with the body and the scale. On a phone the horizontal layout's readout is Fit. Tests: `e2e/follows.gl.ts` runs kazoku-ui's shared `checkFollowsTheHand` (drag, arrow keys, Auto-turn west to east) and `checkExactGrab` in the line, thick, realistic and space looks (`e2e/ground.mjs` is kazoku-ui's `templates/e2e-ground.mjs`, unchanged); `e2e/centre.gl.ts` drags the globe far off, presses Centre and checks it is back, picture and all.
- **Always lit and Night boost** (MODULES-259): a ride on the night side is no longer a black frame. `light="sun"` (the true light, the default), `light="lit"` (the Earth lit as if by daylight from the camera's side, the day picture and no city lights) or `light="boost"` (the true terminator, with the night side raised so land and coasts read), on `<chikyu-space>` and `<chikyu-earth-realistic>`, as `element.light`, as three buttons in the demo (Light: Sun, Always lit, Night boost; English and Japanese) and in the address (`?light=lit`; the embed takes it too). The Sun, the Moon and the planets keep their true places. One uniform each and no extra pass. Tests: a night-side view is dark with the Sun and bright with Always lit and Night boost, and a ride on the ISS at a moment of its orbit in the Earth's shadow goes from nearly black (mean brightness 12 of 255) to 33 with Always lit and 18 with Night boost (`e2e/ride.gl.ts`).
- A guide, "The real Sun, planets, Pluto and moons", in English and Japanese.
- Documentation: an architecture guide with its Japanese twin, a code builder page (`builder.html`), a longer README whose examples run (`pnpm test:readme`), and every release of this changelog dated. No behaviour changed.
- The README opens with the package's thumbnail, and the demo carries it as its link preview (og:image) and publishes the card, a dark card and an icon on Pages at `thumbnail.png`, `thumbnail-dark.png` and `icon.png`.

## 0.10.0 - 2026-11-03

Three fixes for a page that puts the Earth behind something else.

- **A time and a view changed together are one draw** (MODULES-177). `time` and `setView` in one task each asked the rate gate; the first drew at once and the second 33 ms later, so a page moving the Sun and the camera on every tick drew twice. `Gate.soon()` makes every ask of one task a single ask, made when the task ends, and the realistic element uses it. Measured before: 2 draws for the two changes, now 1 (`e2e/realistic.gl.ts`).
- **`max-ratio`** on `<chikyu-earth-realistic>`: the most device pixels to a CSS pixel the canvas is drawn at (2 at most; `0.5` draws at half the size and scales it up). It is read when the element connects and is the shared renderer's cap for the page; the textures are chosen for it too. Test: at a device ratio of 2, `max-ratio="1"` draws a canvas under a third of the pixels.
- **A strict Content-Security-Policy no longer refuses the elements' styles** (MODULES-180). `<chikyu-earth>`, `<chikyu-earth-realistic>` and `<chikyu-space>` wrote a `<style>` into their shadow roots, which `style-src 'self'` blocks. They now adopt a constructable stylesheet (shared by every element with the same text), and where a browser has none, a `<style>` carrying the element's `nonce`. Test (`e2e/csp.gl.ts`): each element in a page served with `style-src 'self'` reports no violation, its styles apply, and no `<style>` is written.
- **`setSharedRenderer(renderer)`** (`@johnmorrisdotca/chikyu-earth/realistic/element`; MODULES-171): the page hands the Earth and the space view a renderer made with kazoku-ui's `createSharedRenderer`, so a page that draws other things with it keeps one WebGL context. The page owns it: its `maxRatio` and `onContext` apply and the elements never dispose it. Call it before the first element connects (it throws while one is in the page). Unit-tested (`test/shared.test.ts`).

## 0.9.1 - 2026-11-02

The ground now follows the pointer, in every look and when riding.

- **The Earth turned the wrong way up and down** (MODULES-200). A drag up made the ground go down in the line, thick, realistic and space looks, and the up arrow did the same: the controls' tilt was added to the latitude of the view, and it should be subtracted (the top of the globe tips away as the tilt grows, as the controls say). It is now one sign in `lookAt` and `projectionView` (`src/view.ts`) and one in the space view, so the flat globe, the realistic Earth and the space view agree. **A tilt in an address or a call now tips the other way.**
  Left and right were right already. Auto-turn turns the real way: the Earth goes round west to east, so with north up the ground moves from left to right, the same way as a drag right and the right arrow.
- **A ride could not be dragged** (MODULES-199). Riding at a body, a drag turned the camera's head round the straight-down line, which from the ISS only spun the picture, and tilt could not go the other way past the straight-down look, so a drag seemed to do nothing. `ridePose` now looks about from the base look as a head on a pivot does: yaw turns the camera to its left and tilt tips it towards the bottom of its picture, so a drag right moves the ground right and a drag up moves it up, about one and a half pixels a pixel, the pace of the line globe and the Earth from space. The angle for a pixel follows the field of view, so zooming in does not make the ground race. Behind a satellite (`view: "follow"`) the drag is mirrored, because the Earth is behind what the camera looks at, and the Earth follows the pointer.
- **The demo keeps the address's yaw and tilt when it opens on a ride** (it set both to 0 as the ride began), and **an address with `ride` and no `look` opens the space look**, so the reported address rides the ISS.
- **Tests**: `e2e/drag.gl.ts` drags with a real pointer, presses the arrow keys and runs Auto-turn in the line, thick, realistic and space looks, riding the ISS (down and at the horizon) and the Moon, and behind the ISS and the Moon, and checks which way the ground moved by sliding the first picture over the second; and that a ride opens with the address's turn, a drag writes it back and the address brings the same picture back; and the reported address. All fail on 0.9.0. Unit tests for `ridePose` and the view's signs.

## 0.9.0 - 2026-11-02

Ride along: the camera on the ISS, a Starlink satellite, the Moon or a planet, looking at the Earth.

- **`element.ride(target, options)`** on `<chikyu-space>`: the camera sits at a moving body at its real place for the moment shown and looks at the Earth, with the way the body is going at the top of the picture; the Earth turns and slides beneath it as the body goes along its orbit
  (an ISS view goes round in about 93 minutes). `target` is a body name (`"Moon"`, `"Mars"`, ...) or a satellite of a group (`{ group, index }`). Options: `view: "from"` (the default) or `"follow"` (a fixed distance from the body, looking at it; `distanceKm` for a satellite), `look: "down"` (the default) or
  `"horizon"` (tipped forward until the horizon is a little above the middle), and `smooth`. The shared controls' tilt tips the camera further, their yaw turns it round the straight-down line, their zoom narrows the 60 degree field of view. Time is the page's clock, forwards, backwards, faster or slower.
  `element.riding`, the `chikyu-ride` event, and `chikyu-ride-lost` (the satellite could not be placed on this date: its elements are too old; the ordinary camera comes back). A ridden satellite is placed exactly, one SGP4 call a frame, at any speed, even where its group is hidden.
- **Switching is smooth**: another `ride` call glides the camera's place, its turn (spherical interpolation) and its field of view from where the last draw left them to the new camera over 1.2 seconds, eased; reduced motion jumps. `ride(null)` stops.
- **`ridePose(input)`** (`@johnmorrisdotca/chikyu-earth/space`, pure, no browser): where the camera looks, for a place, a way of travel, a look and the controls' yaw, tilt and zoom. Unit-tested (looking down at the Earth's centre, the way it goes at the top, the horizon look, tilt, yaw, zoom, no way of travel).
- **Budget, each line tested** (`e2e/ride.gl.ts`): the camera is within 1 km of satellite.js's own place for the ISS and 420 km up; at 60 times real time it goes round the Earth at the ISS's rate (301 game seconds: 19.4 degrees, 19.4 expected); riding the Moon puts it 10 Earth radii away in the compressed scale and 55 to 66 in the true one;
  it animates continuously but at most 30 frames a second (the ISS at real time 6.5 a second, at 60 times 28.5, Mars at a day a second 28.5); paused, 0 GL draws and 0 frame requests; scrolled away or in a hidden tab, 0 GL draws at 60 times; reduced motion 1.00 frames a second at 60 times, and a jump instead of a glide; the glide from the ISS to the Moon takes 1.4 s
  and then rests; a satellite too old for the date gives `chikyu-ride-lost`; two more rounds of six switches add no buffers, textures or vertex arrays; a lost context comes back with the ride. The freeze test has a fourth look, the space view riding the ISS (and the look-changing rounds ride the ISS and the Moon). The ten-minute soak rides every
  way (the ISS, Tiangong, a Starlink satellite, the Moon, Mars, from it and behind it, down and at the horizon) while it adds, removes and chooses satellites: 965 steps, JS heap 14.35 to 14.51 MB after garbage collection, GPU objects 123 to 123, one WebGL context, no error.
- **The Auto-turn of the controls no longer draws thirty times a second in the space view.** Its turn at the Earth's own rate moves nothing visible in seconds, but every frame of it asked the space view for a draw. `setView(view, final = true)` now keeps a turn that moves less than half a pixel for the next draw and does not draw for it unless `final` is true:
  8 seconds of Auto-turn now make 0 draws (the controls ask for 480 animation frames in that time). This holds for the Earth's views, for riding, and for satellites.
- **Demo**: a "Ride along" row in the space look (ISS, Tiangong, a Starlink satellite, Moon, Mars, Stop; View: From it or Behind it; Looking: Straight down or At the horizon), with a line saying what is ridden, in English and Japanese (the Japanese page is tested for English words left in a control). The choices are kept in the address (`ride`, `rview`, `rlook`).
  The embed takes `ride=iss|css|starlink|Moon|Mars`, `rview=follow` and `rlook=horizon`; its test: one context, the ISS's height, nothing drawn at rest, a Moon ride at a day a second capped.
- **Docs**: a ride-along guide in English and Japanese, a page for it (docs/ride-along.md) and every new export with TSDoc and an example, usage examples run by `pnpm test:usage` (a Vite page that rides the ISS and is opened in a browser; `ridePose` in Node), README section, screenshots. The space view has no markers (those belong to the flat and the realistic globes), so the ticket's "markers stay on the ground" has nothing to do here.
- The names beside the bodies are not drawn for the body being ridden (the camera is inside it) and the Earth's is not drawn when riding at a body.

## 0.8.0 - 2026-11-02

Satellites on the space view, the space view in the embed, and the demo's space controls in Japanese.

- **Satellites** (`@johnmorrisdotca/chikyu-earth/satellites`, new, and `<chikyu-space>`): `createSatellites(elements)` turns orbital elements into positions with SGP4, and `space.setSatellites("stations", group)` draws them: a group is **one draw call** however many it holds
  (`THREE.Points`), each shown or hidden by name (`showSatellites`), with their orbits (`orbits: true` for a group of 40 or fewer), a ring and an orbit for a chosen one (`selectSatellite`, `satelliteInfo`) and `chikyu-satellite-click` for a press on one
  (not on one behind the Earth). **The package fetches nothing and ships no orbital data**: your page passes in elements in CelesTrak's GP JSON format (`ElementSet`), and the guide has the rules for getting them (CelesTrak's usage policy; Space-Track's
  agreement does not let an account holder pass data on, so it is not used). Elements more than 14 days from the moment shown (`maxAgeDays`) are left out. [docs/satellites.md](docs/satellites.md), the [satellites guide](docs/guides/satellites.md) (and in Japanese).
- **SGP4 about once a second, not once a frame**: satellite.js 6.0.2 (MIT, a new optional peer dependency; 10 KB gzipped, plain JavaScript; version 7 pulls WASM helper files that bundlers choke on) is run for the whole group at two moments a step apart, and every
  position between is an interpolation (a metre at 1 second, a few kilometres at 60). Above 60 times real time the groups are hidden and SGP4 does not run (`MAX_SATELLITE_SPEED`); a chosen satellite is still placed exactly. The package's own part is 2.7 KB minified
  for the maths and 5.1 KB for the drawing (3.6 KB gzipped together). A unit test checks that a satellite's longitude from the scene's axes and sidereal time agrees with satellite.js's own within 0.02 degree, and an end-to-end test centres the view under the ISS (worked
  out in the test) and finds it in the middle of the Earth's disc.
- **Budget, each line tested** (`e2e/satellites.gl.ts`, 6,000 made-up satellites spread round their orbits, together with the demo's 2,252 real ones): paused, 0 GL draw calls, 0 frame requests and 0 SGP4 calls in 3.5 s; at 60 times real time 29.0 frames a second, 8,242 SGP4 calls a second (one for
  each satellite), 34.2 GL draw calls a frame against 33.4 without the 6,000 (the group is one), 0.09 ms of JavaScript a frame on average and 2.6 ms for the longest SGP4 batch of 8,252; at real time 1.00 frames a second and 2,249 SGP4 calls a second for 2,252
  satellites; at 3,600 times real time the groups are hidden, 0 SGP4 calls and 29 frames a second; with reduced motion 1.00 frames a second at 60 times; nothing drawn out of sight or in a hidden tab; a group taken away frees its buffer; a lost context comes back with the
  satellites. The freeze test has a third look, the space view with satellites on, and its look-changing rounds show the stations and Starlink every time (GPU objects flat at 85 after the warm-up round). The ten-minute soak adds and removes the 6,000, chooses satellites and runs
  past the speed limit: 964 steps, JS heap 13.73 to 14.04 MB after garbage collection (while the 6,000 are on it is 20.4 MB, and it returns), GPU objects 123 to 123, 28.5 frames a second on average, one WebGL context. The soak and the new tests now run with no motion preference, at the full 30 frames a second.
- **Demo**: a "Satellites" row (Stations, Starlink, and Find: ISS, Tiangong) in the space look, and a line about what is chosen (name, height, speed, period, age of its elements). It uses **one snapshot of CelesTrak's lists from 2 November 2026** in a file of the demo site's own
  (`demo/celestrak-snapshot.json`, 330 KB, 105 KB gzipped, fetched only when a group is asked for): all 20 stations and every fifth Starlink satellite (2,232 of 11,156), credited on the page and in NOTICE.md. A snapshot more than 14 days old shows the day it was taken instead of today.
  `scripts/make-satellite-snapshot.mjs` makes the file from two downloaded lists and fetches nothing.
- **The space view in the embed** (`embed.html?look=space`): `time`, `speed` (still by default), `scale`, `body`, `zoom` (earth, moon, sun, inner, solar-system), `orbits`, `labels`, and `satellites=stations,starlink` with `sat=25544`. One context, a capped canvas, no controls, nothing but its own files, 0 draws at rest,
  at most 30 a second at a day a second, nothing in a hidden tab (`e2e/embed.gl.ts`). The embed guide, in both languages, lists them.
- **Japanese for the demo's space controls**: Space, Time, Scale, Go to, Look at, every body's name, Orbits, Names, the scale note, the body and satellite facts and the notices, through `demo/words.js`; the names drawn beside the bodies change too (`element.bodyNames`, `element.bodyHint`). A browser test opens the Japanese
  page and fails on any English word left in a control, apart from ISS, Starlink, CelesTrak, SGP4 and km.
- **Docs**: a satellites guide in English and Japanese, a page for the new entry point and every export (TSDoc and an example each), a usage example run by `pnpm test:usage` (a Vite page with the ISS on the space view, opened in a browser and made to place it; and the same elements in Node), README section, and screenshots.
- `ThreeParts` has an optional `Points`: a three.js subset handed over by `setThreeLoader` needs it only for satellites (the demo's `three-subset.ts` has it).
- The CHANGELOG of 0.7.0, whose published tarball showed the family-parts notes under the 0.6.0 heading, is as fixed in 6f26012; this entry is under its own heading.

## 0.7.0 - 2026-11-02

The space view can look at any body, bodies can be chosen, and how the Sun and the planets are drawn is a seam another package can fill.

- **Look at a body**: `element.body = "Mars"` (any of Earth, Moon, Sun and the seven planets) points the camera at it; at zoom 1 it fills the view, and the shared controls turn the camera round it and zoom in and out from it. The demo's "Look at" row does it.
- **Bodies can be chosen**: each name beside a body is a real button (Tab and Enter), and a press on a body (not a drag) fires `chikyu-body-click`; `chikyu-body-focus` for the keyboard. The event carries `name`, `radiusKm` and `distanceKm` (`element.bodyInfo(name)` gives the same for a caption); the demo prints "Jupiter: radius 69,911 km, 666,000,000 km from the Earth".
- **A seam for drawing the bodies** (`BodyPainter`, `setBodyPainter`, `plainPainter` from `@johnmorrisdotca/chikyu-earth/space`): the space view keeps each body's place, size, light direction, name and orbit, and asks a painter only for what to draw there (an object of radius 1; `light(toSun)` each draw; the Sun's turns to face the camera). The default is what 0.6.0 drew: spheres in the planets' colours and a glow for the Sun. John chose a separate package (wakusei-planets) for the bodies' own looks, so chikyu ships no planet pictures and no rings; the Earth and the Moon keep theirs.
- Tests: e2e (a body looked at, its name chosen by keyboard, a press on it chooses it, a drag that turns the view does not) and a unit test of the default painter.

### The family's published parts: demo, embed, docs and usage

Chikyu Earth now has what every package of the family has, and it was missing from 0.3.0 to 0.5.0.

- **Demo on GitHub Pages**, set as the repository's and the package's homepage: <https://johnmorrisdotca.github.io/chikyu-earth/>, with the family header (the kazoku-ui language picker, English and Japanese, and theme switch, the table cloths and the Help switch), light and dark, and the family footer. `pnpm site` builds it, and the Pages workflow publishes it on every push to `main`.
- **An embed page**, `embed.html`, for an `<iframe>` with no script of your own: `?look=line|thick|realistic`, `center`, `graticule`, `turn=0|1|auto`, `time`, `clouds`, `lights`. Still by default, no controls, no location prompt; it draws only when something changes and nothing while hidden. Tested in Chromium and WebKit, and on the realistic look: one WebGL context, canvas inside its budget, nothing drawn at rest.
- **A documentation site** at `/docs/`: a page for every export (from its TSDoc, with an example that is run when the site is built), ten guides in English and in Japanese, one language to a page, search, `llms.txt` and the family's header. Every export of every entry point has a summary, `@param`, `@returns` and an `@example` that imports the package by its name; `pnpm check` fails when one does not.
- **Every way to use it, written down and tested** (`pnpm test:usage`): a script tag from jsDelivr and from unpkg, the realistic Earth from a CDN, the shared controls, Vite, webpack, React (and a server render of it), Vue, Svelte, Angular, an iframe, TypeScript types and Node. Each example is built or run against the package as npm packs it, opened in a browser and made to show a globe; the guides and the README must hold the same text word for word.
- **`look` attribute**: `<chikyu-earth look="thick">` is the new name of `style`, which frameworks read as CSS (React refuses a string `style`). `style` still works.
- **Types for the tags**: `document.querySelector("chikyu-earth")` is a `ChikyuEarth` (and `"chikyu-earth-realistic"`, `"chikyu-space"`) once the element's entry is imported.
- **A freeze test in the release** (`e2e/freeze.demo.ts`, `pnpm test:freeze`): at rest nothing is drawn and no frame asked for, turning draws at most once for each frame of the page and asks for one frame at a time, out of sight or in a hidden tab nothing is drawn, the canvas stays inside 6 million pixels and 4096 a side on a 5K screen at a pixel ratio of 2 in the Earth from space and the space view, and six rounds of changing the look leave the GPU objects flat in one WebGL context and let the context go at the end. Every Chromium project draws WebGL in software, never on the machine's graphics card. The release workflow runs it (`freeze-command`, kazoku-ui 0.9.1).
- **The family's must-have list**, checked: `scripts/check-standard.mjs` (kazoku-ui's, unchanged) fails `pnpm check` when a package lacks its demo, embed page, docs site with Japanese twins, family files or tested usage.
- **Family files**: `family-template.mjs` and `family-readme.mjs` of 2026-11-02 with Chikyu Earth added to the family's list (33 packages), `family.css`, and the README's "The family" block. Added to the list here only; the other packages take the new files when they are next touched.

## 0.6.0 - 2026-11-02 (never published on its own: it ships in 0.7.0)

The Sun, the Moon and the planets: `<chikyu-space>`, an optional entry point, under the same performance budget as the Earth from space.

- **`<chikyu-space>`** (`@johnmorrisdotca/chikyu-earth/space/element`) places the Earth, the Moon, the Sun and the planets (Mercury to Neptune) in their positions for a date and time, with the Moon's
  phase and the Earth's sunlit side coming out of the light (the Moon is half lit on 2 November 2026, last quarter). Positions are computed in the browser by **astronomy-engine** (MIT, a new optional peer dependency;
  nothing is fetched). Time controls: `time` (an ISO date or `now`), `speed` (1 real time, 0 held, 3600 an hour a second, 86400 a day a second, negative backwards). Zoom from the Earth out to the solar system and back with
  the shared controls (`zoom-min`, `zoom-max`), and `zoomFor("moon" | "sun" | "inner" | "solar-system" | "earth")` for the jumps. Names beside the bodies and the planets' orbits can be switched off.
- **Two scales, and it says which**: `compressed` (default; every direction real, the Moon 10 Earth radii away instead of 60, the Sun 44, the planets round the Sun at 44 radii times their distance in astronomical
  units to the power 0.45, sizes enlarged) and `true` (real distances and sizes, where the planets are specks). The demo says "Compressed scale: ..." whenever it is on. [docs/space.md](docs/space.md).
- **Budget, each line tested** (`e2e/space.gl.ts`): paused, 0 draw calls and 0 frame requests in 4 s; real time, 0 draw calls in 6 s (a draw a minute); a day a second: 1.00 days a second of game time, 29.4 draws a second,
  and 2.0 ephemeris lookups a second (the ephemeris is looked up once a game-second span and interpolated, within 0.1 degree of the Moon's true place); nothing drawn out of sight at a day a second; the textures follow the zoom and
  are freed after it; removal frees what it held; a lost context is recovered. The space soak (10 minutes, 945 steps from the Earth to the solar system and back, at every speed, both scales, orbits and names toggled): JS heap 8.05 to 8.45 MB after garbage collection (flat from the fifth minute), GPU objects 46 to 46, textures, buffers and programs equal to the start, the average 76 GL draw calls a second (about 25 a frame, so 3 frames a second), one WebGL context, no error.
- **Pictures**: the Moon (NASA SVS 4720, LROC colour mosaic, 1024 and 2048 wide, 306 KB) joins the Earth's; the package's textures are 1.85 MB. The planets are plain colours.
- **Shared parts**: the texture loader (`src/realistic/textures.ts`) and the page's one renderer (`src/realistic/shared.ts`) now serve both the Earth from space and the space view, so a page keeps one WebGL context between them. The
  Earth's shaders look at the camera instead of assuming one, so they work from any angle.
- **Research, no code** ([docs/satellite-sources.md](docs/satellite-sources.md), MODULES-85): CelesTrak (grey), Space-Track (red for a package), the r/SpaceX API (archived, offline), Launch Library 2 (grey), Wikipedia and Wikidata
  (green) for launches; the recommendation is a satellite view that takes elements the page supplies. John chooses before MODULES-86 and MODULES-87 start.

## 0.5.0 - 2026-11-02

The Earth from space, and markers for any place on either globe, both under a hard performance budget.

### Markers

- **`attachMarkers(element)`** (`@johnmorrisdotca/chikyu-earth/markers`) puts your places on `<chikyu-earth>` or `<chikyu-earth-realistic>`: add, update and remove markers at `[lon, lat]` with a label, colour, icon and size; groups (cities, stadiums) shown or hidden together; markers that turn, zoom and pan with the globe and fade on the far side; crowded places gathered into clusters; labels that make room for each other; `chikyu-marker-hover`, `-click` and `-focus` events carrying your own `data`; a button for each shown label (Tab and Enter work) and a hidden list of every place for a screen reader. Chikyu ships no places; the demo shows 22 cities and 10 stadiums (Wikidata coordinates, CC0). [docs/markers.md](docs/markers.md).
- **Budget**, each line tested: all dots in one 2D canvas pass, and a pool of 24 label buttons, never an element per place; 5,000 markers cost 0.36 ms a view change on the flat globe; a 5,000-marker drag on the Earth from space made 117 draws in 4 s (29 a second), the markers drawn with them one for one and not at all at rest or out of sight; the overlay canvas holds the same 4096-a-side, 6 MP limit.
- The flat element's picture now sits in a holder beside the markers' overlay (a redraw replaces only the picture), and `lookAt` moves to `view.ts`.

### The Earth from space

An optional realistic look, drawn with three.js through kazoku-ui's shared renderer.

- **`<chikyu-earth-realistic>`** (`@johnmorrisdotca/chikyu-earth/realistic/element`): day side from NASA's Blue Marble, the cities' lights on the night side, a cloud
  layer that drifts with the date, a sun glint on the sea, an atmosphere at the rim, and the day and night line placed by the real Sun for a date and time (now by
  default). The same shared controls (turn, tilt, zoom, pan) and the same `setView(view, final)` as the flat globe. `time`, `clouds`, `lights`, `center`,
  `texture-base`, `max-texture` and `live-seconds` attributes; `chikyu-ready`, `chikyu-unavailable` and `chikyu-tier` events. [docs/realistic.md](docs/realistic.md).
- **The flat look stays**: `<chikyu-earth>` is unchanged (and gains a `centre` getter); the demo's Line, Thick and Realistic buttons choose between them, keep the
  camera, and keep the choice, the graticule, the clouds, the lights and the time in the address (kazoku-ui's address state). Without WebGL the demo says so and
  shows the line globe.
- **Optional, so the base install stays small**: `three` and `@johnmorrisdotca/kazoku-ui` are optional peer dependencies; the base entry and `<chikyu-earth>` need neither.
  The realistic element, its Sun, its scene and its shaders, with kazoku-ui's renderer, are 22.6 KB minified (9.2 KB gzipped); three.js is the page's, and the demo's
  subset of it (`demo/three-subset.ts`) is 188 KB gzipped. Sun position: `subsolarPoint(ms)` in `@johnmorrisdotca/chikyu-earth/realistic`, tested against the almanac
  (declination within 0.05 degree, the equation of time in the longitude).
- **Pictures** (1.55 MB in `dist/textures/`, WebP, all NASA public domain, credited in NOTICE.md): day at 1024, 2048 and 4096; night, clouds and a water mask at 1024 and 2048.
  The 1024 ones load first; a larger one loads when the zoom needs it (about 3 texels per pixel of the disc's radius), replaces the smaller, and is freed 4 s after the
  zoom drops. No texture is wider than 4096 (2048 on a device with 2 GB or less); `pnpm textures` rebuilds them.
- **Performance, each proved by `e2e/realistic.gl.ts` (Chromium, software WebGL)**: 0 draw calls and 0 animation frames in 4 s at rest; a drag at 125 moves a second
  draws 29.3 times a second, and 2,700 `setView` calls in 2 s make 59 draws; an Auto-turn at the Earth's rate draws 0 times in 6 s; one WebGL context; the canvas on a
  5K screen at ratio 2 is 3264 x 1835 = 5.99 MP; the textures alive grow one a layer with the zoom and return to the start after it; 0 draws and 0 frames while out of
  sight or in a hidden tab; after removal 0 buffers, 0 programs and none of our textures remain, and the element can come back; a lost context draws nothing and then
  recovers, not black; no WebGL gives `chikyu-unavailable`. The soak (10 minutes, 976 moves, 2,000 markers on): JS heap 7.29 to 7.80 MB after garbage collection, GPU objects 20 to 20, textures, buffers and programs the same as at the start, the draw rate 5.4 a second on average, one WebGL context, no error.
- `pnpm test:soak` (`SOAK_MINUTES`, 10 by default; CI runs 1) turns, zooms, re-times and toggles for that long and compares the heap, the GPU objects and the draw rate with the start.
- `pnpm screenshots` also makes the realistic pictures; `scripts/make-textures.py` makes the textures from NASA's sources.

## 0.4.0 - 2026-11-02

The outlines now come from chizu, the controls from kazoku-ui 0.9, and the release from the family's shared workflow.

- **chizu's `world-geo` replaces our own country data.** `src/data/countries.ts` (154 KB) and `scripts/make-countries.ts`
  are gone; `src/countries.ts` is a small adapter over `@johnmorrisdotca/chizu/world-geo` (chizu 1.6.0, now a
  dependency). The globe looks the same and `COUNTRIES` and `countryList()` keep their shape. Region count: 177 before,
  177 now, so nothing to reconcile (chizu's 173 `WORLD` countries plus Antarctica, the French Southern Lands, Northern
  Cyprus and Somaliland). One difference: Kosovo's `alpha2` is `XK` (it was `null`); Northern Cyprus and Somaliland
  stay `null`. The demo bundle goes from 207 KB to 220 KB (chizu's data is a little larger than ours was, and
  kazoku-ui 0.9's bar has more in it). `world-atlas`, `topojson-client` and kuni are no longer dev dependencies.
- **kazoku-ui ^0.9.0** (was ^0.1.0, which could not move past 0.1.x), now a dev dependency: the package itself
  imports none of it, only the demo does. The demo asks for `controls="advanced"` so Front, 2x, tilt and the pan pad
  stay on the bar; the idle turn stops when the view is out of sight (kazoku-ui 0.7.1) and the demo's one redraw a
  second stays.
- **Shared release workflow.** `release.yml` now calls kazoku-ui's `reusable-release.yml` (pinned to v0.9.0) with
  `pnpm check && pnpm test:package`; the npm trusted-publisher entry still names `release.yml`.
- **AGENTS.md** is kazoku-ui's template (Facts: board `modules`, area `chikyu-earth`, ports 8200 to 8299).
- A still picture of the demo opens the README; `pnpm screenshots` makes the pictures in `docs/images/`.

## 0.3.0 - 2026-11-01

The shared-controls integration is documented and covered in every motion preference, and the future of the
country data is written down.

- The README's new Controls section has the kazoku-ui snippet and the exact yaw/tilt/zoom/pan mapping. The browser
  suite now proves reduced motion leaves the globe still, as well as Auto-turn continuing after a zoom.
- Inspected chizu 1.5.1 from npm: `@johnmorrisdotca/chizu/world` is Miller-projected canvas data centred on 155°E,
  not longitude/latitude, so chikyu keeps its own Natural Earth 1:110m outlines and d3-geo.
  [docs/chizu-proposal.md](docs/chizu-proposal.md) proposes the `world-geo` export that would let it share chizu's
  data later.
- The demo and test servers move to this work's port block, 8200–8299.

## 0.2.0 - 2026-11-01

The globe now uses the family's shared view controls.

- `<kazoku-view-controls>` supplies turn, tilt, Auto-turn, Front, zoom, pan and touch gestures; the custom Rotate ¼
  button and the element's private rotation timer are gone.
- `projectionView()` maps yaw and tilt to the orthographic rotation, zoom to its scale and pan to its translation,
  always relative to the reader's home centre. `<chikyu-earth>.setView()` applies that state.
- Auto-turn runs at `0.004178` degrees a second, the Earth's own sidereal rate, and keeps running through zoom,
  pan, Fit and Front. Reduced motion is respected by kazoku-ui.
- Browser tests now cover Chromium and WebKit at desk and phone sizes, including drag, pinch, zoom, Fit and the
  continuing Earth-rate turn.

## 0.1.0 - 2026-11-01

The first scaffold, and the first working globe.

- `globe()` draws an orthographic globe as an SVG string: an ocean disc, the country outlines and the rim,
  in two line styles (`line`, `thick`), with an optional graticule.
- `<chikyu-earth>` puts that globe on a page as a web component. It opens centred on where you are
  (the `center` attribute wins over geolocation) and turns at the Earth's own rate — one sidereal day,
  23 h 56 min 4.0905 s, per revolution.
- Country outlines are Natural Earth's, baked into the package at build time; each carries its English and
  Japanese name and ISO alpha-2 code from kuni. d3-geo does the projection, the only runtime dependency.
- A demo (`pnpm dev`), unit tests, a package check and a Playwright demo test, with CI to run them.
