| index 8d86190..1f4e859 100644 |
| --- a/docs/superpowers/specs/2026-09-02-word-processor-basics-design.md |
| +++ b/docs/superpowers/specs/2026-09-02-word-processor-basics-design.md |
| @@ -178,6 +178,25 @@ action inside a run-level control group. |
| |
| ### 3.2 Contents |
| |
| +**What of this actually shipped, since the list below is the plan and |
| +not the record.** Built and reachable: the whole bar; File's New |
| +document, Open, both downloads, Print and Sign out; Edit's Undo, Redo |
| +and Select all; View's Paged/Infinite pair; Format's marks, paragraph |
| +styles, alignments, lists, quote, indent/outdent and Clear formatting; |
| +Tools' Word count and Keyboard shortcuts. Rendered and greyed, each |
| +naming the section it waits on: Insert's Link, Image, Table, Page break |
| +and Horizontal line, Edit's Find and replace, View's Show ruler. |
| + |
| +**Not built and not in the menu at all**: Rename, Make a copy, Page |
| +setup, Cut/Copy/Paste, Full screen, Special characters, Spelling. The |
| +list below still names them because it is the design; they are called |
| +out here so nobody reads an unmarked line as a promise that was kept. |
| +Cut/Copy/Paste in particular should not be built — a `<button>` cannot |
| +drive the clipboard reliably (`execCommand` is deprecated, |
| +`navigator.clipboard.read` is permission-gated and absent in Firefox), |
| +and a menu item that sometimes fails is worse than one that is not |
| +there. |
| + |
| Real tonight unless marked. Items that are present-but-disabled are |
| listed because a menu that hides what the app will obviously grow is a |
| menu that gets redesigned; one that greys it is a menu that gets filled |
| @@ -240,7 +259,13 @@ it has to be *principled*, or the two drift: |
| - **State flows one way.** The ProseMirror plugin that already keeps |
| toolbar `aria-pressed` in step (`toolbar.mjs`'s plugin, updating on |
| every selection change including remote ones) also sets menu items' |
| - `aria-checked`. Nothing listens for clicks to infer state. |
| + `aria-pressed`. Nothing listens for clicks to infer state. |
| + |
| + `aria-pressed`, not the `aria-checked` this said first: these menus |
| + are disclosures whose items are ordinary `<button>`s, and |
| + `aria-checked` belongs to `menuitemcheckbox` and `menuitemradio`. |
| + Putting an attribute on an element it does not apply to is worse than |
| + putting none on at all. |
| |
| ### 3.4 Keyboard, ARIA, and 320px |
| |
| @@ -285,14 +310,24 @@ implementation — so the bar is one tab stop. |
| the menu was ever opened. |
| - 24×24 minimum targets. The existing `[docs-tool]` is 28px and clears |
| this; menu items are full-width rows and clear it comfortably. |
| -- **At 320px the bar does not scroll and does not overflow.** Six menu |
| - titles do not fit 320px. Below a breakpoint the bar collapses to a |
| - single `Menu` button opening one `role="menu"` whose items are the |
| - six menus as submenus. This is one component in two arrangements, not |
| - two components: same command table, same names, same tests. The |
| - reflow check must be green with the menu bar present, and must be |
| - extended to cover the collapsed arrangement — extended, never |
| - relaxed. |
| +- **At 320px the bar wraps. It does not scroll and it does not |
| + collapse.** Six menu titles do not fit 320px, so `flex-wrap` puts |
| + them on two lines and every one stays reachable. |
| + |
| + This originally specified collapsing to a single `Menu` button |
| + opening one `role="menu"` whose items were the six menus as |
| + submenus — a design that contradicted this same section's rule |
| + against nested `<details>`, which is the `rst-menus` trap the Sheets |
| + session hit first. Wrapping keeps ONE component in ONE arrangement: |
| + same markup, same command table, same keyboard behaviour at every |
| + width, nothing changing shape at a breakpoint. The only thing the |
| + media query moves is the panel, which spans the bar below 30rem |
| + rather than hanging off its own title, because an anchored 14rem |
| + panel overflows a 320px viewport — and the page gaps, whose negative |
| + margin has to match the page padding it is pulling out of. |
| + |
| + The reflow check must be green with the menu bar present, and |
| + extended, never relaxed. |
| |
| ### 3.5 Visual direction |
| |
| @@ -534,16 +569,33 @@ own failure mode, and the one this repo has already been bitten by. |
| |
| ### 9.2 The toggle |
| |
| -`View → Paged` / `View → Infinite`, a `menuitemradio` pair. It is a |
| -**per-person preference, not a document property** — how you like to |
| -read is not something you impose on a collaborator. Stored in |
| -`localStorage`, defaulting to infinite, applied before first paint to |
| -avoid a visible reflow. |
| - |
| -Infinite is one `[docs-page]` box that grows. Paged repeats |
| -`[docs-page]` once per computed page with the desk showing between them |
| -— the shape `show.html`'s own comment says it was built to allow |
| -("one box, its own padding, ready to hold more than one sibling"). |
| +`View → Paged` / `View → Infinite`, a pair of `<button>`s carrying |
| +`aria-pressed` — not `menuitemradio`, for §3.3's reason: these menus are |
| +disclosures and their items are ordinary buttons. It is a **per-person |
| +preference, not a document property** — how you like to read is not |
| +something you impose on a collaborator. Stored in a **cookie**, |
| +defaulting to infinite. |
| + |
| +A cookie rather than the `localStorage` this first specified, and the |
| +reason is in the same sentence that specified it: "applied before first |
| +paint". `localStorage` is invisible to the server, so the mode could |
| +only be applied once the deferred bundle ran — which is a document |
| +visibly reflowing from infinite into pages a moment after it appears. |
| +The server reads the cookie and renders `data-view` on the canvas, so |
| +the first paint is already right. |
| + |
| +Infinite is one `[docs-page]` box that grows. Paged is the SAME single |
| +box, with a desk-coloured gap drawn between pages as a widget |
| +decoration inside the text flow. |
| + |
| +Not one `[docs-page]` per page, which is what this said first and what |
| +`show.html`'s own comment anticipated ("one box, its own padding, ready |
| +to hold more than one sibling"). ProseMirror owns everything inside the |
| +editable element (`{mount: el}`), so its children cannot be wrapped in |
| +sibling page boxes without taking the document away from it. Repeating |
| +the box is a layout-engine shape; a decoration is a |
| +pagination-as-a-view shape, which is what §9.1 already committed to. |
| +`show.html`'s comment is corrected in the same commit. |
| |
| ### 9.3 Explicit page breaks |
| |