> Idea: A paintable Conway's Game of Life: click and drag to draw live cells on a grid, play/pause/step, adjust speed and cell size, randomize, clear, and drop in classic patterns (glider, pulsar, glider gun). Show the generation count and population.

Build a single-page, dependency-free web application called **LifeCanvas**: a paintable, interactive implementation of Conway's Game of Life rendered on an HTML5 canvas. The entire app must ship as static files with no build step, no bundler, and no external network requests of any kind. A user opens `index.html` and immediately has a polished, dark-themed cellular-automaton studio they can paint on with the mouse or finger, run as a simulation, scrub speed and zoom, seed with classic patterns, and watch live statistics update in real time.

Address every instruction below to yourself as the implementing agent. Make every reasonable assumption rather than leaving anything underspecified; where this brief names a concrete number, color, or behavior, implement exactly that. Do not stub, do not leave TODOs, do not ship placeholders. The result must run perfectly on first load with zero console errors or warnings.

## Goal

Deliver a genuinely impressive, tactile Conway's Game of Life simulator that feels like a small creative tool rather than a textbook demo. The experience centers on a large canvas grid the user can **paint** on: clicking and dragging toggles or paints live cells with the responsiveness of a drawing app. Around that canvas sits a clean, dark control surface with transport controls (play, pause, step), a speed slider, a cell-size (zoom) slider, randomize, clear, and a library of classic Life patterns the user can stamp onto the grid (glider, lightweight spaceship, pulsar, Gosper glider gun, and more). A persistent statistics strip shows the current **generation count** and **population** (number of live cells), updating every tick.

The simulation must be **correct** — it implements Conway's B3/S23 rules exactly — and **performant**: a grid of tens of thousands of cells must run smoothly at high speed without jank. The visual design must be cohesive, modern, and dark, with thoughtful microinteractions, accessible contrast, and a layout that is responsive from a 320px-wide phone up to a wide desktop monitor.

Concrete success feels like: open the page, see a softly glowing dark grid, drag the mouse to sketch a shape, hit Play, watch it evolve with a smooth pulse, drop a Gosper glider gun in a corner and watch it spit gliders forever, slide the speed up to a blur and back down, zoom the cells larger to inspect a pulsar breathing, and read the generation/population counters ticking the whole time — all with no lag and no errors.

## Tech stack

- **Pure static front end. No build step, no framework, no package manager.** Three files only: `index.html`, `main.js`, and `styles.css`.
- **Vanilla JavaScript (ES2020+), no libraries.** No React, Vue, Svelte, Alpine, htmx, jQuery, lodash, or any CDN script. Hand-write everything. The simulation engine, renderer, input handling, and UI wiring are all your own vanilla code.
- **Rendering via the Canvas 2D API.** Use a single `<canvas>` element for the grid. Do not render cells as DOM nodes — DOM-per-cell will not scale. All cell drawing, gridlines, and overlays happen on the canvas.
- **HTML5 + CSS3 only for chrome.** Controls are real HTML form elements (`<button>`, `<input type="range">`, `<select>`) styled with CSS. Layout uses CSS Grid and Flexbox. Use CSS custom properties (variables) for the entire color and spacing system.
- **System font stack only** — no web fonts, no `@import`, no Google Fonts. Use: `font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;` for UI text and `ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;` for numeric/statistic readouts.
- **No inline JavaScript and no inline event handlers.** This is a hard constraint: the app is served under a strict Content-Security-Policy that forbids inline scripts. There must be **zero** `<script>` blocks with inline code, **zero** `onclick=`/`onchange=`/`onload=`/`oninput=` attributes, and **zero** `javascript:` URLs. All JavaScript lives in `main.js`, loaded with `<script src="./main.js" defer></script>`. All event wiring is done via `addEventListener` in `main.js`. Do not use `eval`, `new Function`, or `setTimeout`/`setInterval` with a string argument.
- **No external resources whatsoever.** No external images, fonts, stylesheets, analytics, or telemetry. No `fetch`, `XMLHttpRequest`, `WebSocket`, or `navigator.sendBeacon` to any origin. Any imagery must be drawn on the canvas or expressed as inline SVG / CSS / data URIs. The app must be fully functional offline, opened directly from the filesystem.
- **Relative asset paths only** (`./main.js`, `./styles.css`) so the app works whether served from a domain root, a subpath, or a subdomain.
- Persist UI preferences (speed, cell size, theme accent, wrap toggle, show-grid toggle) to `localStorage` under a single namespaced key (e.g. `lifecanvas.settings.v1`), wrapped in try/catch so a disabled/again-throwing storage API never breaks the app.

