fuzzyworld

tower / cascadia / files / README.md

Branch cascadia · default branch · all branches

README.md

16.5 KB · history · blame

Tower

Live map — https://pavelsafronov.gitlab.io/tower/ · Source

Companion piece to a novel set inside Tower — a fictional smart cylinder orbiting Earth, spun for 1 g, with an inner surface the size of Wisconsin, lit by 54 TW of sunlight piped down its axis and scattered by mirrors that make its days and nights. Its wall is a kilometre of sealed hull: no windows along all 540 km, and no view of the Earth it orbits. Both end caps are windows, though — 100 km of glass each, and the only places in the world with a horizon that is not Tower. Nobody aboard can see the sun either: the 244 km collector sits between Tower and it, 79 times its diameter, so the sun cap looks out at a black disc and the stars around it — black except at its edge, where the structure holding it flat catches the sun side-on and traces the whole 244 km in a thin sun-coloured ring.

Explore Tower from outside, pick a spot on the inner surface, and stand there — with the ground curving up on both sides and the far side of the world hanging 100 km overhead, clearer than the ground at your feet. Turn its sun up to Earth clear-sky noon, down to permanent dusk, or shut the beam off entirely and watch the sky come out: through the far cap the stars wheel once every 7 min 29 s about a single motionless star on the axis. Nothing inside Tower rotates, because you and the ground and the air all turn together — so that window is the only place the spin is visible at all.

Tower flies all 78 billion mirrors of its own sunlight, individually, because nothing passive would stay in the beam past mid-afternoon. It is a person.

Status

All three views are built — map, exterior and interior — over an authored geography and a working writer mode.

Built: the unrolled surface map, Tower from outside, standing inside it, place editing for thirteen kinds (points, lines, polygons and bands), localStorage autosave, backup and static exports, import, permalinks, and the sightline probe.

Both are series-bible material: coherence outranks spectacle, and the prose is downstream of them.

On a phone the sidebar is a drawer rather than a column: below 720 px the world gets the whole screen and the panel slides in over it, one tap away and one tap gone. Picking a place closes it, because in every view selecting a place is how you travel there — see decisions.md D-043.

Screenshots

All ten views on one sheet

npm run screenshots drives the real application in a headless browser — clicking the view buttons, picking places out of the list, dragging to orbit and to look up — and writes docs/screenshots/. Taking them through the UI is the point: a shot taken this way fails when the UI fails, so a black canvas ends up in the picture instead of hiding behind a passing unit test.

The whole tour takes about 35 seconds. It used to take six and a half minutes, nearly all of it spent rendering Tower's haze integral on the CPU — the default headless browser has no GPU. It now asks for the full Chrome build, which reaches the real one, and photographs four shots at a time, since a shot is mostly spent waiting. The cost is that the committed images are tied to the GPU that drew them: another machine will show a large one-off divergence rather than a regression.

Desktop — 1440×900
map the unrolled inner surface, with a place selected
map-sightline shift-click two points to measure a sightline through the air
exterior x-ray hull — the inner surface projected out, with the caps and the collector
exterior-true true hull — bare skin, and the land visible through the far cap window
interior standing at The Narrows, the ground curving up on both sides
interior-overhead looking up: the far side 100 km overhead is clearer than ground 100 km away
interior-dawn dawn — a lit sky over dark ground, the light still 27 km away
reader ?reader=1 — terrain, places, a detail card and the probe, no editing
Mobile — 390×844
map the world with the whole screen, the panel one tap away
exterior the spin readout dropped clear of the panel button
interior the standing readout at a size that fits 390 px
panel the sidebar as a drawer, opened over the world

Looking before committing

overview.png is a contact sheet of all ten. It exists to be looked at, once, before committing — one image that answers "is the application still there?". Regenerate, glance at it, then commit.

--check puts a number on the same question. Every shot is compared against the committed one and the run fails if any of them moved too far:

npm run screenshots -- --check              # fail past 3% divergence on any shot
npm run screenshots -- --threshold 8        # report only, looser bar
npm run screenshots -- --url http://localhost:5173   # use a dev server already up

