# VK community cover

The cover art for the VK community (`1920×768`). The community avatar — the «Э» tile — is
uploaded separately; this is only the backdrop behind it.

| File | What |
|------|------|
| `cover-night-spot.png` | the dark cover — board in a warm spotlight |
| `cover-day-spot.png` | the light cover — same camera, same crop, daylight |
| `build-cover.mjs` | the generator both are rendered by |

`build-cover.mjs` is a small software renderer that draws an Эрудит board in perspective with
the opening `ГРАМОТНОСТЬ / СОПЕРНИК / ЭРУДИЦИЯ / УМ` already played, and writes the two PNGs
next to itself.

```sh
cd assets/vk/cover
node build-cover.mjs                # both covers
node build-cover.mjs night-spot     # one of them
FAST=1  node build-cover.mjs        # 1x instead of 2x supersampling, for quick iteration
ZONES=1 node build-cover.mjs        # overlay the VK keep-outs on the render
LAYOUT=cross node build-cover.mjs   # the alternative word arrangement
```

It needs no install: skia-canvas comes from the render sidecar's `node_modules`, and the
letters are set in `Spectral-Bold.ttf` from the icon brand folder.

## The position

`ГРАМОТНОСТЬ` opens through the centre square (its `Т` on H8) and the other three words hook
onto a shared letter. `assertLegal` re-reads the finished grid and fails the build if the
centre is uncovered, if a declared word is missing, or if any maximal run of two or more
letters is a word nobody played — so the board on the cover is always a position the engine
would accept. All four words are in the Эрудит dictionary; tile values come from
`scrabble-solver` `rules.Erudit()`.

The default `ladder` arrangement puts both long words horizontally. The `cross` arrangement
hangs `ЭРУДИЦИЯ` down the left instead, which looks more symmetric but collides with the VK
mobile avatar (below).

## VK keep-outs

Measured off VK's own template (`../VK_group_cover_template.fig`), in cover pixels:

| Zone | Area | Why |
|------|------|-----|
| Top crop | `y < 130` | trimmed by some clients — nothing important there |
| Mobile avatar | circle, centre `(283, 818)`, r `283` | the community picture sits over the bottom-left in the VK app |

`ZONES=1` paints both so a composition can be checked against them.

## Rendering technique

The camera has pitch only — no roll, no yaw — so a board-space horizontal line always maps to
a screen-space horizontal line. That makes the perspective warp an exact per-scanline remap of
a flat texture rather than a general homography: the board surface and the tile faces are each
drawn once, flat, at high resolution, then replayed band by band (`warpPlane`). Tile thickness
is filled as real 3D quads between the two planes, so the tiles have visible edges.

Two things that are easy to get wrong here and cost a hundredfold in render time:
`ctx.filter = 'blur(...)'` applies per drawing call, so many blurred shapes must be collected
into one offscreen layer and blurred once (`blurred`); and `drawImage` re-snapshots a live
`Canvas` source on every call, so a texture sampled hundreds of times must be baked into an
`Image` first (`freeze`).
