What an extended playtest found at the table: a move awaiting confirmation is asked in the status strip, which stays in view, and Confirm takes the focus, with Escape to cancel and the selection kept; the squares are one Tab stop, entered at the square last visited; the masthead's buttons wrap at tablet widths instead of running off the page; the glass canvas fits the window's height, seats its camera afresh when the frame turns wide, remembers its view across a spell on the flat boards, keeps its ways to look above the canvas on a phone, and sits a little further from the seat so the far rank fits; a Basilisk's gaze reaches the status line; a move picked from the chronicle is named in the status as lit on the boards as they stand, and its board is brought into view; the end of a game offers a fresh drake, a rematch and the hall together under the result, with the status no longer repeated in the story

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx
This commit is contained in:
Eric WagonerandClaude Fable 5.1 committed 2026-10-27 22:43:04 -04:00
1 parent b88c57f350
commit 13fc4c5ef3
5 files changed
+194 -77

No files matched your search

+5 -1
View File
@@ -43,6 +43,8 @@
} = $props();
let svg: SVGSVGElement | undefined = $state();
/** The one square Tab reaches: the grid is entered once, at the square last visited, and the keys walk it from there. */
let visited = $state<number | null>(null);
/** Arrows walk a board the way it is drawn, Page Up and Page Down climb and descend, Enter picks up and sets down. */
function key(e: KeyboardEvent, i: number) {
const step: Record<string, [number, number, number]> = {
@@ -86,6 +88,7 @@
return { x: PAD_L + f * CELL, y: slot * (boardHeight + GAP) + PAD_T + r * CELL };
}
const drawn = $derived(levels.flatMap((lv) => Array.from({ length: PER_LEVEL }, (_, n) => (lv - 1) * PER_LEVEL + n)));
const entry = $derived(visited ?? selected ?? (levels.includes(2) ? idx(2, flipped ? FILES - 1 : 0, flipped ? RANKS - 1 : 0) : drawn[0]));
const fileLetter = (n: number) => 'abcdefghijkl'[flipped ? FILES - 1 - n : n];
const rankNumber = (n: number) => (flipped ? n + 1 : RANKS - n);
const describe = (i: number) => {
@@ -135,7 +138,8 @@
role={decorative ? undefined : 'gridcell'}
aria-label={decorative ? undefined : describe(i)}
aria-selected={decorative ? undefined : selected === i}
tabindex={decorative ? undefined : 0}
tabindex={decorative ? undefined : entry === i ? 0 : -1}
onfocus={decorative ? undefined : () => (visited = i)}
onclick={decorative ? undefined : () => tap(i)}
onkeydown={decorative ? undefined : (e) => key(e, i)}
/>