SIGN IN SIGN UP

Fix rate-limit failures: throttle fetches, bail out on blocked pages

Root cause of "listings with my profile picture and 0/empty fields":
both bookmarklets fired every product-page fetch simultaneously via
Promise.all, with no throttling at all. That's a much bigger burst
than manual browsing - I hit Vinted's own rate limiter myself during
testing after just a handful of sequential page loads, so a real
user's larger closet firing a dozen-plus concurrent requests is very
likely to trip it. When rate-limited, the fetched page is Vinted's
block page, not the real listing: no Product ld+json, but the shared
site header (with the user's own avatar) still renders - which
explains exactly what was reported.

Two fixes:
- Replaced Promise.all with a sequential fetch loop (250ms gap between
  requests) in both bookmarklets, so a large shop/closet no longer
  fires a burst of near-simultaneous requests.
- Made both extractors return null (not a zeroed-out fake listing)
  when the expected data isn't present - Vinted's when there's no
  ld+json Product block, Depop's when there's no price AND no
  description. Previously these silently produced garbage listings
  with $0 and blank everything instead of just being dropped.
- If more than half the requests come back empty, the bookmarklet now
  tells the user why (likely rate-limited) instead of silently
  showing a partial/broken result.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
I
Ian Lee committed
28f8d02571276f37eb4f08220f37a09abbba3b09
Parent: f5bc531