The threshold is measured at both ends, not guessed. The 2D shots come out byte-identical between runs — nothing in Tower is stochastic, the exterior spin is switched off, and every shot gets a fresh browser context so no camera leaks into the next. The WebGL shots do not, because the tour draws on the real GPU and Metal does not schedule floating-point work identically twice; they drift by 0.1% to 0.9%. Against that, hiding both 3D canvases scored 7% to 31%, and a view going entirely black scores 12% to 39%.

3% is three times the worst noise and less than half the mildest real failure. It is a smoke alarm, not a verdict: when it fires, go and look at the sheet. Note that a view which never worked scores 0% when it breaks further — this catches regressions, not things that were already broken.

Development

npm install
npm run dev      # http://localhost:5173
npm test         # 104 tests; canon figures are pinned to design.md
npm run build
npm run terrain   # regenerate the maps from content/geography.json
npm run cascadia  # regenerate the 1:1 Cascadia surface (see below)
npm run screenshots  # drive the app and rephotograph docs/screenshots/

Vite + TypeScript, deployed to GitLab Pages by .gitlab-ci.yml on every push to the default branch. Three.js is loaded only when a 3D view is opened, so a reader who stays on the map never downloads it.

Assets are referenced relatively, so the same build works whether Pages serves it from https://pavelsafronov.gitlab.io/tower/ or from a generated unique domain at a root. Set a BASE CI variable to force an absolute base if that is ever needed.

Geography

content/geography.json is the authored source of truth for terrain — coordinates in canon (θ, z), elevations in metres relative to the base shell, negative for anything cut below it. render.minHeightM / render.maxHeightM declare the range the height raster is stretched across; the generator prints the range the terrain actually occupies and warns if it has outgrown the declaration. npm run terrain renders it, with no dependencies beyond Node:

static/terrain-height.png 16-bit greyscale, across the declared minHeightM–maxHeightM
static/terrain-color.png the whole world, 264 m/px
static/terrain-corridor.png the developed corridor, 122 m/px
static/world.json seed places for the app

It reports each stage as it goes — every relief op, colourisation, and PNG encode — and takes about 6 seconds. Flags:

--probe <theta> print elevation jumps along a row, for checking river gradients and finding discontinuities
--quiet one line per stage instead of one per feature
--force let the seed overwrite places added in the app

The Cascadia surface — a ruler

The panel's Surface control can swap the authored ground for the Pacific Northwest at 1:1, to answer the question a number cannot: how big is this actually?

It fits because Tower is a corridor and so is Cascadia. Measured in UTM 10N, the ground from the Pacific surf at Kalaloch east to the Columbia at Entiat is 312.8 km against Tower's 314.2 km circumference — so the real coast closes the ring on real terrain, with 1.4 km to spare. Walk east from the beach, over the Olympics, across Puget Sound, over the Cascades and down the east flank to the Columbia, and you are back at the beach. Seattle sits 150 km deepward of the sun cap, and the point 100 km straight overhead is both Kalaloch and Entiat — one place, reached by walking either way round. Nothing is rescaled and nothing is invented.

It is not canon, contains no Tower geography, defaults off, and draws no places. The one artefact is a seam where θ wraps and geography does not — a scarp of 369–844 m through the settled half, kept as a landform rather than repaired. See D-055 for the alternatives that were measured and rejected.

npm run cascadia            # ~2 s from cache, ~5 s cold
static/cascadia-height.png 16-bit greyscale, sharing canon's -560–4400 m window
static/cascadia-color.png the same 2048 x 1192 grid, 264 m/px

Elevation comes from the AWS open terrain tiles — SRTM/3DEP over land, GEBCO below water, Canadian ground north of 49°N in the same grid — cached under .cache/, re-fetchable, and not committed. There are no dependencies beyond Node; the UTM projection and the PNG decoder are in the repo.

Every surface must share the raster grid and height window: the interior view bakes that window into its GLSL as literals, so a surface declaring its own would silently displace its ground. test/raster.test.ts reads the constants back out of tools/cascadia.mjs and holds it to them.

Reading and writing

The map opens in writer mode: tools, editor, canon controls and import/export. Add ?reader=1 to preview what a reader gets — the terrain, the places, a detail card and the sightline probe, with no editing. Writer is the default while the world is still being built; that is a one-line change when it is ready to publish. Either way it is a UI mode, not a security boundary — with no backend an editor can only change their own copy (decisions.md D-011).

