diff --git a/build.sh b/build.sh
index 286c9e1..bf9aa0f 100755
--- a/build.sh
+++ b/build.sh
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
-# Assemble dist/ — the CSP-clean static build served at learn.bztmon.com.
+# Assemble dist/ - the CSP-clean static build served at learn.bztmon.com.
# The site's face is the delivery arc (index.html); scripts stay SEPARATE files so
# `script-src 'self'` holds with no 'unsafe-inline' exception. Assembly logic lives
-# in pilot/assemble-arc.mjs (node — the build image carries no python).
+# in pilot/assemble-arc.mjs (node - the build image carries no python).
set -euo pipefail
IFS=$'\n\t'
trap 'printf "build failed at line %s\n" "$LINENO" >&2' ERR
@@ -35,7 +35,7 @@ node pilot/assemble-arc.mjs "$dist"
# No inline JS may survive into ANY served HTML, or the CSP silently kills the page.
for page in "$dist"/*.html; do
if grep -oiE '\n"
- f"\n" + out)
-
-dest = ROOT / "pilot/arc.html"
-dest.write_text(out)
-heroes = len(re.findall(r"data:image/webp", out))
-print(f"built pilot/arc.html {len(out)/1024:.0f}KB ({heroes} heroes inlined)")
diff --git a/pilot/assemble.py b/pilot/assemble.py
deleted file mode 100644
index b494078..0000000
--- a/pilot/assemble.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env python3
-"""Derive the Course I slice manifest from measured geometry, then assemble the pilot.
-
-The cut lines below are NOT eyeballed. They were fitted from the hero's own pixels:
-each slab's bottom edge tracked column-by-column through the void gaps, least-squares
-lines through the left and right arms, tip at their intersection. Symmetry of the two
-arms came out within 0-10% on every slab, which is the check that the fit is real.
-Re-derive with tools/fit-geometry.py if the hero is ever regenerated.
-"""
-import base64, json, pathlib, re, sys
-
-ROOT = pathlib.Path(__file__).resolve().parent.parent
-HERO = ROOT / "assets/dist/docker-layers.webp"
-
-# measured bottom silhouettes: left corner -> bottom tip -> right corner (percent of frame)
-CUTS = {
- "writable": dict(l=(27.75, 27.24), tip=(50.77, 40.73), r=(72.00, 26.87)),
- "code": dict(l=(28.38, 41.34), tip=(49.76, 56.15), r=(71.50, 41.02)),
- "deps": dict(l=(27.88, 56.36), tip=(49.48, 76.21), r=(71.88, 56.30)),
- "base": dict(l=(28.12, 74.41), tip=(49.95, 94.20), r=(71.75, 74.40)),
-}
-EPS = 0.7 # regions grow UPWARD only — the slab in front always covers the overlap.
- # Growing downward would drag a copy of the slab behind into the slice.
-NEST = 0.75 # fraction of each gap closed when collapsed
-
-ORDER = ["base", "deps", "code", "writable"] # paint order: back -> front
-LABEL = {
- "base": ("Base image", "The OS layer everything else is stacked on. Pull it once, "
- "share it across every image on the host."),
- "deps": ("Dependencies", "Your packages and runtime. Change these and every layer "
- "above has to be rebuilt."),
- "code": ("Application code", "Your actual program — usually the smallest layer, and "
- "the one that changes every single build."),
- "writable": ("Writable layer", "Created fresh per container, thrown away when it dies. "
- "Anything written here is not in the image."),
-}
-
-
-def V(c): return [list(c["l"]), list(c["tip"]), list(c["r"])]
-def up(v, e): return [[p[0], round(p[1] - e, 2)] for p in v]
-
-
-def band(top, bot):
- """Region between two silhouettes; sides run to the frame edge, which is pure void."""
- p = []
- p += ([[0, top[0][1]]] + top + [[100, top[2][1]]]) if top else [[0, 0], [100, 0]]
- p += ([[100, bot[2][1]]] + bot[::-1] + [[0, bot[0][1]]]) if bot else [[100, 100], [0, 100]]
- return p
-
-
-def manifest():
- tips = {k: CUTS[k]["tip"][1] for k in CUTS}
- dy, acc = {}, 0.0
- for i, k in enumerate(ORDER):
- if i:
- acc += (tips[ORDER[i - 1]] - tips[k]) * NEST
- dy[k] = round(acc, 2)
-
- regions = {
- "base": band(up(V(CUTS["deps"]), EPS), None),
- "deps": band(up(V(CUTS["code"]), EPS), V(CUTS["deps"])),
- "code": band(up(V(CUTS["writable"]), EPS), V(CUTS["code"])),
- "writable": band(None, V(CUTS["writable"])),
- }
- return {
- "scene": "course-I-docker-layers", "eps": EPS, "nest": NEST,
- "source": "assets/dist/docker-layers.webp",
- "parts": [{"name": k, "title": LABEL[k][0], "blurb": LABEL[k][1],
- "anchor": round(CUTS[k]["tip"][1] - 6, 2),
- "points": regions[k], "dy": dy[k]} for k in ORDER],
- }
-
-
-def main():
- if not HERO.exists():
- sys.exit(f"missing hero: {HERO}")
- man = manifest()
- (ROOT / "pilot/manifest.json").write_text(json.dumps(man, indent=1))
-
- hero = "data:image/webp;base64," + base64.b64encode(HERO.read_bytes()).decode()
- out = (ROOT / "pilot/course-1.tpl.html").read_text() \
- .replace("__MANIFEST__", json.dumps(man, separators=(",", ":"))) \
- .replace("__HERO__", hero)
- out = (f"\n"
- f"\n" + out)
-
- dest = ROOT / "pilot/course-1.html"
- dest.write_text(out)
-
- blocks = re.findall(r"", out)
- print(f"built {dest.relative_to(ROOT)} {len(out)/1024:.0f}KB "
- f"({len(blocks)} script blocks, hero {len(hero)/1024:.0f}KB inlined)")
- for name, part in zip(ORDER, man["parts"]):
- print(f" {name:<9} {len(part['points']):2d} pts collapse travel {part['dy']:5.2f}%")
-
-
-if __name__ == "__main__":
- main()
diff --git a/pilot/course-1.tpl.html b/pilot/course-1.tpl.html
deleted file mode 100644
index 27a45fd..0000000
--- a/pilot/course-1.tpl.html
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
The Exploded Cluster · Course I
-
An image is not a box. It is a stack of frozen diffs.
-
Scroll, and the thing you keep calling "a container image" comes apart in your hands.
- Four layers. Each one only stores what changed from the layer under it.
-
scroll
-
-
-
-
Docker image layers, exploded
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field note. The order of your Dockerfile is a caching decision, not a style choice.
- Put COPY . . above your dependency install and you have told the builder to
- throw away every cached layer every time you change one line of code.
-