## File layout

```
lifecanvas/
├── index.html      # Semantic markup: header, canvas stage, control panels, stats, footer.
│                   # Links ./styles.css in <head> and ./main.js via <script defer> at end of body.
│                   # NO inline <script>, NO inline event handlers, NO inline styles beyond trivial layout hooks.
├── main.js         # ALL logic: Life engine, canvas renderer, input/painting, transport loop,
│                   # pattern library + stamping, controls wiring, stats, persistence, resize handling.
└── styles.css      # ALL presentation: dark theme tokens, layout grid, control styling,
                    # slider/button/select theming, responsive breakpoints, motion, focus states.
```

Keep `main.js` organized into clear, commented logical sections even though it is one file. Suggested internal structure (use comment banners, not separate files):

1. **Config & constants** — default grid dimensions, default cell size, speed range, color tokens read from CSS variables, the rule set, the pattern catalog.
2. **State** — a central `state` object: the cell grid (typed array), columns, rows, cellSize, running flag, speed (generations/sec), generation counter, population, current tool (paint/erase), wrap mode, showGrid flag, pointer state, the requestAnimationFrame handle, and last-tick timestamp.
3. **Life engine** — grid allocation, neighbor counting (with both toroidal-wrap and bounded modes), the `step()` function that computes the next generation into a back buffer and swaps, population recomputation.
4. **Renderer** — `render()` that paints the canvas: background, optional gridlines, live cells (with the chosen accent + subtle glow), and any hover/brush preview. Must respect `devicePixelRatio` for crisp rendering on HiDPI screens.
5. **Input / painting** — pointer event handlers (pointerdown/move/up, plus touch-action handling) that map screen coordinates to grid cells and paint or erase, including drag interpolation so fast drags don't leave gaps.
6. **Transport loop** — a `requestAnimationFrame` driver that advances the simulation at the configured generations-per-second independent of frame rate, accumulating elapsed time.
7. **Pattern library & stamping** — the catalog of named patterns as coordinate arrays, plus a "stamp at next click" / "stamp at center" mechanism with rotation.
8. **Controls wiring** — `addEventListener` calls binding every button, slider, select, and keyboard shortcut to engine actions; live label updates.
9. **Persistence** — load/save settings to `localStorage`.
10. **Bootstrap** — read settings, size the canvas to its container, build the grid, wire everything, do the first render, and (optionally) seed a small welcome pattern so the canvas is never blank on first open.

## Behavior

Implement the full Conway's Game of Life rule set and all interactions below. Be exact.

### The simulation rules (B3/S23)

For each cell, count its 8 neighbors (Moore neighborhood). Apply standard Conway rules:

- A **live** cell with **2 or 3** live neighbors survives to the next generation; otherwise it dies (underpopulation if <2, overpopulation if >3).
- A **dead** cell with **exactly 3** live neighbors becomes alive (reproduction).
- All cells update **simultaneously** based on the previous generation — never mutate the grid in place while counting. Compute the entire next generation into a second buffer, then swap buffers.

Provide a **wrap (toroidal) mode toggle**: when ON, the grid edges wrap so neighbors at the left edge include the right edge and top includes bottom (a torus); when OFF, out-of-bounds neighbors count as dead (bounded universe). Default: wrap ON. Recompute neighbor lookups accordingly without branching inside the hottest inner loop more than necessary — precompute edge handling or use modular arithmetic carefully for speed.

### Grid & cell-size (zoom)

- The grid's logical size in columns × rows is derived from the canvas pixel size divided by the current **cell size**. The cell size is user-controlled via a slider, ranging **4px to 32px**, default **12px**. Changing cell size re-derives columns/rows.
- When cell size changes, **preserve the existing pattern as faithfully as possible**: keep the same top-left origin and copy over live cells that still fall within the new bounds (do not wipe the board on zoom). If the new grid is smaller, cells outside the new bounds are dropped; if larger, new area is empty.
- The canvas fills its responsive stage container. On window resize, recompute columns/rows for the current cell size and re-fit, preserving live cells where they still land.
- Account for `devicePixelRatio`: set the canvas backing-store resolution to `cssPixels * dpr` and scale the 2D context so 1 logical unit = 1 CSS pixel. Cells and gridlines must look crisp, not blurry, on Retina/HiDPI displays.

