feat(mockups): 12 vellum atlas (11's navigation in 10's style, motif toggle A/B/C)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-30 00:06:43 +01:00
1 parent 89a30e5479
commit 298efca711
3 files changed
+82 -60

No files matched your search

+8 -5
View File
@@ -258,10 +258,10 @@ function drawGeneral(root: SVGElement, mini = false) {
if (g <= 0) return;
const note = g === 1 ? "a year passes" : `${g === 2 ? "two" : g} years at sea`;
// Troy's year passes on the loop below port 5; the long crossing is written on open water.
if (song.sagaId === "troy") txt(root, 410, 630, note, "time-note", { "text-anchor": "middle" });
if (song.sagaId === "troy") txt(root, 410, 578, note, "time-note", { "text-anchor": "middle" });
else {
const a = OV_PORTS[i - 1]!, b = OV_PORTS[i]!;
txt(root, (a.x + b.x) / 2 - 4, (a.y + b.y) / 2 + 34, note, "time-note", { "text-anchor": "middle" });
txt(root, (a.x + b.x) / 2 - 22, (a.y + b.y) / 2 + 24, note, "time-note", { "text-anchor": "middle" });
}
});
@@ -344,7 +344,7 @@ function plateDressing(root: SVGElement, sagaId: string, L: InsetLayout) {
rhumbs(root, 190, 540);
rhumbs(root, 960, 150);
txt(root, 545, 172, "The open sea", "plate-sea-name", { "text-anchor": "middle" });
storm(root, 840, 232, 1.0);
storm(root, 830, 284, 1.0);
rock(root, 420, 540, 18, 9);
rock(root, 446, 556, 9, 13);
rock(root, 880, 470, 22, 3);
@@ -459,7 +459,7 @@ function drawInset(root: SVGElement, sagaId: string) {
const at = L.ports.find((p) => p.song.id === state.shipAt);
if (at) {
const lines = wrap(at.song.title, 15).length;
ship(root, at.x - 34, at.y + 1, `You are here: ${at.song.title}`, -22 - (lines - 1) * 22 - 25 - 24 + 1);
ship(root, at.x - 58, at.y + 1, `You are here: ${at.song.title}`, -22 - (lines - 1) * 22 - 25 - 24 + 1);
}
}
}
@@ -633,7 +633,10 @@ function sailPopover(song: Song) {
const host = plate.getBoundingClientRect();
pop = h("div", "sail-pop", undefined, plate);
pop.style.left = `${box.left + box.width / 2 - host.left}px`;
pop.style.top = `${box.top - host.top + 34}px`;
// Sit below the port's story-time caption, so the popover never covers it.
const times = [...(g.parentElement?.querySelectorAll(".port-time") ?? [])].map((e) => e.getBoundingClientRect().bottom);
const below = Math.max(box.bottom, ...times);
pop.style.top = `${below - host.top + 8}px`;
h("p", "sp-title", song.title, pop);
h("p", "sp-when", song.storyTime.label, pop);
if (song.id === state.shipAt) {