// Viewport counts
function updateViewportCounts() {
var b = map.getBounds();
var c = {portal:0,hospital:0,clinic:0,pharmacy:0,dialysis:0,sud:0};
PORTAL_FACS.forEach(function(f){
if(f.latitude&&f.longitude&&b.contains([parseFloat(f.latitude),parseFloat(f.longitude)])) c.portal++;
});
EXT_FACS.forEach(function(f){
if(!f.latitude||!f.longitude||!b.contains([parseFloat(f.latitude),parseFloat(f.longitude)])) return;
var t=(f.facility_type||'').toLowerCase();
if(t.indexOf('hospital')>=0) c.hospital++;
else if(t.indexOf('pharmacy')>=0) c.pharmacy++;
else if(t.indexOf('dialysis')>=0) c.dialysis++;
else if(t.indexOf('sud')>=0||t.indexOf('substance')>=0||t.indexOf('treatment center')>=0) c.sud++;
else c.clinic++;
});
var tot=c.portal+c.hospital+c.clinic+c.pharmacy+c.dialysis+c.sud;
['portal','hospital','clinic','pharmacy','dialysis'].forEach(function(k){
var el=document.getElementById('vp-'+k); if(el) el.textContent=c[k]||' ';
});
var te=document.getElementById('vp-total'); if(te) te.textContent=tot||' ';
}
map.on('moveend zoomend',updateViewportCounts);
setTimeout(updateViewportCounts,2000);
// Near Me
var nmMarker=null,radiusCircle=null,radiusMi=10,nmCenter=null;
var RADIUS_OPTS=[5,10,25,50]; var rIdx=1;
function drawRadius(){
if(!nmCenter) return;
if(radiusCircle) map.removeLayer(radiusCircle);
radiusCircle=L.circle(nmCenter,{radius:radiusMi*1609.34,color:'#4B2E83',
fillColor:'#4B2E83',fillOpacity:0.06,weight:2,dashArray:'6,4'}).addTo(map);
}
document.getElementById('near-me-btn').addEventListener('click',function(){
if(!navigator.geolocation){alert('Geolocation not supported.');return;}
var btn=this; btn.disabled=true;
btn.innerHTML='Locating...';
navigator.geolocation.getCurrentPosition(function(p){
nmCenter=[p.coords.latitude,p.coords.longitude];
map.setView(nmCenter,13);
if(nmMarker) map.removeLayer(nmMarker);
nmMarker=L.marker(nmCenter,{icon:L.divIcon({className:'',
html:'',
iconSize:[18,18],iconAnchor:[9,9]})}).addTo(map)
.bindPopup('Your location').openPopup();
drawRadius();
document.getElementById('radius-btn').classList.remove('d-none');
btn.innerHTML='Near Me'; btn.disabled=false;
updateViewportCounts();
},function(e){alert('Location error: '+e.message);
btn.innerHTML='Near Me'; btn.disabled=false;
},{timeout:10000});
});
document.getElementById('radius-btn').addEventListener('click',function(){
rIdx=(rIdx+1)%RADIUS_OPTS.length; radiusMi=RADIUS_OPTS[rIdx];
document.getElementById('radius-label').textContent=radiusMi+' mi';
drawRadius();
});
// Fullscreen
document.getElementById('fullscreen-btn').addEventListener('click',function(){
var el=document.getElementById('map');
if(!document.fullscreenElement){
(el.requestFullscreen||el.webkitRequestFullscreen||el.mozRequestFullScreen).call(el);
this.innerHTML='';
} else {
(document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen).call(document);
this.innerHTML='';
}
});
document.addEventListener('fullscreenchange',function(){
if(!document.fullscreenElement){
var b=document.getElementById('fullscreen-btn');
if(b) b.innerHTML='';
setTimeout(function(){map.invalidateSize();},200);
}
});
// Spin CSS
(function(){var s=document.createElement('style');
s.textContent='@keyframes spin{to{transform:rotate(360deg)}}.spin{display:inline-block;animation:spin .8s linear infinite;}';
document.head.appendChild(s);})();
⚠️ You are offline. Recently viewed pages are available. Submissions will sync when you reconnect.
💾 Items waiting to syncWill upload automatically when online
📲
Add the Hub to your home screen for offline access iPhone: Safari → Share → Add to Home Screen •
Android: Chrome menu → Add to Home Screen •
Desktop: Click ⊕ in your address bar.
Works offline — submitted forms sync automatically when you reconnect.