export function haversineKm(lat1, lon1, lat2, lon2) { const R = 6371; const dLat = ((lat2 - lat1) * Math.PI) / 180; const dLon = ((lon2 - lon1) * Math.PI) / 180; const a = Math.sin(dLat / 2) ** 2 + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) ** 2; return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); } export function getUserPosition() { return new Promise((resolve, reject) => { if (!navigator.geolocation) { reject(new Error('Geolocalización no compatible con este navegador')); return; } if (typeof window !== 'undefined' && window.isSecureContext === false) { reject(new Error('La geolocalización requiere HTTPS (o localhost)')); return; } navigator.geolocation.getCurrentPosition( pos => resolve({ lat: pos.coords.latitude, lon: pos.coords.longitude }), err => { console.error('[geo] getCurrentPosition failed — code:', err && err.code, 'message:', err && err.message); reject(err); }, { timeout: 15000, maximumAge: 60000, enableHighAccuracy: false } ); }); } export function formatDistance(km) { if (km < 1) return `${Math.round(km * 1000)} m`; if (km < 10) return `${km.toFixed(1)} km`; return `${Math.round(km)} km`; }