### Painting (the headline feature)

- **Click to toggle** a single cell's state. **Click-and-drag to paint** a stroke of live cells. This must feel like a brush: as the pointer moves, every cell under the path turns live (in paint mode) regardless of frame timing — interpolate between successive pointer positions (Bresenham-style line fill or sampled steps) so a fast diagonal drag produces a continuous line, never a dotted one.
- The **tool/mode** is determined at stroke start: if you press down on a **dead** cell, the whole drag **paints live** cells; if you press down on a **live** cell, the whole drag **erases** (sets dead). This "draw vs. erase based on the first cell" behavior is the expected, intuitive model — implement it. (Optionally also support holding a modifier or a right-click drag to force-erase, but the first-cell rule is required.)
- Painting works **while the simulation is paused and while it is running**. If running, newly painted cells take effect on the next tick.
- Show a subtle **hover preview**: when the pointer is over the grid and not actively painting, lightly highlight the cell under the cursor (a faint outline or fill at reduced opacity) so the user sees exactly which cell they'll affect. Remove the preview when the pointer leaves the canvas.
- Support **touch and pen** via Pointer Events. Set `touch-action: none` on the canvas so dragging paints instead of scrolling the page on mobile. A single-finger drag paints; do not require multi-touch.
- Painting must update the **population** counter live as cells are added/removed.

### Transport: play / pause / step

- **Play/Pause** is a single toggle control (and the Spacebar shortcut). When playing, the simulation advances at the configured speed; the button label/icon reflects state (▶ Play / ⏸ Pause) and has a clear active style.
- **Step** advances exactly **one generation** and leaves the simulation paused. Pressing Step while playing first pauses, then steps. Keyboard shortcut: the period/right-arrow key advances one step.
- The transport loop uses `requestAnimationFrame`. Advance generations based on **elapsed wall-clock time** and the target **generations-per-second**, accumulating a time debt so the simulation rate is stable regardless of display refresh rate. Cap the maximum catch-up per frame (e.g. no more than a few generations per frame) so a backgrounded tab returning to focus doesn't fast-forward thousands of generations or freeze.

### Speed control

- A **speed slider** controls generations per second, ranging from **1 gen/sec to 60 gen/sec**, default **12 gen/sec**, plus a special max position labeled "Max" that runs as fast as the frame budget allows (advance once per animation frame). Display the current speed next to the slider (e.g. "12 gen/s").
- Changing speed while running must take effect immediately and smoothly (no reset of the generation counter).

### Randomize, Clear, and density

- **Randomize** fills the grid with live cells at a configurable **density** (default ~22%). Provide a small density control (a secondary slider or a sensible fixed default with a couple of preset buttons like Sparse / Normal / Dense). Randomizing resets the generation counter to 0 and recomputes population.
- **Clear** empties the entire grid, sets population to 0, and resets the generation counter to 0. If the simulation is running, Clear pauses it. Because Clear is destructive, it is acceptable to make it instant (no modal), but the button should be visually distinct (a muted/danger accent) to avoid accidental misclicks.

### Classic pattern library (stamping)

Provide a curated catalog of well-known Life patterns the user can drop onto the grid. Expose them via a labeled **pattern picker** (a `<select>` dropdown and/or a row of buttons). At minimum include, with correct cell coordinates:

- **Still lifes**: Block, Beehive, Loaf.
- **Oscillators**: Blinker (period 2), Toad (period 2), Beacon (period 2), **Pulsar** (period 3), Pentadecathlon (period 15).
- **Spaceships**: **Glider**, Lightweight spaceship (LWSS).
- **Guns**: **Gosper glider gun** (the classic 36-wide pattern that emits a glider every 30 generations).
- **Methuselahs**: R-pentomino, Acorn (small seeds that evolve for a long time — great demos).

Stamping behavior:

