diff --git a/PROJECT.md b/PROJECT.md
index 81f2801..3901042 100644
--- a/PROJECT.md
+++ b/PROJECT.md
@@ -3732,6 +3732,17 @@ scaled so the BODY matches the standing frame (98% of sprite height) and the rac
this on any new pose with a raised prop.
## Gotchas learned the hard way
+
+- **MODULE-LEVEL STATE CLOCKED OFF `G.idleT` MUST SURVIVE THE CLOCK GOING BACK TO ZERO.**
+ `resetState()` rewinds `G.idleT` for every new run; anything living in a module's own closure does
+ not rewind with it. The camera flashes had both halves of that bug at once (2026-08-21): a
+ `flashNext` inherited from the previous run meant NO photographs until the new run's clock climbed
+ past it, and any flash still in flight was left with a `t0` in its own future, which makes
+ `1 - (now - t0)/life` permanently greater than 1 — a shutter frozen at full brightness in the
+ stand for the rest of the session. Oliver: "at a random place in the crowd some frozen midflash
+ circle is visible. after a few points the flashes unfreeze." `tickFlashes` now clears and re-arms
+ whenever the clock moves backwards. **If you add anything else with a remembered `t0` or a "next
+ at" in render.js, give it the same guard** — the reset path will not do it for you.
- **Nothing outside the four slot accessors may know how many slots there are.** `endBurst` had
`[0, 1, 2, 3, 4].find(i => slotId(i) === id)`, which was correct for exactly as long as the rack
held five. `RACK_MAX` 4 → 9 and a burst weapon in slot 5..9 was suddenly unfindable, so it was
diff --git a/index.html b/index.html
index 165aa6c..56a8da3 100644
--- a/index.html
+++ b/index.html
@@ -664,6 +664,6 @@ if (location.hostname !== 'splatter-tennis.wuwi.one' && !window.Capacitor?.isNat
-
+