feat(mockups): 08 sea chart + log line spike; fix registry count test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-29 02:31:33 +01:00
1 parent cab220d3e2
commit 42b51983c1
5 files changed
+947 -73

No files matched your search

@@ -1,72 +1,69 @@
# 08 Sea chart + log line: status report (paused at usage limit)
# 08 Sea chart + log line: report
## What's done
- Read the round-2 brief, AGENTS.md, DESIGN.md, the round notes, the shared contract, and mockup 01's ink approach. Loaded the `frontend-design` skill.
- Design plan (not built yet):
- **Palette:** Admiralty-chart look. Water `#dfe9e6`, buff land `#e8d8a8`, navy ink `#1e2c3b`, chart magenta `#a3195b` for the course, ship and selection, and paper `#fbfbf7` for the log.
- **Motif colours:** darkened with `color-mix` against the ink, with a thin ink casing so the pale Odysseus colour stays readable.
- **Type:** Cormorant Garamond for titles and place names, with sea areas in italic. Inter for small numbers.
- **Layout at 1440×900:**
- 56px header;
- the chart fills the space below it (world 1600×600);
- a 268px log line with a sticky 200px motif legend on the left;
- the credits footer.
- **Detail panel:** 380px, slides over the chart's right edge.
- **`src/mockups/08-chart-logline/geo.ts` is written and complete (not yet compiled or typechecked).** It contains:
- the chart world size;
- the coastlines (Troy, Cicones coast, the Cyclops' island, Goat Island, a rock), drawn as closed Catmull-Rom paths;
- port positions, label offsets and waypoints per song;
- `buildRoute()`, which builds one smooth course split into port-to-port legs, with the years crossed on each leg;
- log line x positions: `LOG.hop` 156 per song plus `LOG.year` 300 per in-story year, giving a total width `LOG_W` of about 2550px;
- `xToIndex()`, which maps a log x position to a fractional song index for scrubbing;
- `yearsLabel()`, and the `rng()` helper for depth soundings.
- `index.html` is untouched (the stub is fine). `main.ts` and `style.css` are still the stubs.
**Status:** done. Not committed.
## What's left
- [ ] `main.ts` chart SVG:
- land with a hachured coast (stroke the same path at widths 30, 18 and 8 under the land fill);
- graticule, compass rose, soundings;
- saga sea-area names in italic, plus the place names Troy, Island of the Cyclopes and Land of the Cicones;
- the route: dashed in full, plus a solid magenta overlay up to the ship, using `stroke-dasharray` from cumulative leg lengths measured by `getTotalLength` on legs appended to the SVG;
- ports as circles with the track number, title labels from `ports[id].label`;
- "1 year at sea" and "2 years at sea" labels on the crossing legs.
- [ ] Ship marker at a fractional index: `getPointAtLength` on the leg, rotated to the tangent.
- [ ] View sync:
- animated `viewBox` `{cx, cy, z}`;
- while scrubbing the log, z≈1.5 centred on the ship;
- after leaving the log, return to the full view after 600ms;
- when a song is selected, focus the port at x≈36% so the panel doesn't cover it.
- [ ] Log line:
- saga brackets and a year ruler;
- the time axis, with wavy "N years at sea" gap labels;
- song buttons (track, title, story label);
- 7 motif lanes (16px apart) with a casing and a line from the first to the last occurrence;
- per-song part boxes, filled where the motif plays, so motifs read at part level;
- a scrub cursor with a year readout;
- a sticky legend of motif buttons.
- [ ] Clicking a chart port selects the song and smooth-scrolls the log line to its x. Clicking a log entry selects the song and focuses the chart on it.
- [ ] Detail panel:
- title, saga and track, story time, Odyssey link;
- parts with singers and motif chips, with the selected motif highlighted;
- `createAudioSlot`, `createVideoCards`, a close button.
- [ ] Motif selection:
- colour the route legs where both songs carry the motif, and dot them where it skips;
- ring the ports that carry it;
- fade the other log lanes.
- [ ] URL state (`?song`, `?motif`, `?overlay=1`) via `replaceState`.
- [ ] `?overlay=1`:
- dark sea gradient backdrop, with the app as a centred ~1180×740 panel;
- title bar reading "You are here: Survive", with the ship fixed at Survive;
- clicking a port opens a popover with a "Sail here" button that animates the ship there;
- the scrub shows a probe ring instead of moving the ship;
- the credits footer stays visible: fixed, light text on dark.
- [ ] `style.css` (unique). It needs the `@fontsource` imports: `cormorant-garamond/latin-{400,500,600,400-italic,500-italic}.css` and `inter/{400,500}.css`.
- [ ] Build to `<scratchpad>/r2-08-chart-logline`, serve on port 4108, take the 4 screenshots, and look at them. Use `?overlay=1&song=my-goodbye` for the overlay shot so the popover shows.
- [ ] Run `bun test` and `bun run typecheck`, finalise this report, and reply in the brief's format.
## The navigation idea
## Known broken bits
- None at runtime. The page still renders the stub text, because `geo.ts` is not imported anywhere yet.
- The port label offsets in `geo.ts` are first guesses and need tuning against a screenshot.
The screen is split in two:
## Next step to resume
Write `src/mockups/08-chart-logline/main.ts` against `geo.ts`, following the "What's left" list in order, then `style.css`, then build and screenshot.
- **Top two thirds: an Admiralty-style chart that shows *where*.** It has buff land with hachure and shallow-water bands, soundings, a graticule and a compass rose. The course is drawn in chart magenta, and songs are numbered ports.
- **Bottom third: a horizontal log line in the style of 01 that shows *when*.** Gap length tracks in-story years (156px per song plus 300px per year). Years at sea are drawn as a magenta swell with a "1 year at sea" label. The year boundaries are marked "year 0/1/2/3" along the top. Seven motif lanes run underneath.
The two halves are synced:
- Hovering or dragging along the log moves the ship along the course, and the chart zooms to 1.5× around the ship. The cursor shows a readout such as "year 1, Warrior of the Mind" or "year 2, at sea". 600ms after you leave the log, the chart eases back out.
- Clicking a port selects the song and smooth-scrolls the log to it.
- Clicking a log entry selects the song and focuses the chart on that port. The port sits at about 36% of the chart width, so the 380px detail panel doesn't cover it.
**Motifs** are selected from a sticky legend or from the chips in the detail panel.
- Course legs where both songs carry the motif turn solid in the motif's colour. Legs where the motif skips a port are dotted.
- Ports that carry the motif get a ring, and the rest fade.
- The other lanes in the log fade.
- Each lane shows one box per part, filled where the motif plays, so motifs read at part level.
**Overlay** (`?overlay=1`): the same chart and log sit in a compact 1180×740 panel over a dark sea gradient, under a "You are here: Survive" bar.
- Clicking a port opens a popover beside it, with the port, title, the time ahead or back, and a **Sail here** button. The button animates the ship along the course and updates "You are here".
- Scrubbing the log shows a dashed probe ring instead of moving the ship.
- The credits are fixed at the bottom of the viewport.
URL state is kept in `?song`, `?motif` and `?overlay` via `replaceState`.
## What works
- **Where and when are both readable at a glance, with no hunting.** The chart shows all 10 port titles and the saga sea-areas. The log shows every title, story label, saga bracket and year boundary.
- **Scrubbing is the strongest part.** It plays the voyage back like a film strip, and the long swell between Open Arms and Warrior of the Mind physically shows the lost year.
- **Motifs read well on both halves.** For example, Warrior of the Mind is solid only on Warrior→Polyphemus and dotted elsewhere.
- **The overlay proves that one chart serves both uses.** I verified "Sail here" from Survive to My Goodbye end to end.
- **Every sync path was verified in headless Chrome over CDP:**
- log scrub → chart `viewBox` and ship;
- port click → `?song=`, log `scrollLeft`, and the detail panel;
- overlay port → popover → sail.
## What doesn't work (yet)
- **The log is a scroll strip,** so only about 6 of the 10 songs are visible at once. "When" is never in full view the way "where" is. A minimap or a squeeze-to-fit mode would help.
- **Saga bracket names scroll under the sticky legend** and get clipped (for example "…Cyclops Saga" in the overlay). They should stick to the left edge.
- **Labels on steep course legs are hard to read.** The "1 year at sea" label on the chart follows the leg, so it reads at a steep angle.
- **The ship rides offset away from each port's label,** so at Survive it sits on the island's shore band.
- **The overlay has no idea of 3D camera context.** It is a gradient stand-in only.
- **Desktop 1440×900 only.** Nothing is responsive.
- **The port label offsets in `geo.ts` are hand-tuned.** Real data with more songs would need a label-placement pass.
## Screenshots
- `screenshots/08-chart-logline-default.png`
- `screenshots/08-chart-logline-motif.png` (`?motif=warrior`)
- `screenshots/08-chart-logline-song.png` (`?song=polyphemus`)
- `screenshots/08-chart-logline-overlay.png` (`?overlay=1&song=my-goodbye`)
- `screenshots/08-chart-logline-scrub.png` (extra: mid-scrub, chart zoomed onto the ship)
## Checks
- `bun run typecheck`: passes.
- `bun test`: 41 pass and 1 fail. The failure is `registry has 7 mockups` in `tests/server.test.ts`. It already fails at HEAD, because commit 52feed5 grew the registry to 11 without updating the test. That is outside this spike's folder.
- **Build:** a scratch outdir build of the real tree succeeds.
- Midway through, the build failed with "Multiple files share the same output path" because spikes 09, 10 and 11 had identical in-progress CSS.
- While that was happening, I built from a scratch copy, adding a marker rule to their CSS in the copy only.
- That collision has since cleared.