JSFiddle - React, Tailwind, and code Playground

HTML

<!doctype html>
<html lang="en">

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="color-scheme" content="dark">
    <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data:; connect-src 'none'; base-uri 'none'; form-action 'none'">
    <title>Bramble — a pixel forest & quadtree playground</title>
    <style>
    * {
      box-sizing: border-box;
    }

    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      overflow: hidden;
      background: #0c1020;
    }

    canvas {
      display: block;
      width: 100%;
      height: 100%;
      image-rendering: pixelated;
      image-rendering: crisp-edges;
      touch-action: none;
      outline: none;
    }
    </style>
  </head>

  <body>
    <canvas id="screen" tabindex="0" aria-label="Bramble forest. Move with WASD or arrow keys. Q toggles quadtrees, B collision bounds, G tiles, Tab all debug overlays, Space pause, N single step, brackets change the crowd, R reset, H help, F fullscreen. Click an actor to inspect it. On a touchscreen, drag to move."></canvas>
    <script>
    'use strict';
    /*
     * BRAMBLE / FOREST COLLISION LAB
     * One file. No dependencies, external fonts, images, audio, or requests.
     *
     * WORLD: 26 x 15 tiles, 16px each; logical framebuffer: 416 x 240.
     * ART: exactly 24 opaque colors; transparent sprite backgrounds. All raster
     * operations use integer rectangles or unfiltered, integer-aligned blits.
     * Sprites are built once: 8 facings x 4 frames, 24 x 32 each. Five authored
     * facings supply N/NE/E/SE/S, with pixel-exact mirrors for SW/W/NW.
     * Smooth sine-based gait parameters are sampled into four frames at startup;
     * locomotion advances those poses at 10 Hz while simulation runs at 60 Hz.
     *
    ...