Two follow-ups to the warm-pool patch:
* Semaphore 1 → 3. Playwright contexts are isolated, the captureToPool
site/port allocation is synchronous (no race), and concurrent user
clicks that all miss the pool no longer serialize behind a single
~5s capture. Peak memory grows from one context to three; each is
short-lived.
* Capture-time validation. After Playwright extracts the JWT, do one
cheap upstream call (/car/info with the public demo VIN) through the
same proxy port before pushing the slot to the pool. DataImpulse
occasionally rotates to IPs the partner widget can load but the
upstream API can't reach, or that get instantly 401/403'd; those
ports used to spend 30s timing out on the first real user click.
Failures rotate to the next site within the existing 4-retry budget.
Adds ~1s to each successful capture; saves up to 30s per dead slot.