diff --git a/docs/design/002-sea-chart-spikes/09-chart-transit-report.md b/docs/design/002-sea-chart-spikes/09-chart-transit-report.md index baf5490..a0b14f9 100644 --- a/docs/design/002-sea-chart-spikes/09-chart-transit-report.md +++ b/docs/design/002-sea-chart-spikes/09-chart-transit-report.md @@ -1,102 +1,97 @@ -# 09 — Schematic sea chart (`09-chart-transit`): interrupted +# 09 — Schematic sea chart (`09-chart-transit`): report -Status: **stopped before any code was written** (the coordinator called a halt for the usage limit). -`src/mockups/09-chart-transit/` is still the untouched stub. No files were left half-edited. +Status: **done**. Built from the saved plan. `bun test` (42 pass) and `bun run typecheck` pass. The build +goes to the scratchpad outdir `r2-09-chart-transit`, served on port 4109. Nothing is committed. -## What's done +Files: `src/mockups/09-chart-transit/layout.ts` (new), `main.ts`, `style.css`. `index.html` is unchanged. -- I read the brief (`round2-brief.md`), `AGENTS.md`, `docs/design/002-direction-round-notes.md`, the shared contract (`src/data/*.ts`, `src/shared/*.ts`), the layout code for mockups 03 (`map.ts`) and 07 (`route.ts`), and the screenshots for 01, 03 and 07. -- I loaded the `frontend-design` skill and settled the design plan below. It is not built yet. +## The navigation idea -## Design plan (settled, ready to build) +The ship's course is straightened into a transit-map schematic, like mockup 03: +- x is story time: a hop of 92 between songs, +100 per year, +70 when the saga changes. +- Each saga is a horizontal row, and the rows are joined by single 45° diagonals in the gaps between + ports. Every port therefore sits on a horizontal, and every label is level and unrotated. +- Under the course is a faint Admiralty-style chart: pale water, rhumb lines from a compass rose, buff + "saga islands" with a shoal band and dashed depth contours, and a dashed storm cell at Storm. -**Look:** this is an Admiralty-chart palette, not cream parchment. -- Deep water `#f4f7f5` is the background. -- Shoal bands `#d3e5ea`. -- Buff land `#ecdca4`. -- Navy chart ink `#1f3346`. -- Chart magenta `#a8326e` marks the ship's course and "you are here". This is the one bold element. -- Fonts are Cormorant Garamond and Inter, both via `@fontsource`: - - Cormorant: upright for land and saga names, italic for sea areas and in-story time. - - Inter: port labels and UI. +Motifs run as coloured lanes parallel to the magenta course: +- Character themes run on the left of the course and musical motifs on the right, each in a fixed lane. +- A lane is solid where the motif plays in consecutive songs. A single song gets a ~30px stub. +- A dotted lane means the theme is silent there and returns later. +- Each port is a capsule across the course and every lane that calls there. -**Schematic layout** (to go in `layout.ts`): -- The x-axis is story time: - - hop 92 between songs; - - +110 per year; - - +50 when the saga changes; - - X0 = 110. -- The rows are octilinear: - - Troy row at y≈290; - - a 45° diagonal down to the Cyclops row at y≈410; - - a long diagonal down to Storm at y≈590. -- The diagonals sit only in the gaps between ports, so every port is on a horizontal. -- Labels are horizontal, centred above each port, and wrap to two lines (max ~88px). -- The `storyTime.label` goes in italic below the lanes, with a year tag wherever the year changes. -- Gaps of a year or more carry an italic note on the course, such as "a year passes". +A slider (with "Schematic" and "True geography" end buttons that animate) morphs every sample of the +course to a rough equirectangular Aegean–Ionian map. Land crossfades to coastlines, a graticule fades +in, lanes pull closer to the course, and names give way to track numbers. -**Motif lines:** -- Each motif gets a fixed lane parallel to the course: character themes on the left (north) side, musical motifs on the right (south) side, spaced 10 apart. -- A lane is drawn only over runs of consecutive songs that contain that motif. A single-song run gets a ±30 stub. -- Between runs, a faint dotted lane shows the motif returning. -- Lanes are built as offset polylines with miter joins, plus `roundedPath` (re-implement it locally; don't import from 03). -- Pale data colours are darkened toward a warm dark until they reach about 2.6:1 contrast on the paper. Each line has a paper-coloured casing. -- At each port, a capsule perpendicular to the course spans the lanes present. A port with 2 or more motifs is an interchange and gets a heavier border. +## What works -**Chart layer:** -- A compass rose in the empty top-right, around (1210, 190), with faint rhumb lines radiating across the chart. -- Schematic islands: soft blobs drawn as closed Catmull-Rom curves. - - A Troy blob under the Troy row. - - A Cyclops blob under the Cyclops row. - - A storm cell (dashed rings) at Storm. - - Dashed depth contours, drawn as scaled copies of each blob. +- **Readable at a glance (the round's question).** At the default 1440×900, all ten song titles, + three saga names, every in-story time label, the year tags (Year 0, 1, 3) and the gap notes ("a year + passes", "two years pass") are visible together with no hunting. Straightening the course is what + makes this possible. +- **Motif tracing is very clear.** + - Selecting a theme fades the other lanes to 13% and rings its ports in the theme colour. + - Ports that don't carry it are greyed. + - The key prints "plays in 5 songs: …". + - The dotted "returns later" stretches show when a theme goes silent and comes back. 03 couldn't + show that. +- **One chart serves both uses.** At `?overlay=1` the same SVG renders inside a ~1180×650 card over a + dimmed sea gradient: + - the viewBox is cropped to the course; + - time labels are hidden and the key becomes chips; + - a magenta ship marker reads "You are here: Survive"; + - clicking a port opens a popover with **Sail here** (the ship animates along the course and the + pill reads "Sailing to Storm", then "You are here: Storm") and **Song details**. +- **The morph earns its place.** At `?morph=1` you see that the voyage really doubles back westward, + and the slider makes the cost of geography obvious: ports 06–09 cluster at Messina and their names + can't fit. +- **Detail drawer.** + - Contents: track and saga, title, story time with years after Troy, Odyssey link, theme chips (which + select the motif), parts with singers and motif dots, `createAudioSlot` and `createVideoCards`. + - The chart pans left when the open port would sit under the drawer, e.g. Storm. +- **Interactions and accessibility.** + - URL state: `?song=`, `?motif=`, `?overlay=1`, plus `?morph=0..1` and `?pop=` for screenshots. + - Escape closes the popover, then the drawer, then the motif. + - Ports are keyboard-focusable. + - Reduced motion is respected. +- **Credits.** The credit is fixed at the bottom and fully visible in every state. +- **Verification.** Click flows were checked over Chrome DevTools: port → drawer, key → motif, + geography button → morph=1, overlay popover → Sail here → arrival, and popover → details. No console + errors. -**Morph slider (schematic ↔ true geography):** -- Sample the course densely by schematic parameter `u`. -- The geo course is a polyline through the songs' lon/lat in an equirectangular projection (lon 11–28.5, lat 35–42, x scaled by cos 38.5°). -- Point = lerp(schematic(u), geo(u), t). Recompute the lanes and ports for every `t`. -- Land crossfades between the schematic blobs and rough Mediterranean polygons: Italy, Sicily, Greece with the Peloponnese, Asia Minor, Crete and Ithaca. I drafted the coordinates in my head; re-derive them. -- Geo positions: - - songs 1–4 near Troy/Ismarus (26.2,40.0 → 24.6,40.3); - - Warrior of the Mind off Cape Malea (22.0,36.0), with via-points so the route avoids Attica; - - the Cyclops songs on Sicily (~15,37.7); - - Storm NW of Sicily (13.0,38.9). -- As `t` rises, the time labels fade out and port labels shrink to track numbers, which shows the trade-off. -- Support `?morph=0..1`. +## What doesn't work (or is weak) -**Page:** -- Title cartouche at top-left, morph control at top-centre, motif key at bottom-left. -- The detail drawer is about 400px on the right and pans the chart when the port would be hidden. - - Contents: title, story time, Odyssey link, parts with singers, motif chips, `createAudioSlot`, `createVideoCards`. -- Selecting a motif fades the other lanes and rings the ports where it plays. -- The footer is styled to be always visible. -- URL params: `?song=`, `?motif=`, `?overlay=1`. +- **Geo mode is a demo of the trade-off, not a usable view.** + - The four Troy ports and the four Cyclops ports bunch up. + - Capsules overlap at the turnarounds, and you only get track numbers. + - The midpoint of the morph (~0.5) is messy: big rotated capsules and two land layers crossfading. +- **The coastlines are hand-drafted and rough.** Hellas and Thrace are one blob, and the Peloponnese + is crude. +- **Song positions are illustrative.** Geo positions per song are rough guesses: Troy and Ismarus, + off Cape Malea, the cave on Sicily's east coast, and Storm north-west of Sicily. They are not + checked against the musical. +- **Interchanges were redefined.** In the sample data every song has 2 or more themes, so I made an + "interchange" mean **3 or more** themes meet. Otherwise every port would be one. +- **Horizontal space is tight.** The hop of 92 only works because titles wrap onto two balanced lines. + The full album (~40 songs) won't fit one screen at this density, so it would need horizontal + panning like 03, or rows that wrap per saga. +- **Many dotted lanes.** Seven lanes plus dotted returns along the whole course get busy. Without a + motif selected, the dotted returns compete a little. +- **Small chart details.** + - In overlay mode, the "N" of the compass is cropped and the ship marker covers the Survive capsule. + - The Odysseus colour was pushed to a brown (contrast 4.6) so it doesn't collide with Warrior gold. + It is no longer the data colour `#f2e3b3`. +- **The key covers some land.** The key panel covers the south-west corner of the Troy island, and the + western lon labels in geo mode. -**Overlay (`?overlay=1`):** -- A dimmed CSS-gradient sea backdrop. -- The chart as a compact card, about 1180×650: story-time labels hidden, key as compact chips, slider hidden. -- A magenta ship marker reading "You are here: Survive". -- Clicking a port opens a popover with "Sail here", which animates the ship along `u`. +## Screenshots -## What's left - -- [ ] Write `layout.ts`: schematic trunk, port positions, geo coordinates and polygons, morph sampling, offset lanes, `roundedPath`, blobs. -- [ ] Write `main.ts`: SVG render (static chart layer plus a dynamic layer rebuilt on morph), key, motif select, detail drawer, URL params, overlay mode with Sail here, `mountCredits()`. -- [ ] Write `style.css`. It must stay unique, not byte-identical to any other mockup's. -- [ ] Update the `index.html` title if needed. Keep `