Any selection updates the URL, so a link is always shareable:

#place=the-narrows select and centre a place
#at=0.03,170000 drop a sightline endpoint at (θ, z)

Views

Map is the unrolled inner surface. Exterior is Tower from outside — a kilometre of hull, the checkered sun cap, the glazed far cap, the 244 km collector flying ahead and the beam converging into the sun cap. Each piece is captioned.

The hull reads two ways and the Hull switch picks one. True is the outer skin: bare structure, and the far cap a real window — look in through it and the land is actually there, lit and receding 540 km down the tube. It is the only line of sight into Tower that is not a diagram. X-ray wraps the terrain onto the outside instead, which is a diagram of what is inside rather than a view of it, and useful precisely because the wall is opaque. The active view is remembered and travels in the permalink, so #view=exterior&place=the-narrows opens where you left off. Drag to orbit, scroll to zoom, click the hull to drop a point; the spin runs at 1x to 1200x real time, and a point picked off the turning hull still comes back in canon coordinates.

Interior is standing inside. The shell is the real cylinder, displaced by the height raster and painted with the colour one, so the ground curves up on both sides and closes overhead. Haze is integrated through Tower's rotational air column for every pixel, which reproduces the strangest fact about the place: the land 100 km straight up is 78% clear while the ground 100 km away is 31% — distant geography here is best seen by looking up.

Drag to look, scroll to zoom in like a pair of binoculars, and select a place — in the list or by its caption — to walk there. Most of the world is beyond the haze horizon from any given spot, so travelling is more use than turning.

The far cap is a window — 100 km of it, looking into deep anti-sun space. By day it is simply a disc of blue, because 540 km of air in front of it scatters more light than anything behind it sends; the stars are there at noon and unseeable, which is a fact about eyes rather than about glass. Turn the light down and they come out. The sun cap stays a checkered plate: it faces the sun, and needs glare management rather than a view.

The one part of the far cap that is not glass is a 3.2 km mirror on the axis. A quarter of the beam survives all 540 km and arrives collimated, so it lands as 1.7 MW/m² — 1,200 suns — on a spot a thousandth of the cap's area; the mirror sends it back up the column for a second pass, which lifts the beam's utilisation from 76% to 94%. You can see it: the rod of light visibly terminates on a bright disc, and the disc banks and goes out with the beam.

The checker survives on the far cap as the window's mullions — the same polar tessellation at the same pitch, so it is still the only object in the world with a known cell size and still the only rule anyone has for judging distance. It is just read against sky now instead of against a plate.

Dawn is a line, not a fade. The beam glows by itself, so when its power comes up the sky brightens everywhere at once — but the ground is lit by the diffusers, and they hand the light down the axis. So a Tower morning is a fully lit sky over dark ground, with daylight arriving as a front running deepward from the sun cap at 225 m/s, crossing all 540 km in 40 minutes. Tower has no latitude; the cycle gives it longitude. Scrub the Time slider to 06:17 and stand at The Capital to watch it come, or tick Run the clock and let it.

The light has five settings when the clock is not driving it. Dark shuts the 54 TW beam down entirely and is the only one that is genuinely black — there is no airlight, no lit ground and no rod overhead, and the only thing left in the world is the sky. Night banks the beam to a thousandth instead of killing it, which is what night here has to be: the beam glows by itself, so a lit beam lights the world whatever the mirrors are doing, and aiming them away would leave the floor at about 100 W/m² — half of noon.

The eye-height slider runs from 1.7 m to 25 km with the local gravity beside it, and Rain leans 1.5° antispinward. Nothing inside rotates, because you, the ground and the air all turn together — so for 539 of the 540 km that 1.5° is the only evidence Tower turns at all. The exception is the window: the sky out there does not co-rotate, and wheels once every 7 min 29 s about the one motionless star on the axis. It is by a wide margin the plainest sign of the spin anywhere in the view, and it is only available at night, at the deepward end, looking the one direction that has ever had anything in it but Tower.

Working in the map

