clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

Specify world index presentation and touch controls

Dami committed 6c3654d
commit
6c3654dc3e84021fe6199003b6b951e6e08cfdac
parent
a224fc9aee96317c4ca86d06e3c7bab712867b7a
author
Dami <dami.etoile@gmail.com>
5 files changed, +298 -0
Aopenspec/changes/add-world-index-presentation/.openspec.yaml2+
Aopenspec/changes/add-world-index-presentation/design.md88++++++++++++++++++++
Aopenspec/changes/add-world-index-presentation/proposal.md38+++++++++
Aopenspec/changes/add-world-index-presentation/specs/world-index-presentation/spec.md131++++++++++++++++++++++++++++++
Aopenspec/changes/add-world-index-presentation/tasks.md39+++++++++
A openspec/changes/add-world-index-presentation/.openspec.yaml +2 -0
A openspec/changes/add-world-index-presentation/design.md +88 -0
@@ -0,0 +1,88 @@
1+## Source contract2+3+This change follows the accepted D20 material in `docs/design.md` and the4+designer reply headed **D20 header round 1** in `docs/design-inbox.md`, dated5+2026-09-24. `openspec/changes/add-world-index-navigation/` owns the world view6+model, request origins, world transition events, and navigation behavior. This7+change consumes those values and does not recreate them from level data.8+9+## INDEX header10+11+The desktop and mobile header uses this hierarchy, with 8px between lines:12+13+1. An 11px tracked eyebrow in `--muted`: `INDEX | WORLD NN`.14+2. The world name in `--fg`, weight 800, at 28px on desktop.15+3. The world tagline in `--muted`, falling back to `walk the path, pick a16+ proof`.17+18+The large standalone `INDEX` heading and colliding stacked world-number19+heading are removed from this presentation. World completion is shown as20+`★ n / N`, counted only for the active world. The header must fit its owning21+region at the supported desktop and 390px mobile sizes without overlapping the22+board or footer.23+24+On mobile, the world name may use the existing measured fitting helper and a25+smaller scene-approved size when needed. This change does not alter authored26+world names or the D20 world model.27+28+## World strip29+30+The desktop strip is drawn as `[Q] ◀ ● • • ▶ [E]`: keycaps flank the arrows,31+arrows are 14px, dots are 10px, and the current dot uses the normalized32+world's accent when one is present. Non-current dots use the neutral dot role.33+The strip is a visible control and its hit geometry follows the drawn control.34+35+On mobile, keycaps are omitted. The arrows remain visible 44px tap targets,36+with no change to the one-world-per-gesture behavior owned by D20.37+38+When the D20 seam reports a world switch, the sheet/camera transition uses the39+existing 280ms world ease and the current dot slides between its old and new40+positions over 110ms with the accepted back-ease. The dot and sheet use the41+same transition start, while each keeps its own duration. Reduced motion shows42+the settled dot and sheet immediately.43+44+## First-entry world card45+46+When the stage receives the D20 `world-card` request, INDEX renders the card47+over the stage with the existing iris entry choreography. The card contains:48+49+- the normalized world glyph at 96px;50+- the world name;51+- the tagline, when present;52+- `by <author>`; and53+- an ENTER action shown as a drawn keycap on keyboard layouts.54+55+The card is centered on the ink-and-signal surface and preserves the existing56+hard-edged card lip and Recursive font. The card uses the world's accent as a57+signal color while retaining neutral card surfaces. Card text is fitted and58+wrapped within the card; it must not clip at the supported desktop or mobile59+sizes.60+61+ENTER (or the equivalent confirmed card action) dismisses the card and62+returns to the settled INDEX sheet. Dismissing the card does not select or63+enter a proof. The card is shown at most once per world per session, and a64+Workshop PLAY request uses the same composition with its D20 `workshop` origin.65+On touch layouts the ENTER action keeps its visible keycap style but exposes a66+44px hit target. Reduced motion presents the settled card immediately.67+68+## Mobile INDEX footer and narration69+70+Below 760px or on a coarse pointer, INDEX does not show keyboard keycap71+instructions. Under the active proof banner it shows `tap the cat to play`,72+and the bottom thumb row exposes the menu affordance (`☰ menu`). Workshop is73+reached through that menu. Desktop retains the scene's drawn keycap and verb74+pairs.75+76+The canvas accessible label includes the active world number and name, its77+completed and total proof count, and the Q/E world-switch action on keyboard78+layouts. While the card is open, narration names the world, tagline, author,79+and the ENTER action. Pointer/touch targets and narration must refer to the80+same visible controls.81+82+## Non-goals83+84+- Changing the D20 world model, ordering, progress keys, or navigation.85+- Changing rule evaluation, actor movement, grid coordinates, or simulation86+ snapshots.87+- Adding a new world identity validator or changing pack share data.88+- Changing the board's map geometry or proof solving behavior.
A openspec/changes/add-world-index-presentation/proposal.md +38 -0
@@ -0,0 +1,38 @@
1+# World INDEX presentation2+3+## Why4+5+The D20 navigation change provides a stable world model, world switching6+events, and a first-entry card request. The remaining presentation contract is7+still implicit in the renderer: the INDEX header hierarchy, world strip8+controls, mobile touch affordances, and the card's entry interaction need one9+reviewable specification. The designer's 2026-09-24 D20 header review in10+`docs/design-inbox.md` is the source for the latest placement and timing11+decisions.12+13+## What changes14+15+- Define the first-entry and Workshop world card composition and ENTER input16+ without changing the D20 request seam or installing content.17+- Replace the large INDEX title stack with the accepted desktop and mobile18+ world header hierarchy.19+- Make the world strip an explicit control with desktop keycaps, mobile tap20+ targets, accent-aware dots, and synchronized 110ms dot motion during the21+ 280ms world sheet transition.22+- Define mobile INDEX footer affordances and accessible narration for world23+ identity, progress, actions, and card dismissal.24+25+## Scope boundary26+27+This change owns canvas presentation, layout, animation, hit geometry, and28+accessibility copy. It does not change engine rules, simulation state, integer29+grid coordinates, catalog identity, world ordering, navigation semantics, or30+pack validation. The world model and transition seam are defined by31+`add-world-index-navigation`.32+33+## Impact34+35+Affected modules are the INDEX and world-card renderers, their stage-owned36+presentation input/hit handling, and focused visual/accessibility tests. The37+existing D20 navigation tests and world solver remain separate verification38+gates.
A openspec/changes/add-world-index-presentation/specs/world-index-presentation/spec.md +131 -0
@@ -0,0 +1,131 @@
1+## ADDED Requirements2+3+### Requirement: INDEX SHALL present the active world as the header subject4+5+The INDEX presentation SHALL render an 11px tracked `INDEX | WORLD NN`6+eyebrow, the active world name in `--fg`, weight 800, and its muted tagline7+with 8px vertical spacing. The tagline SHALL fall back to8+`walk the path, pick a proof` when the normalized world has none. The large9+standalone INDEX heading and overlapping world-number stack SHALL not be10+rendered. The presentation SHALL also show `★ n / N`, where both counts are11+scoped to the active world view model.12+13+#### Scenario: Desktop world header establishes hierarchy14+15+- **WHEN** INDEX renders an active world on a desktop canvas16+- **THEN** the eyebrow, name, tagline, and per-world count are legible,17+ separated by the specified spacing, and do not overlap the board or world18+ strip19+20+#### Scenario: Missing tagline uses the approved fallback21+22+- **WHEN** the normalized active world has no tagline23+- **THEN** INDEX renders `walk the path, pick a proof` in the tagline region24+25+#### Scenario: Mobile header remains inside its owning region26+27+- **WHEN** INDEX renders at 390px wide28+- **THEN** the complete world name, fallback or authored tagline, and per-world29+ count remain inside the header region without covering the board or footer30+31+### Requirement: INDEX SHALL render the world strip as an actionable control32+33+The desktop strip SHALL render `[Q] ◀ ● • • ▶ [E]` with drawn Q and E keycaps,34+14px arrows, 10px dots, and one dot per world. The active dot SHALL use the35+normalized world's accent when present; inactive dots SHALL use the neutral dot36+role. On mobile or coarse pointers, keycaps SHALL be omitted and each arrow37+SHALL expose a 44px tap target. Hit geometry SHALL match the visible arrows.38+39+#### Scenario: World strip exposes adjacent actions40+41+- **WHEN** INDEX renders three worlds on desktop42+- **THEN** it shows Q, a previous arrow, three dots, a next arrow, and E in43+ that order, with the active dot accented44+45+#### Scenario: Mobile strip exposes touch targets46+47+- **WHEN** INDEX renders on a 390px canvas or a coarse pointer48+- **THEN** Q/E keycaps are absent and the previous and next arrows each have a49+ 44px tappable target50+51+#### Scenario: Dot slide follows a world transition52+53+- **WHEN** the D20 seam reports a world switch54+- **THEN** the active dot travels from its prior position to its new position55+ over 110ms with back-ease, while the world sheet uses the same transition56+ start and its 280ms ease57+58+#### Scenario: Reduced motion settles the strip59+60+- **WHEN** reduced motion is enabled during a world switch61+- **THEN** the strip renders the destination dot and sheet immediately without62+ an intermediate slide63+64+### Requirement: The first-entry world card SHALL present and dismiss world identity65+66+The INDEX SHALL consume the D20 `world-card` request and render a centered,67+hard-edged card containing the normalized glyph at 96px, name, tagline when68+present, `by <author>`, and an ENTER action. The card SHALL use the normalized69+accent as a signal color, fit all copy inside the card at desktop and mobile70+sizes, and preserve the existing iris entry choreography. ENTER or the71+equivalent confirmed pointer/touch action SHALL dismiss the card and leave the72+player on the settled INDEX sheet without selecting a proof. The card SHALL73+not install packs or mutate simulation state.74+75+#### Scenario: INDEX first entry opens a readable world card76+77+- **WHEN** D20 requests a card with origin `index`78+- **THEN** the card shows the world glyph, name, tagline, author, and ENTER79+ action without clipping80+81+#### Scenario: Workshop PLAY uses the same card presentation82+83+- **WHEN** D20 requests a card with origin `workshop`84+- **THEN** the card uses the same composition and preserves the Workshop85+ selected pack's first node for the subsequent INDEX sheet86+87+#### Scenario: Card confirmation returns to INDEX88+89+- **WHEN** the player confirms ENTER on an open world card90+- **THEN** the card closes and INDEX remains on the active world's sheet; no91+ proof move or simulation turn is recorded92+93+#### Scenario: Touch confirmation has a large target94+95+- **WHEN** the card is rendered for a coarse pointer96+- **THEN** the visible ENTER keycap remains readable and its confirmation hit97+ target is at least 44px high98+99+#### Scenario: Card motion respects reduced motion100+101+- **WHEN** reduced motion is enabled102+- **THEN** the card appears in its settled geometry without an iris intermediate103+104+### Requirement: Mobile INDEX controls SHALL use touch affordances and coherent narration105+106+Below 760px or on coarse pointers, INDEX SHALL omit keyboard keycap hints,107+render `tap the cat to play` below the active proof banner, and expose the108+bottom `☰ menu` thumb affordance. Workshop SHALL remain reached through that109+menu. The INDEX accessibility label SHALL include world number/name,110+world-scoped completion, total proof count, and the keyboard world-switch111+action where keyboard controls are available. An open card label SHALL include112+world identity, author, and its ENTER action.113+114+#### Scenario: Mobile footer removes desktop hints115+116+- **WHEN** INDEX renders below 760px or for a coarse pointer117+- **THEN** it shows the cat play prompt and menu thumb affordance without the118+ desktop ENTER, ESC, or SPACE keycap row119+120+#### Scenario: Accessibility follows the visible world state121+122+- **WHEN** the active world or its completed count changes123+- **THEN** the INDEX label names the current world and its updated `n of N`124+ proof progress, and announces Q/E switching when applicable125+126+#### Scenario: Presentation leaves simulation and grid state unchanged127+128+- **WHEN** any header, strip, card, or mobile footer presentation is measured,129+ animated, or dismissed130+- **THEN** engine rules, simulation snapshots, integer board coordinates,131+ progress keys, and pointer semantics remain unchanged
A openspec/changes/add-world-index-presentation/tasks.md +39 -0
@@ -0,0 +1,39 @@
1+## 1. World header and strip2+3+- [ ] 1.1 Render the accepted desktop/mobile INDEX header hierarchy from the D204+ world view model, including fallback tagline and per-world completion.5+- [ ] 1.2 Render the desktop `[Q] ◀ dots ▶ [E]` strip with accent-aware current6+ dot and visible control geometry.7+- [ ] 1.3 Add mobile 44px arrow targets, omit mobile keycaps, and keep strip hit8+ geometry aligned with the drawn controls.9+- [ ] 1.4 Synchronize the 110ms back-ease dot slide with the D20 280ms world10+ sheet transition and settle both immediately for reduced motion.11+12+## 2. World card13+14+- [ ] 2.1 Apply the accepted centered card composition: 96px glyph, name,15+ tagline, `by <author>`, accent signal, hard-edged surfaces, and ENTER action.16+- [ ] 2.2 Preserve the D20 `index` and `workshop` origins and dismiss the card17+ to the settled INDEX sheet without entering a proof or changing simulation.18+- [ ] 2.3 Fit and wrap card copy for desktop/mobile canvases, expose the 44px19+ coarse-pointer ENTER target, and settle the card under reduced motion.20+- [ ] 2.4 Add focused renderer, input, and accessibility tests for first entry,21+ Workshop PLAY, confirmation, pointer/touch parity, and one-per-session card22+ behavior.23+24+## 3. Mobile controls and narration25+26+- [ ] 3.1 Replace mobile INDEX keycap hints with `tap the cat to play` and the27+ `☰ menu` thumb affordance, keeping Workshop behind that menu.28+- [ ] 3.2 Keep INDEX and open-card accessible labels synchronized with visible29+ world identity, progress, controls, and ENTER dismissal.30+- [ ] 3.3 Verify desktop and 390x844 screenshots for hierarchy, overlap,31+ transitions, card fitting, and footer placement, including reduced motion.32+33+## 4. Verification and handoff34+35+- [ ] 4.1 Run focused presentation and browser tests without changing D2036+ navigation or engine solver behavior.37+- [ ] 4.2 Run the full Node suite and production build.38+- [ ] 4.3 Post the desktop/mobile header, strip, card, and footer evidence to39+ `docs/design-inbox.md` for designer review before release.