From 7ef0c1bc14834559e1ae40219edee61d18ddbdad Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Wed, 14 Oct 2026 17:35:39 -0400 Subject: [PATCH] On a phone, the table fits the screen and another wizard's turn says whose it is The masthead's links never wrapped, so a game widened a phone's page to nearly 500px: the page scrolled sideways and the opening roll-off sat off its centre. And while an automaton's opening turn played back, the rail that says "Automaton is taking their turn" sat below the fold, leaving a board that moved on its own. Of 132 bot-first games, 13 humans never made a move. Now the links wrap, and a caption over the board names the wizard whose turn it is, and says when yours is next. Co-Authored-By: Claude Opus 5.5 --- packages/web/src/App.svelte | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index e0cf7db..e48cb5b 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -420,6 +420,17 @@ view !== null && view.phase === "playing" && view.activePlayerId === view.you && !view.stack, ); const youMustRespond = $derived(view?.stack != null && view.stack.waitingOn === view.you); + /** Another wizard's turn, seen from a phone: the rail that says so sits + * below the fold, and a board moving on its own with no word reads as a + * game running without you. Names the wizard, and whether you're next. */ + const theirTurnCaption = $derived.by(() => { + if (wideScreen || !view || !view.you || net.spectating || local.active || openingRolls) return null; + if (view.phase !== "playing" || view.activePlayerId === view.you) return null; + const alive = view.players.filter((p) => p.alive || p.id === view!.activePlayerId); + const at = alive.findIndex((p) => p.id === view!.activePlayerId); + const next = alive.length ? alive[(at + 1) % alive.length]!.id : null; + return `${view.activePlayerId}'s turn${next === view.you ? " — yours is next" : ""}.`; + }); /** An interruption window (INTERRUPT / OPPORTUNITY FIRE) is your moment: * casting and targeting open up as if the turn were yours. */ const yourMoment = $derived( @@ -3179,6 +3190,11 @@ This is you. Tap a lit square beside your wizard to walk. + {:else if theirTurnCaption} +
+ + {theirTurnCaption} +
{/if}
{#if prefs.liveFp && view.you && !net.spectating} @@ -5246,7 +5262,10 @@ height: 56dvh; } .chronicle { max-height: 30dvh; flex: initial; } - .masthead { gap: 0.45rem; padding-top: 0.5rem; } + /* The table's links wrap to a second line rather than widen the page: + * an unwrapped row pushed a phone's layout past the screen's edge. */ + .masthead { gap: 0.45rem; padding-top: 0.5rem; flex-wrap: wrap; row-gap: 0.25rem; } + .mast-leave, .mast-room { white-space: nowrap; } .boxlid { padding: 1rem 0; } .boxlid-inner { padding: 1.5rem 1.2rem 1.4rem; } .boxlid-title { font-size: 2.3rem; }