Closes BLOCKER B5 — the offline map was blank for most real trips:
- The Workbox 'map-tiles' cache held only 1000 entries while the prefetcher
budgeted ~3413, so prefetched tiles were evicted on arrival. Both caps are
now a coherent 12288 (~180 MB), kept in sync with cross-referencing comments.
- prefetchTilesForTrip skipped a trip entirely when its all-zooms estimate
exceeded the cap, so region/road-trip bboxes got no tiles. Removed the
all-or-nothing guard; prefetchTiles already fills zooms low→high and stops at
the budget, so large trips now cache the zooms that fit instead of nothing.
Closes three offline BLOCKERs from the PWA audit:
- B1: offline edits/deletes of an offline-created entity were lost. The
negative temp id was baked into the PUT/DELETE url and never rewritten
after the CREATE returned a real id, so dependents 404'd and were dropped.
Dependents now carry a {id} placeholder + tempEntityId; flush builds a
tempId->realId map and durably rewrites still-queued dependents on CREATE
success (survives flush boundaries / reloads).
- B2: tempId = -(Date.now()) collided within a millisecond, overwriting an
optimistic row. Replaced with a monotonic nextTempId() minter.
- B3: any 4xx marked the mutation failed with no rollback and no signal, and
the badge ignored failed rows. Terminal failures now roll back the phantom
optimistic CREATE; 401/408/425/429 are treated as retryable; failedCount()
is surfaced in OfflineBanner (red pill) and OfflineTab.