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

The [canvas share image](/posts/endgame-and-the-share-card#the-board-outlives-the-game) drew every snake segment as a separate inset square. A straight body looked like a row of tiles, and a curl was almost impossible to follow. The live board already connected consecutive segments and rounded the right corners, so the real question was whether to port that behaviour, duplicate it for canvas, or extract the rule both renderers were trying to express.

## Prototype the awkward shapes

The visual design started with a throwaway canvas prototype covering a straight run, a turn, a tight coil, and two crossing snakes. Removing the gaps and rounding each segment worked for the first two. It failed on the coil: cells that touched geometrically but were far apart along the snake's path merged into a solid block. The chosen version adds a thin background-coloured outline only where two neighbouring cells are not consecutive segments, preserving both the continuous body and the distinction inside a coil.

<InfoBox title="The rule that survived the prototype" variant="note">
  A corner can round only when neither of its two touching sides connects to the previous
  or next segment. Geometric proximity is not enough. The order of the snake's path decides.
</InfoBox>

## Share the decision, not the renderer

The architecture discussion then moved the adjacency and corner-classification rules into one engine-agnostic module. The DOM board translates those answers into CSS attributes, while canvas translates them into rounded rectangles and outlines. The rendering techniques remain different, but neither side gets to invent its own understanding of which cells belong together. An ADR records the same expectation for any future renderer.

The implementation also replaced the live board's separate head, tail, and turning helpers with the unified corner rule from the prototype. That made the change more than a canvas patch, so the regression tests covered every existing board corner case as well as the new image behaviour. The final verification rendered a gap-free rounded snake in the daily recap while confirming that Daily and Duel still looked unchanged during play.

The share image now reads as the same snake the player steered, not a second interpretation assembled from disconnected squares. More importantly, the visual consistency has an explicit owner: one small adjacency seam, shared by both renderers, with canvas-specific paint kept outside it.