createPack() resolves when the pack is registered, not when tiles are
done downloading. Wrapping in a Promise that resolves only on
status.state === 'complete' keeps the progress modal visible and the
'Download complete' alert fires only when the pack is actually ready.
Transient tile errors ('stream was reset: CANCEL') are silently ignored
in the error listener — MapLibre retries them internally and they do not
indicate a failed download. The onError callback is removed from the
public API since it was causing spurious alerts mid-download.
New src/services/offline.ts:
- downloadRegion(): createPack with bounds, zoom 6-16, progress callback
- listRegions() / deleteRegion(): pack management
- expandBounds(): adds 5km buffer around the visible area
- formatBytes(): human-readable size string
RecordingScreen:
- MapRef attached to Map component to read getBounds()
- '↓ Offline' overlay button (Liberty style + idle state only)
- Modal: name input → download → progress bar with % and MB counter
- Raster styles show no download button (not supported by OfflineManager)
Settings → App → Offline maps:
- Lists all downloaded regions with size and tile count
- Delete with confirm alert
- Placeholder text when no regions exist