diff --git a/CLAUDE.md b/CLAUDE.md index 3c710c3..3f460b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -341,9 +341,10 @@ you.** This section used to say "edit the block, run `npm run verify`, bump `vN` repositories". That was true while the blocks were maintained by hand. It is now the one instruction in this file that silently does nothing. -Six blocks are generated, and the fence markers name them: `design tokens`, `header contract`, -`stage contract`, `language`, `prose reset` and `prose footer`. Everything between and including a -pair of markers belongs to the package. +Ten blocks are generated, and the fence markers name them: `design tokens`, `header contract`, +`stage contract`, `language`, `prose reset`, `prose footer`, `deck transport`, `deck lockup`, +`deck fit` and `deck runtime`. Everything between and including a pair of markers belongs to +the package. ```bash npm run design # rewrite every fenced block from the pinned release @@ -369,9 +370,9 @@ remembering to look. That is the guarantee the old habit-with-a-tripwire never w with a one-line diff. Either one means this site has decided to own that block and diverge. That is a real choice; make it deliberately, in a commit that says so. -**Not everything is generated.** The deck footer is still a hand-maintained copy carrying its own -version marker — see below, where the old discipline applies in full — and the `` contract is -a copy with no fence at all. +**Not everything is generated.** The `` contract is a copy with no fence at all — see +below. The deck footer used to belong here too, hand-maintained; it doesn't any more — see +below, where its old version marker was replaced rather than kept. Both decks under `talks/` carry the system too, and all four pages load their faces from the **one `fonts/` directory at the root** — `../../fonts/` from a deck, as on both sibling sites. @@ -380,20 +381,24 @@ Both decks under `talks/` carry the system too, and all four pages load their fa which has the outlines baked in. A per-deck copy buys nothing and has to be kept in step with the root by hand, with nothing checking that it is. -### The footer carries a version marker, like the tokens +### The deck's chrome fences replaced the footer's version marker -The deck footer is copied across `blust.ch`, `guestgraph.io` and `companygraph.io`, and no -suite can see a sibling — the same gap the token block has. It is fenced by a -`deck footer · vN` marker and `footerVersion` asserts it. +The deck footer used to be a hand-maintained copy across `blust.ch`, `guestgraph.io` and +`companygraph.io`, fenced by its own `deck footer · vN` marker with a `footerVersion` check — +because no suite can see a sibling, the same gap the token block has. Both are gone, not +retargeted: that marker and that check were retired in a previous plan. The deck's whole +chrome and runtime are generated fences now — `deck transport`, `deck lockup`, `deck fit` and +`deck runtime` — exactly like the tokens above. -What the marker covers is a **contract, not a look**: the lockup goes to the landing page, the -person to `blust.ch`, the third link to the talks index, and none of them opens in a new tab. -Change any of that and bump `vN` **in all three repositories**, then run all three suites. A -suite fails two ways — a version it does not expect, and no marker at all — so deleting the -fence is not a way around it. +What the old marker covered was a **contract, not a look**: the lockup goes to the landing +page, the person to `blust.ch`, the third link to the talks index, and none of them opens in a +new tab. That contract still holds; `design:check` is what enforces it now, comparing each +fence's bytes against the pinned release — strictly stronger than `footerVersion` ever was, +because the constant had to be hand-edited in three repositories to stay true, which was the +very drift it existed to catch. -`verify/design.mjs` is byte-identical across the three and holds both `TOKEN_VERSION` and -`FOOTER_VERSION`. Never edit it in one repo alone. +`verify/design.mjs` is byte-identical across the three and holds `TOKEN_VERSION`. Never edit +it in one repo alone. ## The header is a contract, and its copy carries a version @@ -547,8 +552,8 @@ per page, German swapped in at runtime from `data-de`. It becomes correct the da ship, and not before. **The head contract is a third copy**, shared with `guestgraph.io` and `companygraph.io` and -carrying no `· vN` tripwire, unlike the token block and the deck footer. Port changes by hand -to all three. +carrying no `· vN` tripwire, unlike the token block and the deck's other generated fences. +Port changes by hand to all three. ## CI diff --git a/package-lock.json b/package-lock.json index b45e8bd..ab62b12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "blust-ch", "version": "1.0.0", "devDependencies": { - "@robertblust/design": "github:robertblust/design#v0.5.0", + "@robertblust/design": "github:robertblust/design#v0.7.0", "pdf-lib": "^1.17.1", "playwright": "^1.49.1" } @@ -34,8 +34,8 @@ } }, "node_modules/@robertblust/design": { - "version": "0.5.0", - "resolved": "git+ssh://git@github.com/robertblust/design.git#424a9978e0b1c56e5b4134d4c0ec44bcd0d66d7a", + "version": "0.7.0", + "resolved": "git+ssh://git@github.com/robertblust/design.git#2d870f626f32f36879fe3ded8d673f1178ed1c18", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index c5b6991..78c38db 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:instance": "node --test verify/instance.test.mjs" }, "devDependencies": { - "@robertblust/design": "github:robertblust/design#v0.5.0", + "@robertblust/design": "github:robertblust/design#v0.7.0", "pdf-lib": "^1.17.1", "playwright": "^1.49.1" } diff --git a/talks/essential-complexity/index.html b/talks/essential-complexity/index.html index dabca4a..fb00cfc 100644 --- a/talks/essential-complexity/index.html +++ b/talks/essential-complexity/index.html @@ -384,7 +384,7 @@ .name a:hover, .name a:focus-visible{color:var(--ink)} /* ─── end deck lockup ───────────────────────────────────────────────────*/ - /* ─── deck transport · v1 · shared ───────────────────────────────── + /* ─── deck transport · v3 · shared ───────────────────────────────── Generated from @robertblust/design — edit it there and run `npm run design`. The transport bar and the chrome around it, byte-identical on all four decks @@ -396,16 +396,26 @@ `deck lockup`. They were two components wearing one name, and only one of them legitimately differs between sites. - This block holds 53 rules, not the round number a first read of the region + This block holds 57 rules, not the round number a first read of the region might suggest. The marker never closed, so "which rules are inside it" was never a settled question; measured mechanically — everything from the `---------- transport ----------` comment through the transport's own three - mobile breakpoints, minus the lockup's own rules, minus the one rule that shows - the LCD while it carries a message (staying per-deck), minus the speaker-notes drawer and the - slide-layout rules that happen to share the same breakpoints — 53 is what's - left, and all 53 are byte-identical on every deck. Anyone re-deriving this - should get the same 53; if a cut to a smaller, rounder number seems - obviously right, it wasn't obvious here and is worth writing down why. */ + mobile breakpoints, minus the lockup's own rules, minus the speaker-notes drawer + and the slide-layout rules that happen to share the same breakpoints — 57 is + what's left, and all 57 are byte-identical on every deck. That count includes + the rule that shows the LCD while it carries a message, `.lcd:has(.n.msg)`: + below 400px `.lcd{display:none}` hides the counter to make room, and + `lcdMessage()` puts transient text in that same element — but `lcdMessage()` + has exactly one call site, gated on `!pickVoice() && !hasClips()`, and + `hasClips()` returns `clipsSeen`, a constant `true` on every deck today. So the + rule is currently unreachable: no deck ever adds `.msg` to `#lcdn`, at any + width. It stays because it costs nothing and becomes live the moment + `hasClips()` ever probes instead of assuming, so the narrow-screen case is + already handled rather than rediscovered later. `lcdMessage`, `msgTimer` and + both `novoice` strings are dead code for the same reason, on every deck, today. + Anyone re-deriving this should get the same 57; if a cut to a smaller, rounder + number seems obviously right, it wasn't obvious here and is worth writing down + why. */ .transport{ grid-column:2; justify-self:center; display:flex; align-items:center; gap:.45rem; @@ -439,6 +449,11 @@ .tbtn svg{width:18px; height:18px; fill:currentColor; display:block} .tbtn svg.stroked{fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round} .tbtn:hover{color:var(--ink); background:#20242e} + /* aria-disabled, not :disabled — the runtime keeps the control focusable and returns + early from its own handler instead of removing it from the tab order; see + `deck runtime`'s render() for why a real `disabled` moves focus under the user. */ + .tbtn[aria-disabled="true"]{opacity:.35; cursor:default} + .tbtn[aria-disabled="true"]:hover{color:inherit; background:none} .tbtn:focus-visible{outline:2px solid var(--c-mid); outline-offset:2px; color:var(--ink)} .tbtn[aria-pressed="true"]{color:var(--c-mid); background:#1b2231} @@ -497,6 +512,10 @@ /* below this the seven controls need every pixel */ @media (max-width: 400px){ .lcd{display:none} + /* the counter is hidden to make room, but lcdMessage() adds .msg to #lcdn to show + transient text in that same element — a message with nowhere to appear is worse + than a hidden counter, so bring it back when it is carrying one. */ + .lcd:has(.n.msg){display:flex} .transport{padding:.45rem .35rem} .tbtn{width:40px; height:40px} .tside{gap:.1rem} @@ -557,14 +576,6 @@ .kicker{margin-bottom:5vw} } - @media (max-width: 400px){ - /* the LCD is the only surface a "no voice" message ever appears on; hiding it - unconditionally leaves a dead play button on narrow phones with nothing to - say why. Keep it hidden except while it is showing a message (.n.msg). - Per-deck and unfenced — a later plan decides whether it belongs in the shared block. */ - .lcd:has(.n.msg){display:flex} - } - /* ─── display face ──────────────────────────────────────────────────── Set last so it wins over the rules above. The slide headline carries the same face the site's does; everything else on a slide is a label or a @@ -795,7 +806,7 @@

Tools c
-
+
@@ -823,6 +834,55 @@

Sprecher-Notiz