Three coordinating mutables move into `src/store/gaplessPreloadState.ts`
behind a thin API:
- `gaplessPreloadingId` / `bytePreloadingId` — guards so the runtime
doesn't fire a chain-/byte-preload twice for the same id
- `lastGaplessSwitchTime` — timestamp used by the 500–600 ms
ghost-IPC suppression guards in `handleAudioEnded` and `playTrack`
Public API: `get…` / `set…` accessors plus `clearPreloadingIds`
(atomic clear of both guards — collapses three `= null; = null;`
duplications) and `markGaplessSwitch` (`Date.now()` stamp). The
mutables are no longer reachable from outside the module.
13 focused tests pin the get/set round-trips, independence between
the two guards, the atomic clear, and the timestamp progression.
playerStore 3208 → 3207 LOC (small delta because the `= null; = null;`
inlines compress to single `clearPreloadingIds()` calls but the
module itself adds the accessor functions to the import list).