# Leaflet Map Integration for PWA Draft Games

## When to add a map view

When a fantasy game's draft room needs to show geographic regions, a map view is more intuitive than a card grid. Use Leaflet.js + OpenStreetMap tiles for free, no-API-key map rendering.

## CDN

```html
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
```

## Implementation pattern

1. **Map container:** Single `<div id="leafletMap">` in the HTML
2. **On view switch:** Destroy old instance (`window._leafletMap.remove()`), create new `L.map()` centered on `[20, 0]` with zoom 2, minZoom 2, maxZoom 5
3. **Tiles:** `L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')`
4. **Markers:** `L.circleMarker([lat, lng], {radius, color, fillColor, fillOpacity})` for each region
5. **Popups:** `marker.bindPopup(content)` with region stats, name, and action button
6. **Color coding:** Available=teal/#0ea5e9, Your pick=amber/#f59e0b, Taken=red/#dc2626, Waiting=gray
7. **Toggle view:** Map | List toggle button that calls `renderMapView()` or shows card grid

## Pitfalls

- **Destroy before recreating:** Always remove the previous Leaflet instance (`window._leafletMap.remove()`) before initializing a new one. Multiple instances on the same div cause visual glitches.
- **Coordinate format:** Leaflet uses `[lat, lng]` in that order (not `[lng, lat]` like GeoJSON).
- **Dark theme:** Override `leaflet-container`, `.leaflet-popup-content-wrapper`, and `.leaflet-control-zoom` CSS to match dark theme.
- **Popup content:** Leaflet's `bindPopup()` accepts raw HTML — use it for region stats, action buttons, etc. Don't use custom overlay modals for map popups.
- **Mobile responsiveness:** Leaflet handles viewport resizing automatically, but set `height: 500px` on the container and wrap in a responsive parent.
- **Prevent scrolling off-world:** Without bounds locking, users can pan left/right until all markers disappear. Fix with:
  ```javascript
  const map = L.map('leafletMap', {
    maxBounds: [[-60, -180], [80, 180]],
    maxBoundsViscosity: 0.8,  // 0 = hard wall, 1 = bounce
  });
  ```
  Viscosity of 0.8 lets it feel natural (not a hard wall) while keeping markers in view.