- Selecting a pattern arms a **"place mode"**: the next click on the grid stamps the pattern with its bounding-box centered (or anchored top-left) at the clicked cell, and shows a live **ghost preview** of the pattern under the cursor before placing so the user can position it precisely. Provide a quick **"Stamp at center"** action too (button or pressing Enter) that places the armed pattern in the middle of the visible grid.
- Provide **rotate** (R key, or a rotate button) to rotate the armed pattern 90° before placing — recompute the coordinate set for the rotation.
- Stamping **adds** the pattern's live cells to the grid (OR onto existing cells; do not clear the board). If part of the pattern would fall outside the grid, clip it gracefully (don't error). Stamping does not reset the generation counter (the user may be composing a scene) — but provide a clear/stamp-fresh path via the Clear button if they want a blank canvas first. For the big demos (Gosper gun), ensure the grid is large enough or auto-suggest zooming out; never throw if it doesn't fit — clip.
- After stamping, exit place mode (one stamp per arm) unless the user holds a "keep placing" modifier; the simplest correct behavior — disarm after one placement — is acceptable and expected.

### Statistics readout

- A persistent stats strip shows at all times: **Generation** (integer, increments each tick, resets on Clear/Randomize/Reset), **Population** (count of live cells, updates every tick and on every paint/stamp/clear), and the grid dimensions (e.g. "120 × 80"). Use the monospace font for these numbers and format with thousands separators (e.g. `1,248`).
- Optionally also show **generations/second actual** (a smoothed FPS-of-simulation readout) so users see real throughput at "Max" speed. Keep it subtle.
- Numbers must animate/update without layout shift — reserve width or use tabular figures so the strip doesn't jitter as digits change.

### Keyboard shortcuts

Wire these via `addEventListener('keydown', …)` (ignore when focus is in a text input, though this app has none by default):

- **Space** — toggle play/pause.
- **S** or **.** (period) or **→** — single step.
- **R** — randomize (or rotate the armed pattern if in place mode — disambiguate: if a pattern is armed, R rotates; otherwise R randomizes; document this in a help tooltip).
- **C** — clear.
- **G** — toggle gridlines.
- **W** — toggle wrap mode.
- **+ / -** — increase / decrease cell size (zoom).
- **1–9** — quick-select the first nine patterns into place mode.
- **?** — open/close a small keyboard-shortcuts help panel.

Provide an unobtrusive on-screen hint (an info "?" button) that reveals the shortcut list so the controls are discoverable.

### First-load experience

On first open (no saved state), seed the canvas with something alive and inviting — for example, stamp a Gosper glider gun in the upper-left **or** a small field of a few gliders, and leave the simulation **paused** so the user sees structure without motion until they hit Play. Never show a completely empty black void on first load. The generation counter starts at 0.

## UX & visual design

Deliver a cohesive, modern **dark** aesthetic with the tactile feel of a creative tool. Mobile-first and fully responsive.

### Color system (define as CSS custom properties)

Use a deep, slightly blue-black canvas with a single luminous accent for live cells. Exact tokens:

- `--bg`: `#0a0c10` (app background, near-black with a cool tint).
- `--surface`: `#121620` (control panel surfaces).
- `--surface-2`: `#1a2030` (raised elements, slider tracks).
- `--border`: `#232b3a` (hairline separators, 1px).
- `--text`: `#e6ebf2` (primary text).
- `--text-dim`: `#8a95a8` (secondary text, labels).
- `--accent`: `#34e6b0` (signature mint/teal — used for live cells and primary actions).
- `--accent-2`: `#5cc8ff` (cool cyan, secondary highlight / hover).
- `--danger`: `#ff5d6c` (Clear button accent).
- `--cell`: live-cell fill, default `var(--accent)`; allow the user to pick from a small swatch set (mint, cyan, amber `#ffc857`, magenta `#ff6ec7`, white `#f5f7fb`) via accent swatches — persisted to localStorage.
- `--grid-line`: `rgba(255,255,255,0.045)` (very faint gridlines so they read as texture, not noise).

