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 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-10-14 17:35:39 -04:00
co-authored by Claude Opus 5.5
parent 5ea0d4fdec
commit 7ef0c1bc14
+20 -1
View File
@@ -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 @@
<span class="step-chip" style:background={playerColor(me.id)}></span>
This is you. Tap a lit square beside your wizard to walk.
</div>
{:else if theirTurnCaption}
<div class="step-caption" aria-live="polite">
<span class="step-chip" style:background={playerColor(view.activePlayerId)}></span>
{theirTurnCaption}
</div>
{/if}
<div class="table-stack" class:fpv-primary={prefs.liveFp && !!view.you && !net.spectating}>
{#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; }