Pick a tool, click to place; Lake, Forest, Desert and Region trace a polygon and River and Canyon trace an open line (Enter finishes, Esc cancels). Drag markers to move them, shift-click two points to measure a sightline, f to fit the view.

Canon is 0 star slats — the hull is sealed, the inner surface is one unbroken 169,646 km², and the only views out are at the end caps. The runtime control for this is disabled and hidden (decisions.md D-033): the terrain raster is baked at 0 slats, so any other count draws bands over land that has none.

Everything autosaves to this browser's localStorage. Two exports:

Export backup everything, private notes included. Keep out of the public repo — .gitignore already excludes tower-backup-*.json.
Export static map content public places only, notes stripped. This is static/world.json, the world readers see, and the seed for a browser with no local draft.
Source
1# Tower
2
3**Live map — <https://pavelsafronov.gitlab.io/tower/>** · [Source](https://gitlab.com/PavelSafronov/tower)
4
5Companion piece to a novel set inside **Tower** — a fictional smart cylinder orbiting Earth,
6spun for 1 g, with an inner surface the size of Wisconsin, lit by 54 TW of sunlight
7piped down its axis and scattered by mirrors that make its days and nights. Its wall
8is a kilometre of sealed hull: no windows along all 540 km, and no view of the Earth
9it orbits. Both end caps are windows, though — 100 km of glass each, and the only
10places in the world with a horizon that is not Tower. Nobody aboard can see the sun
11either: the 244 km collector sits between Tower and it, 79 times its diameter, so
12the sun cap looks out at a black disc and the stars around it — black except at its
13edge, where the structure holding it flat catches the sun side-on and traces the
14whole 244 km in a thin sun-coloured ring.
15
16Explore Tower from outside, pick a spot on the inner surface, and stand there — with
17the ground curving up on both sides and the far side of the world hanging 100 km
18overhead, clearer than the ground at your feet. Turn its sun up to Earth clear-sky
19noon, down to permanent dusk, or shut the beam off entirely and watch the sky come
20out: through the far cap the stars wheel once every 7 min 29 s about a single
21motionless star on the axis. Nothing inside Tower rotates, because you and the
22ground and the air all turn together — so that window is the only place the spin is
23visible at all.
24
25Tower flies all 78 billion mirrors of its own sunlight, individually, because
26nothing passive would stay in the beam past mid-afternoon. It is a person.
27
28## Status
29
30**All three views are built** — map, exterior and interior — over an authored
31geography and a working writer mode.
32
33Built: the unrolled surface map, Tower from outside, standing inside it, place
34editing for thirteen kinds (points, lines, polygons and bands), localStorage
35autosave, backup and static exports, import, permalinks, and the sightline probe.
36
37- [design.md](design.md) — canon, physics and application architecture
38- [decisions.md](decisions.md) — choices made and why
39
40Both are series-bible material: coherence outranks spectacle, and the prose is
41downstream of them.
42
43On a phone the sidebar is a **drawer** rather than a column: below 720 px the world
44gets the whole screen and the panel slides in over it, one tap away and one tap
45gone. Picking a place closes it, because in every view selecting a place is how you
46travel there — see [decisions.md](decisions.md) D-043.
47
48## Screenshots
49
50[![All ten views on one sheet](docs/screenshots/overview.png)](docs/screenshots/overview.png)
51
52`npm run screenshots` drives the real application in a headless browser — clicking
53the view buttons, picking places out of the list, dragging to orbit and to look up —
54and writes [`docs/screenshots/`](docs/screenshots/). Taking them *through the UI* is
55the point: a shot taken this way fails when the UI fails, so a black canvas ends up
56in the picture instead of hiding behind a passing unit test.
57
58The whole tour takes about **35 seconds**. It used to take six and a half minutes,
59nearly all of it spent rendering Tower's haze integral on the CPU — the default
60headless browser has no GPU. It now asks for the full Chrome build, which reaches
61the real one, and photographs four shots at a time, since a shot is mostly spent
62waiting. The cost is that the committed images are tied to the GPU that drew them:
63another machine will show a large one-off divergence rather than a regression.
64
65| Desktop — 1440×900 | |
66|---|---|
67| [map](docs/screenshots/desktop-map.png) | the unrolled inner surface, with a place selected |
68| [map-sightline](docs/screenshots/desktop-map-sightline.png) | shift-click two points to measure a sightline through the air |
69| [exterior](docs/screenshots/desktop-exterior.png) | x-ray hull — the inner surface projected out, with the caps and the collector |
70| [exterior-true](docs/screenshots/desktop-exterior-true.png) | true hull — bare skin, and the land visible through the far cap window |
71| [interior](docs/screenshots/desktop-interior.png) | standing at The Narrows, the ground curving up on both sides |
72| [interior-overhead](docs/screenshots/desktop-interior-overhead.png) | looking up: the far side 100 km overhead is clearer than ground 100 km away |
73| [interior-dawn](docs/screenshots/desktop-interior-dawn.png) | dawn — a lit sky over dark ground, the light still 27 km away |
74| [reader](docs/screenshots/desktop-reader.png) | `?reader=1` — terrain, places, a detail card and the probe, no editing |
75
76| Mobile — 390×844 | |
77|---|---|
78| [map](docs/screenshots/mobile-map.png) | the world with the whole screen, the panel one tap away |
79| [exterior](docs/screenshots/mobile-exterior.png) | the spin readout dropped clear of the panel button |
80| [interior](docs/screenshots/mobile-interior.png) | the standing readout at a size that fits 390 px |
81| [panel](docs/screenshots/mobile-panel.png) | the sidebar as a drawer, opened over the world |
82
83### Looking before committing
84
85[`overview.png`](docs/screenshots/overview.png) is a contact sheet of all ten. It
86exists to be **looked at, once, before committing** — one image that answers "is the
87application still there?". Regenerate, glance at it, then commit.
88
89`--check` puts a number on the same question. Every shot is compared against the
90committed one and the run fails if any of them moved too far:
91
92```
93npm run screenshots -- --check # fail past 3% divergence on any shot
94npm run screenshots -- --threshold 8 # report only, looser bar
95npm run screenshots -- --url http://localhost:5173 # use a dev server already up
96```
97
98The threshold is measured at both ends, not guessed. The 2D shots come out
99**byte-identical** between runs — nothing in Tower is stochastic, the exterior spin
100is switched off, and every shot gets a fresh browser context so no camera leaks into
101the next. **The WebGL shots do not**, because the tour draws on the real GPU and
102Metal does not schedule floating-point work identically twice; they drift by 0.1% to
103**0.9%**. Against that, hiding both 3D canvases scored **7% to 31%**, and a view
104going entirely black scores 12% to 39%.
105
106**3% is three times the worst noise and less than half the mildest real failure.**
107It is a smoke alarm, not a verdict: when it fires, go and look at the sheet. Note
108that a view which never worked scores 0% when it breaks further — this catches
109regressions, not things that were already broken.
110
111## Development
112
113```
114npm install
115npm run dev # http://localhost:5173
116npm test # 104 tests; canon figures are pinned to design.md
117npm run build
118npm run terrain # regenerate the maps from content/geography.json
119npm run cascadia # regenerate the 1:1 Cascadia surface (see below)
120npm run screenshots # drive the app and rephotograph docs/screenshots/
121```
122
123Vite + TypeScript, deployed to GitLab Pages by `.gitlab-ci.yml` on every push to the
124default branch. Three.js is loaded only when a 3D view is opened, so a reader who
125stays on the map never downloads it.
126
127Assets are referenced **relatively**, so the same build works whether Pages serves
128it from `https://pavelsafronov.gitlab.io/tower/` or from a generated unique domain
129at a root. Set a `BASE` CI variable to force an absolute base if that is ever
130needed.
131
132## Geography
133
134[`content/geography.json`](content/geography.json) is the authored source of truth
135for terrain — coordinates in canon (θ, z), elevations in metres relative to the base
136shell, negative for anything cut below it. `render.minHeightM` / `render.maxHeightM`
137declare the range the height raster is stretched across; the generator prints the
138range the terrain actually occupies and warns if it has outgrown the declaration. `npm run terrain` renders it, with no dependencies beyond Node:
139
140| | |
141|---|---|
142| `static/terrain-height.png` | 16-bit greyscale, across the declared `minHeightM`–`maxHeightM` |
143| `static/terrain-color.png` | the whole world, 264 m/px |
144| `static/terrain-corridor.png` | the developed corridor, 122 m/px |
145| `static/world.json` | seed places for the app |
146
147It reports each stage as it goes — every relief op, colourisation, and PNG encode —
148and takes about 6 seconds. Flags:
149
150| | |
151|---|---|
152| `--probe <theta>` | print elevation jumps along a row, for checking river gradients and finding discontinuities |
153| `--quiet` | one line per stage instead of one per feature |
154| `--force` | let the seed overwrite places added in the app |
155
156### The Cascadia surface — a ruler
157
158The panel's **Surface** control can swap the authored ground for **the Pacific
159Northwest at 1:1**, to answer the question a number cannot: *how big is this
160actually?*
161
162It fits because Tower is a corridor and so is Cascadia. Measured in UTM 10N, the
163ground from the Pacific surf at Kalaloch east to the Columbia at Entiat is
164**312.8 km against Tower's 314.2 km circumference** — so the real coast closes the
165ring on real terrain, with 1.4 km to spare. Walk east from the beach, over the
166Olympics, across Puget Sound, over the Cascades and down the east flank to the
167Columbia, and you are back at the beach. Seattle sits 150 km deepward of the sun
168cap, and the point 100 km straight overhead is *both* Kalaloch and Entiat — one
169place, reached by walking either way round. Nothing is rescaled and nothing is
170invented.
171
172**It is not canon**, contains no Tower geography, defaults off, and draws no
173places. The one artefact is a seam where θ wraps and geography does not — a scarp
174of 369–844 m through the settled half, kept as a landform rather than repaired.
175See D-055 for the alternatives that were measured and rejected.
176
177```
178npm run cascadia # ~2 s from cache, ~5 s cold
179```
180
181| | |
182|---|---|
183| `static/cascadia-height.png` | 16-bit greyscale, sharing canon's `-560`–`4400` m window |
184| `static/cascadia-color.png` | the same 2048 x 1192 grid, 264 m/px |
185
186Elevation comes from the AWS open terrain tiles — SRTM/3DEP over land, GEBCO below
187water, Canadian ground north of 49°N in the same grid — cached under `.cache/`,
188re-fetchable, and not committed. There are no dependencies beyond Node; the UTM
189projection and the PNG decoder are in the repo.
190
191Every surface **must** share the raster grid and height window: the interior view
192bakes that window into its GLSL as literals, so a surface declaring its own would
193silently displace its ground. `test/raster.test.ts` reads the constants back out of
194`tools/cascadia.mjs` and holds it to them.
195
196## Reading and writing
197
198The map opens in **writer mode**: tools, editor, canon controls and import/export.
199Add **`?reader=1`** to preview what a reader gets — the terrain, the places, a
200detail card and the sightline probe, with no editing. Writer is the default while
201the world is still being built; that is a one-line change when it is ready to
202publish. Either way it is a UI mode, not a security boundary — with no backend an
203editor can only change their own copy (decisions.md D-011).
204
205Any selection updates the URL, so a link is always shareable:
206
207| | |
208|---|---|
209| `#place=the-narrows` | select and centre a place |
210| `#at=0.03,170000` | drop a sightline endpoint at (θ, z) |
211
212## Views
213
214**Map** is the unrolled inner surface. **Exterior** is Tower from outside — a
215kilometre of hull, the checkered sun cap, the glazed far cap, the 244 km collector
216flying ahead and the beam converging into the sun cap. Each piece is captioned.
217
218The hull reads two ways and the **Hull** switch picks one. **True** is the outer
219skin: bare structure, and the far cap a real window — look in through it and the
220land is actually there, lit and receding 540 km down the tube. It is the only line
221of sight into Tower that is not a diagram. **X-ray** wraps the terrain onto the
222outside instead, which is a diagram of what is inside rather than a view of it, and
223useful precisely because the wall is opaque. The active view is remembered and travels in the permalink, so
224`#view=exterior&place=the-narrows` opens where you left off. Drag to orbit, scroll to zoom, click the hull to drop a point; the spin runs at
2251x to 1200x real time, and a point picked off the turning hull still comes back in
226canon coordinates.
227
228**Interior** is standing inside. The shell is the real cylinder, displaced by the
229height raster and painted with the colour one, so the ground curves up on both sides
230and closes overhead. Haze is integrated through Tower's rotational air column for
231every pixel, which reproduces the strangest fact about the place: the land 100 km
232straight up is **78%** clear while the ground 100 km away is **31%** — distant
233geography here is best seen by looking up.
234
235Drag to look, scroll to zoom in like a pair of binoculars, and select a place — in
236the list or by its caption — to **walk there**. Most of the world is beyond the haze
237horizon from any given spot, so travelling is more use than turning.
238
239**The far cap is a window** — 100 km of it, looking into deep anti-sun space. By day
240it is simply a disc of blue, because 540 km of air in front of it scatters more
241light than anything behind it sends; the stars are there at noon and unseeable,
242which is a fact about eyes rather than about glass. Turn the light down and they
243come out. The sun cap stays a checkered plate: it faces the sun, and needs glare
244management rather than a view.
245
246The one part of the far cap that is not glass is a **3.2 km mirror** on the axis.
247A quarter of the beam survives all 540 km and arrives collimated, so it lands as
2481.7 MW/m² — 1,200 suns — on a spot a thousandth of the cap's area; the mirror sends
249it back up the column for a second pass, which lifts the beam's utilisation from 76%
250to 94%. You can see it: the rod of light visibly terminates on a bright disc, and
251the disc banks and goes out with the beam.
252
253The checker survives on the far cap as the window's **mullions** — the same polar
254tessellation at the same pitch, so it is still the only object in the world with a
255known cell size and still the only rule anyone has for judging distance. It is just
256read against sky now instead of against a plate.
257
258**Dawn is a line, not a fade.** The beam glows by itself, so when its power comes up
259the sky brightens everywhere at once — but the ground is lit by the diffusers, and
260they hand the light down the axis. So a Tower morning is a **fully lit sky over dark
261ground**, with daylight arriving as a front running deepward from the sun cap at
262225 m/s, crossing all 540 km in 40 minutes. Tower has no latitude; the cycle gives it
263longitude. Scrub the **Time** slider to 06:17 and stand at The Capital to watch it
264come, or tick **Run the clock** and let it.
265
266The light has five settings when the clock is not driving it. **Dark** shuts the 54 TW beam down entirely and is the
267only one that is genuinely black — there is no airlight, no lit ground and no rod
268overhead, and the only thing left in the world is the sky. **Night** banks the beam
269to a thousandth instead of killing it, which is what night here has to be: the beam
270glows by itself, so a lit beam lights the world whatever the mirrors are doing, and
271aiming them away would leave the floor at about 100 W/m² — half of noon.
272
273The eye-height slider runs from 1.7 m to 25 km with the local gravity beside it, and
274**Rain** leans 1.5° antispinward. Nothing *inside* rotates, because you, the ground
275and the air all turn together — so for 539 of the 540 km that 1.5° is the only
276evidence Tower turns at all. The exception is the window: the sky out there does not
277co-rotate, and wheels once every 7 min 29 s about the one motionless star on the
278axis. It is by a wide margin the plainest sign of the spin anywhere in the view, and
279it is only available at night, at the deepward end, looking the one direction that
280has ever had anything in it but Tower.
281
282## Working in the map
283
284Pick a tool, click to place; **Lake**, **Forest**, **Desert** and **Region** trace a
285polygon and **River** and **Canyon** trace an open line (Enter finishes, Esc
286cancels). Drag markers to move them, **shift-click two points** to
287measure a sightline, **f** to fit the view.
288
289Canon is **0 star slats** — the hull is sealed, the inner surface is one unbroken
290169,646 km², and the only views out are at the end caps. The runtime control for
291this is disabled and hidden (decisions.md D-033): the terrain raster is baked at 0
292slats, so any other count draws bands over land that has none.
293
294Everything autosaves to this browser's localStorage. Two exports:
295
296| | |
297|---|---|
298| **Export backup** | everything, private notes included. Keep out of the public repo — `.gitignore` already excludes `tower-backup-*.json`. |
299| **Export static map content** | public places only, `notes` stripped. This is `static/world.json`, the world readers see, and the seed for a browser with no local draft. |