From 196dea753708a81038cc51d75feb7ea1dc0aa42e Mon Sep 17 00:00:00 2001 From: eth0net Date: Wed, 30 Sep 2026 22:58:45 +0100 Subject: [PATCH] docs: the icon's reasoning goes beside the code that draws it Thirty-eight lines of spoke angles and corner radii sat in the phases file, which is 18% of a doc about what gets built when. `tools/icons` already holds the generator they describe. Signed-off-by: eth0net --- docs/README.md | 4 ++++ docs/roadmap.md | 38 -------------------------------------- tools/icons/README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 38 deletions(-) create mode 100644 tools/icons/README.md diff --git a/docs/README.md b/docs/README.md index 3837afb..f452b1f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,5 +15,9 @@ doesn't re-derive them; none of it is a spec to build against literally. | [`configuration.md`](configuration.md) | Every variable the binary and the tools read. | | [`ip.md`](ip.md) | The WotC, Scryfall and EDHREC constraints, and the licenses. | +Reasoning that belongs to one tool lives beside it instead: +[`tools/icons/README.md`](../tools/icons/README.md) is what the icon is drawn +from and why. + [`AGENTS.md`](../AGENTS.md) at the root is the condensed orientation for picking the project back up; these carry the reasoning behind it. diff --git a/docs/roadmap.md b/docs/roadmap.md index 16bb8cd..3de5965 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -161,44 +161,6 @@ model too. - Own lexicon namespace, `app.manaweb.game.*` — "game" here means a game being played, not which TCG. Kept apart from collection and deck lexicons. -## The icon takes a theme - -The drawing was already in the pieces it needed to be: three paths are the six -radial spokes, one is the inner ring, one is the outer. So the split was fills -plus a `clipPath` from the inner ring, which catches the lengths of spoke -inside it and makes those the crystal. - -Twelve corners, alternating between radius 31 and radius 26 — six long points -with a shallow dent between each pair, which reads as a hexagon rather than the -circle a regular twelve-sided shape would. The points sit at the six spoke -angles, so the crystal terminates the spokes instead of crossing them. - -Four tokens carry the whole thing: `--web`, `--core`, `--facet` and `--glow`, -set on the `svg` element so a page that inlines it can override them. A token -takes `url(#id)` as readily as a color, so a gradient preset needs the gradient -in `defs` and nothing else — the shape of a theme is already a row of four -values, whatever kind each one is. - -`just write-icons` is the composer that follows from that. It resolves the -tokens to concrete fills, since the renderer reads no custom properties, then -adds a background and an inset, and writes every raster the app ships from the -one drawing. - -Two of those exist for Android alone. A launcher crops a home screen icon to -whatever shape it uses and guarantees only the middle 80%, and it fills a -themed icon from the wallpaper after throwing away every color in it — so one -raster is inset on an opaque background and another is the silhouette, and -neither is what a browser tab wants. iOS takes its icon once, when the app is -added, and the dark alternative is offered through a media query the same way -the favicon's already is. Whether Safari reads it there is untested. - -**A composed app icon is a shipped one, not a chosen one.** iOS fixes a PWA's -icon when it is added to the home screen, and a native app's alternates have to -be in the bundle and picked from a fixed list; Android can take a manifest -change but on its own schedule. So composing produces the set that ships, and -a live choice only reaches the surfaces the app draws itself — the header, and -the SVG the browser reads. The rasters are where a theme is baked in. - ## Multi-TCG (deferred, maybe never) If it ever happens, it's a **fork, not a namespace**: pull the genuinely shared diff --git a/tools/icons/README.md b/tools/icons/README.md new file mode 100644 index 0000000..02da89d --- /dev/null +++ b/tools/icons/README.md @@ -0,0 +1,40 @@ +# The icon takes a theme + +What `bun run icons` draws and why, beside the code that draws it. +`just write-icons` is the recipe. + +The drawing was already in the pieces it needed to be: three paths are the six +radial spokes, one is the inner ring, one is the outer. So the split was fills +plus a `clipPath` from the inner ring, which catches the lengths of spoke +inside it and makes those the crystal. + +Twelve corners, alternating between radius 31 and radius 26 — six long points +with a shallow dent between each pair, which reads as a hexagon rather than the +circle a regular twelve-sided shape would. The points sit at the six spoke +angles, so the crystal terminates the spokes instead of crossing them. + +Four tokens carry the whole thing: `--web`, `--core`, `--facet` and `--glow`, +set on the `svg` element so a page that inlines it can override them. A token +takes `url(#id)` as readily as a color, so a gradient preset needs the gradient +in `defs` and nothing else — the shape of a theme is already a row of four +values, whatever kind each one is. + +`just write-icons` is the composer that follows from that. It resolves the +tokens to concrete fills, since the renderer reads no custom properties, then +adds a background and an inset, and writes every raster the app ships from the +one drawing. + +Two of those exist for Android alone. A launcher crops a home screen icon to +whatever shape it uses and guarantees only the middle 80%, and it fills a +themed icon from the wallpaper after throwing away every color in it — so one +raster is inset on an opaque background and another is the silhouette, and +neither is what a browser tab wants. iOS takes its icon once, when the app is +added, and the dark alternative is offered through a media query the same way +the favicon's already is. Whether Safari reads it there is untested. + +**A composed app icon is a shipped one, not a chosen one.** iOS fixes a PWA's +icon when it is added to the home screen, and a native app's alternates have to +be in the bundle and picked from a fixed list; Android can take a manifest +change but on its own schedule. So composing produces the set that ships, and +a live choice only reaches the surfaces the app draws itself — the header, and +the SVG the browser reads. The rasters are where a theme is baked in. -- 2.51.2