Skip to main content

max / makeover

Strip historical narrative from documentation Remove what a doc used to say, when it changed, the incidents that justified a rule, finished migration narration, and counts and versions that rot. State the rules in the present tense instead. Keep every instruction, prohibition and threshold, and keep the measurements that make a rule actionable. Public-facing docs keep their explanatory voice.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01MptwXZ8k65v19rFmdGAyki
Author: Max Johnson <me@maxj.phd> · 2026-08-31 01:51 UTC
Signed with PGP, not checked
Commit: 540dbe2c93296c8771caec0843734b96eed73973
Parent: 50e6756
4 files changed, +24 insertions, -35 deletions
M README.md +3 -4
@@ -142,8 +142,7 @@
142 142 invert with it, because "black" and "white" mean the darkest and lightest tone
143 143 the theme has, and which intent that is flips between a light theme and a dark
144 144 one. A bare Linux console, a terminal emulator and a generated config that all
145 - consult this agree on what red means; they disagreed for as long as each kept
146 - its own table.
145 + consult this agree on what red means.
147 146
148 147 ### Theme ID
149 148
@@ -171,8 +170,8 @@
171 170
172 171 ## Choosing a theme
173 172
174 - Loading a theme file was always shared; choosing one was not, and every app
175 - re-rolled it. These types are the shared half.
173 + Loading a theme file is one half; choosing one is the other. These types are
174 + the choosing half, so no app re-rolls it.
176 175
177 176 | Item | Purpose |
178 177 | --- | --- |
@@ -22,5 +22,5 @@
22 22
23 23 | What | Where |
24 24 |------|-------|
25 - | All code | `src/lib.rs` (single file, ~585 lines including tests) |
26 - | Theme files | `../themes/*.toml` (16 bundled themes) |
25 + | All code | `src/lib.rs` (single file, including tests) |
26 + | Theme files | `../themes/*.toml` |
M src/lib.rs +14 -24
@@ -4,9 +4,9 @@
4 4 //! MNW web server. Themes are authored by **intent** ("human design"): colors are
5 5 //! declared by role (surface / content / action / status / line / category), not
6 6 //! by hue. This crate is the single place that resolves an authored theme into a
7 - //! full set of intent tokens — including the derived interactive states
8 - //! (hover/active/selection/row-stripe/contrast) that each app used to recompute
9 - //! itself — and emits them as CSS variables or RGB tuples.
7 + //! full set of intent tokens, including the derived interactive states
8 + //! (hover/active/selection/row-stripe/contrast), and emits them as CSS
9 + //! variables or RGB tuples. No app recomputes them itself.
10 10 //!
11 11 //! Theme file shape:
12 12 //! ```text
@@ -482,13 +482,9 @@
482 482 /// or dark, since red is the theme's danger tone either way, which is exactly
483 483 /// why the four achromatic slots are not in this table.
484 484 ///
485 - /// Lifted from Alloy's `skelgen` on 2026-07-31, which had folded three
486 - /// disagreeing hand-maintained copies into one and is the reason the
487 - /// arrangement is trusted. It moved here so a program that paints its own
488 - /// palette at runtime, rather than reading a generated config, resolves the
489 - /// same slots. Slot 14 was the one the copies disagreed on and is
490 - /// `category.six`, which both the Linux console table and the retired
491 - /// `vtrgb.py` had.
485 + /// Here rather than in each consumer, so a program that paints its own palette
486 + /// at runtime resolves the same slots as one reading a generated config. Slot
487 + /// 14 is `category.six`.
492 488 const CHROMATIC: [(usize, &str); 12] = [
493 489 (1, "status.danger"),
494 490 (2, "status.success"),
@@ -776,8 +772,8 @@
776 772 /// Resolve an authored theme into the full intent token set.
777 773 ///
778 774 /// 1. Copy each present base intent from the authored colors.
779 - /// 2. Compute the derived interactive states from the base intents, using the
780 - /// same math the apps used to apply individually (so output is identical).
775 + /// 2. Compute the derived interactive states from the base intents, so every
776 + /// consumer gets identical output.
781 777 ///
782 778 /// Each derived token is emitted only when its source intents exist, mirroring
783 779 /// the skip-missing behavior of the rest of the crate.
@@ -1224,7 +1220,7 @@
1224 1220 Mono,
1225 1221 /// Body and UI text: everything that is not mono or brand. [`FONT_SANS`].
1226 1222 Sans,
1227 - /// The brand / display tier. No house default, per `cdf8ac09`.
1223 + /// The brand / display tier. No house default.
1228 1224 Display,
1229 1225 }
1230 1226
@@ -3104,13 +3100,9 @@
3104 3100 // cannot hold a bevel, not that it is wrong. Shrinking the list is the fix;
3105 3101 // growing it is a regression in the theme, not in this derivation.
3106 3102 //
3107 - // tokyonight left the list on 2026-08-15, and it is the only entry that could
3108 - // leave without a judgment call about someone else's palette. Its page and
3109 - // raised were the identical hex, so it had no ramp at all rather than a
3110 - // shallow one, and the fix is upstream's own `bg_highlight` (#292e42, 0.079
3111 - // above the page) rather than a color we picked. The other nineteen are
3112 - // shallow ramps in published palettes, which is a different claim, and they
3113 - // stay deferred until every app is migrated and eyeballed.
3103 + // An entry leaves this list only when the fix is upstream's own, never a
3104 + // color we picked. The remaining entries are shallow ramps in published
3105 + // palettes, deferred until every app is migrated and eyeballed.
3114 3106 #[test]
3115 3107 fn raised_is_distinct_from_page() {
3116 3108 // Below this, a raised surface and the page under it are one surface to
@@ -4308,10 +4300,8 @@
4308 4300
4309 4301 #[test]
4310 4302 fn the_house_themes_measure_high() {
4311 - // The two we author. Measured 2026-08-28: goingson 6.18/7.01 and
4312 - // audiofiles 6.80/4.78 against page and sunken. A change that drops
4313 - // either below AA is a regression in a theme we control, which is
4314 - // exactly what this crate now knows how to see.
4303 + // The two we author. A change that drops either below AA is a
4304 + // regression in a theme we control.
4315 4305 //
4316 4306 // `high-contrast` is deliberately not in this list. It measures
4317 4307 // 4.89/3.53 and therefore reads as Standard: its muted text misses AA
@@ -48,11 +48,11 @@
48 48
49 49 Neither are the ink's emphasis steps. `content-secondary` and `content-muted`
50 50 are `content.primary` moved 12% and 42% of the way toward `surface.page`, and a
51 - value written under those keys is overwritten at load. They were authored until
52 - 2026-08-16, and separately-authored steps drift: three of the themes here had
53 - ended up with a `secondary` that was lighter than their own `primary`, inverting
54 - the emphasis order every renderer reads. What a theme controls is its ink and
55 - its page; how far back the quieter tones sit is one rule, in one place.
51 + value written under those keys is overwritten at load. Separately-authored
52 + steps drift out of order, so a `secondary` ends up lighter than its own
53 + `primary` and inverts the emphasis order every renderer reads. What a theme
54 + controls is its ink and its page; how far back the quieter tones sit is one
55 + rule, in one place.
56 56
57 57 ### Theme ID
58 58