diff --git a/.github/assets/digest-apart.webp b/.github/assets/digest-apart.webp
deleted file mode 100644
index 8da47b1..0000000
Binary files a/.github/assets/digest-apart.webp and /dev/null differ
diff --git a/.github/assets/digest-card-hero.webp b/.github/assets/digest-card-hero.webp
index d5a18a8..c18dd6c 100644
Binary files a/.github/assets/digest-card-hero.webp and b/.github/assets/digest-card-hero.webp differ
diff --git a/.github/assets/digest-keyed.webp b/.github/assets/digest-keyed.webp
index 9f842ca..fc37cc1 100644
Binary files a/.github/assets/digest-keyed.webp and b/.github/assets/digest-keyed.webp differ
diff --git a/.github/assets/walkthrough-keyed.webp b/.github/assets/walkthrough-keyed.webp
index 6702a49..02bd471 100644
Binary files a/.github/assets/walkthrough-keyed.webp and b/.github/assets/walkthrough-keyed.webp differ
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7900951..891e77e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -37,6 +37,8 @@ Until the first release, changes are recorded under [Unreleased].
### Changed
+- `anatomy`: the flat and screenshot views put each key's text in the margin, joined to its part by a hairline (a bracket for a key with `"span": true`, a dot otherwise), instead of numbered discs and a legend. Below about 560px they fall back to small numbers and the legend; `"notes": "keys"` keeps the old hotspots, and iso always uses them. The flat view takes the iso view's tones with an offset shadow, and its list rows are drawn as raised slabs. The weekly-digests card is drawn flat instead of iso, and the committed weekly-digests and walkthrough-videos posts and the README's hero and example images are re-rendered with margin notes. The examples page and `docs/components.md` show the new hero in place of the iso "apart" picture (`digest-apart.webp` is removed), and the link previews are rebuilt. `lint.mjs` counts margin notes as hotspots, and `inline-assets.mjs` and the gallery handle an SVG ``.
+
- Length guidance sizes a post by the scope of the change, with bands measured against published Cloudflare and Astro posts (`references/story.md`). The deep dive gets a soft ceiling of about 3,000 words: `lint.mjs` warns past it and the author can let it stand.
- Lessons from comparing two outside deep dives with the projects' own announcements: stage a cause a reader would hit in a demo run and show the fix (`references/evidence.md`), read a source's claim in its context before calling it wrong (`references/evidence.md`), walk a report from the top down to a cause even in a deep dive, and let the try-it prove the feature's promise (`references/story.md`), and read the release a feature shipped in for where it fits (`references/brief.md`).
- The skill's argument hint and description name the deck (`[post|video|deck] …`, with a release story and a deep dive as examples), and the site's Deck card shows a `/buildnotes deck …` request like the other outputs. The home page's hero shows the request's shape under the install command: `/buildnotes [post | video | deck] what to write about`.
diff --git a/README.md b/README.md
index 538ab83..5a7e5d9 100644
--- a/README.md
+++ b/README.md
@@ -14,10 +14,10 @@
-
+
-
examples/releases-weekly-digests: Fig. 1 of a build story the skill wrote from a public repo's PRs. Its parts are measured from the shipped card, and on the page they lift, come apart and explain themselves.
+
examples/releases-weekly-digests: Fig. 1 of a build story the skill wrote from a public repo's PRs. Its parts are measured from the shipped card and named in the margin, where pointing at a note picks out its part.
---
@@ -63,7 +63,7 @@ Three full runs are kept as committed examples. Each folder holds the finished p
-
+
@@ -71,7 +71,7 @@ Three full runs are kept as committed examples. Each folder holds the finished p
Before and after: a build story about before/after comparison on uploads.sh, from the public buildinternet/uploads repo. Its figures are the product in use, captured live. Plain style. Read it on the site, or watch its 47-second cut.
-
+
Weekly digests: a build story about the weekly collection digests on Release Notes Index, from the public buildinternet/releases repo. Read it on the site in field notes, with the card above as its first figure, or open post.html for the same post in the Plain style. Its one-minute cut plays in the Motion cut section below.
diff --git a/dev/gallery.mjs b/dev/gallery.mjs
index a680b7f..0bb2b01 100644
--- a/dev/gallery.mjs
+++ b/dev/gallery.mjs
@@ -36,7 +36,7 @@ const ABOUT = {
code: "Real code from git at a given commit, cut to the lines that make the point. Renders the whole figure.",
term: "One command and the output lines that matter. Renders the whole figure.",
strip: "Before/after, or a progression of up to four rounds: images, code or terminal output.",
- anatomy: "The parts of one thing, named: a keyed figure drawn from a parts list measured on a capture. Flat shows it straight on with its own labels, iso at an angle as structure only (it comes apart on request), screenshot puts the keys on the capture itself. Pointing at a part lifts it; pointing at a key fades the rest.",
+ anatomy: "The parts of one thing, named: a keyed figure drawn from a parts list measured on a capture. Flat redraws it straight on in grey and accent tones, and screenshot uses the capture itself; both put each key's text in the margin, joined to its part by a bracket or a dot. Iso draws it at an angle with numbered keys, and comes apart on request. Pointing at a note fades the other parts.",
shader: "A WebGL figure drawn by a fragment shader, for what boxes and lines can't show: many things moving at once, a field or gradient, or pixels that are themselves the subject. Follows the theme, pauses off screen, holds a still frame for reduced motion.",
};
const ORDER = Object.keys(ABOUT);
@@ -61,8 +61,8 @@ const EXAMPLES = {
"strip-rounds.json": "Three rounds of a design, as images.",
"strip-filter.json": "Before and after, as terminal output.",
"anatomy-card.json": "At an angle: structure only, with the object's title on its base. Assembled / Apart lifts the parts off, and the keys go with them.",
- "anatomy-card-flat.json": "Straight on, with the object's own labels. The same spec, through \"from\".",
- "anatomy-card-shot.json": "Keys over the capture itself. Expand opens it full size.",
+ "anatomy-card-flat.json": "Straight on, with the object's own labels and margin notes. The same spec, through \"from\".",
+ "anatomy-card-shot.json": "The capture itself, with margin notes. Narrow the page to see numbers and a legend instead.",
"shader-jitter.json": "Many things at once: 80 clients retrying, and the load they put on the server. Loops every 5 s on u_phase; labels sit over the canvas.",
"shader-rehash.json": "The mechanism behind a number: which keys move when a server joins, and why the ring moves so few. Loops every 5 s.",
"shader-banding.json": "When the pixels are the subject: a rendering fix, shown on the reader's own screen. A still shader, with the level count as an extra uniform.",
@@ -85,7 +85,7 @@ for (const f of specs) {
const kind = f.split("-")[0];
const id = f.replace(/\.\w+$/, "");
const text = readFileSync(join(specDir, f), "utf8");
- const frag = renderKind(kind, text, { id, base: specDir, style }).replace(/src="img\//g, `src="${imgBase}/img/`);
+ const frag = renderKind(kind, text, { id, base: specDir, style }).replace(/(src|href)="img\//g, (_, a) => `${a}="${imgBase}/img/`);
for (const w of takeWarnings()) { warned++; console.error(`! ${f}: ${w}`); }
const name = id.slice(kind.length + 1);
const whole = /^(code|term)$/.test(kind);
diff --git a/dev/test/anatomy.test.mjs b/dev/test/anatomy.test.mjs
index a730fc1..60dcd46 100644
--- a/dev/test/anatomy.test.mjs
+++ b/dev/test/anatomy.test.mjs
@@ -1,4 +1,4 @@
-// Checks for the anatomy renderer: one parts list, three views, each a keyed figure. Run: node --test dev/test/*.test.mjs
+// Checks for the anatomy renderer: one parts list, three views, margin notes or numbered keys. Run: node --test dev/test/*.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
@@ -15,29 +15,64 @@ const card = spec("anatomy-card.json");
const hotspots = (html) => [...html.matchAll(/