Live cells should have a subtle **glow**: draw the cell fill, then a soft outer bloom using either a radial gradient or a low-alpha larger rect / shadow, so a dense colony looks luminous against the dark grid. Keep the glow cheap — do not use `ctx.shadowBlur` per-cell in the hot path on large grids (it's slow); instead bake a soft look via a cached offscreen "cell sprite" or a single low-alpha overlay pass. Performance first.

### Typography & spacing

- System font stack (defined above). UI text base size 14–15px; stat numbers 18–22px in monospace with `font-variant-numeric: tabular-nums`.
- Spacing scale (CSS variables): 4, 8, 12, 16, 24, 32px. Use it consistently for padding, gaps, and margins.
- Corner radius scale: 6px for controls, 10–12px for panels. Hairline 1px borders using `--border`.

### Layout

- **Header bar** (top): app wordmark "LifeCanvas" with a tiny animated glyph (a 3×3 blinker or glider drawn in CSS/SVG/canvas), and on the right the stats strip (Generation, Population, dimensions). On narrow screens the stats wrap below the wordmark.
- **Stage** (center, dominant): the canvas, filling available space, with a subtle inset border/`box-shadow` and rounded corners. The canvas background is `--bg` with faint gridlines. This is the hero.
- **Control panel**: a toolbar that sits **below** the canvas on narrow screens and may dock to a **left/right rail** on wide screens (use a responsive CSS Grid: single column < 860px, two-column canvas+rail ≥ 860px). The control panel groups: Transport (Play/Pause, Step), Speed slider, Cell-size slider, Density + Randomize, Clear, Pattern picker + Rotate + Stamp-at-center, and toggles (Grid, Wrap, accent swatches).
- **Footer**: a small, tasteful line with the required attribution link.

### Controls styling & microinteractions

- **Buttons**: dark surface, 1px border, 6px radius; hover lifts to `--surface-2` with an `--accent`-tinted border and a 120ms ease transition; active/pressed slightly inset. The primary Play button uses an `--accent` fill with dark text and a soft glow; the Clear button uses a `--danger`-tinted border that fills on hover. Every interactive control has a visible `:focus-visible` ring (2px `--accent-2` outline, offset) for keyboard accessibility.
- **Sliders** (`input[type=range]`): fully custom-styled for WebKit and Firefox — slim `--surface-2` track, an `--accent` filled portion if feasible, and a round thumb with a subtle glow that scales up slightly on hover/active. Show the live value beside each slider.
- **Select / pattern picker**: dark-styled dropdown; when a pattern is armed, the picker shows an active accent state and the canvas shows the ghost preview.
- **Toggles** (Grid, Wrap): pill switches that slide and color-fill to `--accent` when on, with a 150ms transition.
- **Toasts / hints**: when the user performs a notable action (stamped a pattern, randomized, cleared), show a brief, quiet toast in the corner ("Stamped: Gosper glider gun") that fades after ~1.6s. Keep it understated.
- **Motion**: keep transitions in the 120–180ms range with ease-out; the simulation itself provides the motion, so chrome animations stay restrained. Respect `prefers-reduced-motion: reduce` by disabling non-essential transitions/toasts.

### Canvas interaction polish

- Cursor: `crosshair` over the canvas to signal "paintable".
- Hover preview cell as described. Brush feels 1:1 — the cell under the pointer is always the one that changes.
- When zoomed in (large cell size), gridlines become more prominent automatically; when zoomed far out (tiny cells, e.g. ≤6px), suppress gridlines for clarity. Toggleable via the Grid switch regardless.
- The whole stage must never produce horizontal page scroll; the canvas resizes to fit.

### Accessibility

- Sufficient contrast for all text against its surface (meet WCAG AA for body text).
- All controls are real, focusable, keyboard-operable elements with descriptive `aria-label`s where the visible label is an icon only (e.g. Play, Step, Rotate).
- The play/pause button reflects state with `aria-pressed`. Sliders expose `aria-valuetext` with human labels (e.g. "12 generations per second").
- Provide a visually-hidden but screen-reader-available live region announcing major state changes (e.g. "Simulation playing", "Cleared", "Randomized") via `aria-live="polite"`. Do not announce every generation tick (too noisy).
- Honor `prefers-reduced-motion`.

### Required footer attribution

Include a small, tasteful footer with the exact text **"Built with a one-shot prompt from 1ShotGen"** linking to `https://1shotgen.com` (open in a new tab with `rel="noopener noreferrer"`). Style it muted (`--text-dim`) with an `--accent` hover. It must be present and unobtrusive.

## Definition of done

The build is complete only when **all** of the following are true:

- [ ] The app is three files — `index.html`, `main.js`, `styles.css` — with no build step, no framework, and no external/CDN resources of any kind.
- [ ] `index.html` links `./styles.css` and loads `./main.js` via `<script src="./main.js" defer></script>`. There are **no** inline `<script>` blocks, **no** inline event-handler attributes (`onclick`, `oninput`, `onload`, etc.), and **no** `javascript:` URLs. All paths are relative.
- [ ] All event handling is wired with `addEventListener` in `main.js`. No `eval`, `new Function`, or string-argument timers. The app loads and runs with **zero console errors or warnings** and is fully functional opened directly from the filesystem and under a strict CSP that forbids inline scripts.
- [ ] Conway's B3/S23 rules are implemented correctly with simultaneous double-buffered updates. A glider travels diagonally without distortion; a blinker oscillates with period 2; a pulsar with period 3; a Gosper glider gun emits a glider every 30 generations indefinitely.
- [ ] Wrap (toroidal) mode and bounded mode are both implemented and toggleable, and produce correct edge behavior in each mode.
- [ ] Click toggles a single cell; click-and-drag paints a continuous (gap-free) stroke via interpolation; the draw-vs-erase mode is decided by the first cell of the stroke. Painting works while paused and while running, on mouse, touch, and pen. A hover preview highlights the target cell.
- [ ] Play/Pause toggles correctly (button + Spacebar); Step advances exactly one generation and pauses; the simulation rate matches the speed slider in real wall-clock terms, frame-rate-independent, with catch-up capped to avoid post-background fast-forward.
- [ ] Speed slider ranges 1–60 gen/s plus a "Max" mode, defaults to 12, updates live, and shows its value.
- [ ] Cell-size slider ranges 4–32px, defaults to 12, re-derives the grid, preserves existing live cells across zoom and window resize, and renders crisply on HiDPI via `devicePixelRatio` handling.
- [ ] Randomize fills at an adjustable density (default ~22%) and resets the generation counter; Clear empties the grid, zeroes population and generation, pauses if running, and is visually distinct as a destructive action.
- [ ] The pattern library includes at least: Block, Beehive, Loaf, Blinker, Toad, Beacon, Pulsar, Pentadecathlon, Glider, LWSS, Gosper glider gun, R-pentomino, and Acorn — each with correct coordinates. Selecting one arms place mode with a ghost preview; clicking stamps it (clipped if it overflows, never throwing); Rotate (R / button) rotates before placing; Stamp-at-center works.
- [ ] The stats strip always shows Generation and Population (live, comma-formatted, tabular figures, no layout shift) plus grid dimensions; counters are accurate after every tick, paint, stamp, randomize, and clear.
- [ ] Keyboard shortcuts work: Space (play/pause), S/./→ (step), R (randomize or rotate when armed), C (clear), G (gridlines), W (wrap), +/- (zoom), 1–9 (quick pattern select), ? (help). A discoverable help panel lists them.
- [ ] The visual design matches the dark token system (exact hex values above), with the signature mint accent and a cheap, performant glow on live cells. Custom-styled buttons, sliders, selects, and pill toggles all have hover, active, and `:focus-visible` states.
- [ ] Layout is responsive: single-column on phones (≥320px wide, no horizontal scroll), canvas + control rail on wide screens (≥860px). The canvas is the visual hero with rounded corners and a subtle inset shadow.
- [ ] Accessibility: real focusable controls, `aria-label`s on icon buttons, `aria-pressed` on play/pause, an `aria-live` polite region for major state changes, AA-contrast text, and `prefers-reduced-motion` honored.
- [ ] UI preferences (speed, cell size, accent, wrap, grid, density) persist to `localStorage` under a versioned key, wrapped in try/catch so storage failures never break the app.
- [ ] First load is never an empty void: a welcome pattern (e.g. Gosper gun or a few gliders) is seeded with the simulation paused, generation at 0.
- [ ] Performance: a large grid (e.g. ~150×100 = 15,000 cells, and gracefully more) runs smoothly at high speed with no visible jank; the render hot path avoids per-cell `shadowBlur` and unnecessary allocations; `step()` reuses buffers rather than allocating each generation.
- [ ] The footer shows exactly "Built with a one-shot prompt from 1ShotGen" linking to `https://1shotgen.com` with `rel="noopener noreferrer"`, styled muted with an accent hover.
- [ ] Final pass: open the app, paint a shape, run it, stamp a glider gun, scrub speed and zoom, randomize, clear, toggle wrap and grid, exercise every keyboard shortcut, and confirm zero console errors, no broken UI, no placeholders, and a polished, impressive result on first load.
