Default learning rate 0.02 -> 0.01 (200-step sweep on the real 16512 vocab: 0.02 gives 1.93 at 100 steps vs 1.01 for 0.01; they converge by 200 but short runs are what the demo is). Batch the per-head backward GEMMs: 4 batched dispatches per layer instead of 4 per head, GEMM calls 167 -> 47 per step, float backward ~14% faster. Adds test_unit_backward.js, the experiment showing int8 gradients do not damage convergence.
Exact kernel gates: verify variants emitted from the same WGSL source restore the int32 oracle on the kernels training actually runs; bit-exact epilogue mirror removes the tolerance entirely; shape sweep; dead exactly-gated kernel deleted. Continuous verification: random-cell audit at live shapes + canonical cross-device kernel probe (the weight hash structurally cannot detect kernel disagreement). New test_gates.js mutation-tests the gate itself.