PrimaryArmorSceneComponent rebuilt its ShaderMaterial every render with null uniforms that were only set once on mount. Create it once with useState instead.
Replace wordy swap prompt with compact icon row (spall liner icon,
swap icon, current provisions) and drop unused ProvisionButton
tooltip that flashed on popover open.
Adds a **Peekaboo DPM** entry nested under DPM for single-shot guns, estimating damage per minute when only firing after resetting camouflage (or waiting out the reload, whichever is slower), assuming at least 10 seconds between shots.
- Shots per minute are capped at `60/10` for reloads faster than 10s, and fall back to `60/reload` otherwise
- The result is multiplied by the currently selected shell's damage and rounded
- An (i) icon next to the label opens a popover explaining the calculation
- The row is hidden for auto-loader/auto-reloader guns
- No percentile ranking bar is shown, since no dataset exists yet for this new stat
The /session/ page crashed when a tracked player's tank stats included
a tank with no matching tank definition or no average stats (WN8
baseline). The delta memo dereferenced `tank.id` on a possibly missing
definition and forced `average?.mu!` through as non-null, so a missing
average threw inside `compositeStats`/`calculateWN8` uncaught, breaking
the page on every load while the bad state persisted in localStorage.
Skip those entries instead of crashing: entries with no tank
definition or no average `mu` are dropped from the delta via
`flatMap`, so the rest of the session table still renders.