import InfoBox from '../components/InfoBox.astro';
import PullQuote from '../components/PullQuote.astro';

Three real fixes anchor these two days, each closing something that had been quietly wrong since it shipped: a board that overflowed at high zoom, assisted mode outliving its welcome, and an end-game screen capable of freezing the browser outright. A run of smaller polish work, duel snake labels, a keyboard layout rework, two more passes at the AI opponent's word choice, filled the rest.

## A board that overflowed off the bottom

The `--cell-size` formula sizing the game board had only ever constrained itself horizontally, against the viewport width; on a phone with display zoom, or at the 400 percent browser zoom WCAG 1.4.10 requires, nothing stopped the board from overflowing the bottom of the screen instead. The fix adds a `--game-chrome-height` token for whatever vertical space the surrounding UI consumes, a second axis on the same formula constrained against it, and a floor so an extreme zoom level computes a very small cell instead of a negative one:

```css
/* before */
--cell-size: min(32px, calc((100vw - 2 * var(--space-4)) / var(--grid-cols)));

/* after */
--game-chrome-height: 10rem;
--cell-size: max(2px, min(
  32px,
  calc((100vw - 2 * var(--space-4)) / var(--grid-cols)),
  calc((100dvh - var(--game-chrome-height)) / var(--grid-rows))
));
```

## Assisted mode, deleted whole

Assisted mode, [added in one evening](/posts/premature-norwegian#norwegian-in-one-evening) nine days earlier, came out completely today: the autocorrect suggestion banner, the API route behind it, the settings toggle, the timer suppression and AI word-length capping it triggered, the leaderboard badge marking an assisted score. The feature had been solving a problem no player had reported, while adding real complexity to four separate systems to do it.

<PullQuote>The feature had been solving a problem no player had reported.</PullQuote>

## The end-game screen that would not respond

The end-game dialog softened the board behind it with a `backdrop-filter: blur(4px)`, and on weaker hardware, consistently on Safari and iOS, that blur had to be recomputed on every animation frame, because a handful of infinite CSS animations kept running behind the dialog: an edible pulse, a blinking text cursor. The combination saturated the GPU and froze the browser outright, the kind of failure a glance at the code would not explain and that took real profiling to catch.

<InfoBox title="What the fix actually stopped">
  The blur came out entirely, with the overlay's background opacity raised from 0.7 to 0.82 to keep
  the same visual separation without recomputing it every frame. The edible pulse and the cursor
  blink both freeze the instant the game ends instead of animating behind a dialog nobody is
  supposed to be looking through. And the per-frame state update was narrowed to mutate only the
  snake and edible properties that actually changed, instead of replacing the whole game-state
  object and waking every subscriber on every frame.
</InfoBox>

## Everything else these two days touched

A duel game now labels each snake "You" and "Them" for its first three turns, fading out afterward. A word that ends in a collision no longer counts toward the best-word record, since its own score was already voided by the crash. A new interactive how-to-play demonstration plays a scripted game against a fixed seed, right on the board, instead of only describing the rules in text. The on-screen keyboard's keys now fill their row instead of sitting at a fixed size, and Backspace moved off the row Submit lives on, so reaching for one no longer risks the other. And the duel AI got two more passes: an adaptive difficulty signal based on how long the player's own recent words have been, and a fix for a sampling bias that had been favoring words early in the dictionary's alphabetical order.

## Where this leaves things

Unlike the last few ranges, most of this one came from hand-branched, Claude-paired commits rather than the coding agent's own queue, and the two problems that needed real profiling and root-cause reasoning, the reflow and the compositing spiral, were exactly the ones that got that closer attention. Two days spent finding out what still did not fit, at the pixel level and the feature level both, is not building the game further so much as making sure what already exists actually holds together.