Replace the broken-looking Leaflet/OSM address picker with a MapLibre GL
map using Map.ir vector tiles, plus Map.ir reverse geocoding for fast
coordinates -> Persian address.
- InteractiveMap: drop react-leaflet/leaflet; init a MapLibre map (Map.ir
style via transformRequest x-api-key), a NavigationControl, and a fixed
center pin — the map moves under the pin and the centre is reverse-
geocoded on moveend (debounced). Wrapped dir=ltr so the map renders
correctly inside the RTL page (fixes the scattered-tiles bug). Selected
address shown in an overlay chip; city select / geolocation fly the map.
- reverse geocoding: Nominatim -> Map.ir (https://map.ir/reverse), which
returns proper Persian addresses (Nominatim was weak for Iran and its
TOS forbids production use).
- default map centre fixed to Tehran (matched the "تهران" selector).
- key via VITE_MAPIR_KEY (documented in .env.example; real key in env).
- deps: add maplibre-gl, remove leaflet/react-leaflet/@types/leaflet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Most browsers (everything but Safari/WebKit) can't decode HEIC in <img> or
canvas, so picking an iPhone HEIC photo broke the preview and the crop editor,
and could reach the backend in a format it couldn't process. Convert HEIC/HEIF
to JPEG right after selection via heic2any (dynamically imported, browser-only).
- new util app/utils/convert-heic.ts: isHeic() detection (MIME or extension
when iOS reports no type) + convertHeicToJpeg()/convertHeicFiles(); never
throws — falls back to the original file on failure.
- wired into the product image picker (store.add.manual) and the store
logo picker (StoreForm).
- adds heic2any dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>