(function(){
  const qs=(s,c=document)=>c.querySelector(s), qsa=(s,c=document)=>Array.from(c.querySelectorAll(s));
  const debounce=(fn,ms=450)=>{let t;return(...a)=>{clearTimeout(t);t=setTimeout(()=>fn(...a),ms)}};
  const haversine=(a,b)=>{const R=6371,toRad=x=>x*Math.PI/180,dLat=toRad(b.lat-a.lat),dLon=toRad(b.lng-a.lng);const v=Math.sin(dLat/2)**2+Math.cos(toRad(a.lat))*Math.cos(toRad(b.lat))*Math.sin(dLon/2)**2;return R*2*Math.atan2(Math.sqrt(v),Math.sqrt(1-v));};
  const getLocation=()=>new Promise((resolve,reject)=>navigator.geolocation?navigator.geolocation.getCurrentPosition(p=>resolve({lat:p.coords.latitude,lng:p.coords.longitude}),reject,{enableHighAccuracy:true,timeout:12000,maximumAge:60000}):reject(new Error('Geolocalização indisponível')));
  async function reverse(lat,lng){const r=await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}&accept-language=pt-BR`,{headers:{Accept:'application/json'}});if(!r.ok)throw new Error('Não foi possível localizar o endereço');const j=await r.json();return j.display_name||`${lat}, ${lng}`;}
  async function searchAddress(q){if(q.length<4)return[];const r=await fetch(`https://nominatim.openstreetmap.org/search?format=jsonv2&limit=6&countrycodes=br&accept-language=pt-BR&q=${encodeURIComponent(q)}`,{headers:{Accept:'application/json'}});if(!r.ok)return[];return r.json();}
  async function route(a,b){try{const r=await fetch(`https://router.project-osrm.org/route/v1/driving/${a.lng},${a.lat};${b.lng},${b.lat}?overview=false`);const j=await r.json();if(j.routes&&j.routes[0])return{distance:j.routes[0].distance/1000,duration:Math.round(j.routes[0].duration/60)};}catch(e){}const d=haversine(a,b)*1.25;return{distance:d,duration:Math.max(1,Math.round(d/30*60))};}

  qsa('[data-address-autocomplete]').forEach(input=>{
    if(input.dataset.autocompleteReady==='1')return;input.dataset.autocompleteReady='1';
    const box=document.createElement('div');box.className='address-suggestions';input.parentNode.style.position='relative';input.parentNode.appendChild(box);
    const run=debounce(async()=>{const rows=await searchAddress(input.value.trim());box.innerHTML='';rows.forEach(row=>{const b=document.createElement('button');b.type='button';b.textContent=row.display_name;b.addEventListener('click',()=>{input.value=row.display_name;const latName=input.dataset.latField,lngName=input.dataset.lngField;if(latName&&input.form?.elements[latName])input.form.elements[latName].value=row.lat;if(lngName&&input.form?.elements[lngName])input.form.elements[lngName].value=row.lon;box.innerHTML='';input.dispatchEvent(new Event('address-selected',{bubbles:true}));input.form?.dispatchEvent(new Event('address-selected'));});box.appendChild(b);});});
    input.addEventListener('input',run);input.addEventListener('blur',()=>setTimeout(()=>box.innerHTML='',220));
  });

  async function fillLocation(btn){const form=btn.closest('form')||document;const old=btn.textContent;btn.disabled=true;btn.textContent='Localizando...';try{const p=await getLocation();const address=await reverse(p.lat,p.lng);const addressName=btn.dataset.addressField||'pickup';const latName=btn.dataset.latField||'pickup_lat';const lngName=btn.dataset.lngField||'pickup_lng';if(form.elements?.[addressName])form.elements[addressName].value=address;if(form.elements?.[latName])form.elements[latName].value=p.lat;if(form.elements?.[lngName])form.elements[lngName].value=p.lng;btn.textContent='Localização preenchida';form.dispatchEvent(new Event('location-ready'));const inp=form.elements?.[addressName];if(inp)inp.dispatchEvent(new Event('address-selected',{bubbles:true}));return p;}catch(e){if(!btn.dataset.autoGeolocate)alert('Não foi possível obter sua localização. Autorize o acesso à localização no navegador.');throw e;}finally{btn.disabled=false;setTimeout(()=>btn.textContent=old,2200);}}
  qsa('[data-geolocate-form]').forEach(btn=>btn.addEventListener('click',()=>fillLocation(btn).catch(()=>{})));
  // Preenchimento automático: tenta uma vez por formulário sem exibir alerta intrusivo.
  qsa('[data-geolocate-form][data-auto-geolocate]').forEach(btn=>setTimeout(()=>{const form=btn.closest('form');const field=form?.elements?.[btn.dataset.addressField||'pickup'];if(field&&!field.value.trim())fillLocation(btn).catch(()=>{});},450));

  qsa('[data-route-form]').forEach(form=>{
    const originLat=form.dataset.originLat||'pickup_lat',originLng=form.dataset.originLng||'pickup_lng',destLat=form.dataset.destLat||'destination_lat',destLng=form.dataset.destLng||'destination_lng';
    const originAddress=form.dataset.originAddress||(originLat==='origin_lat'?'origin':'pickup'),destAddress=form.dataset.destAddress||'destination';
    const ensurePoint=async(addressName,latName,lngName)=>{
      let lat=parseFloat(form.elements[latName]?.value),lng=parseFloat(form.elements[lngName]?.value);
      if(Number.isFinite(lat)&&Number.isFinite(lng))return{lat,lng};
      const input=form.elements[addressName],text=(input?.value||'').trim();if(text.length<4)return null;
      const rows=await searchAddress(text);if(!rows.length)return null;
      lat=parseFloat(rows[0].lat);lng=parseFloat(rows[0].lon);
      if(form.elements[latName])form.elements[latName].value=lat;if(form.elements[lngName])form.elements[lngName].value=lng;
      return Number.isFinite(lat)&&Number.isFinite(lng)?{lat,lng}:null;
    };
    const calc=async()=>{
      const summary=qsa('[data-route-summary]',form);summary.forEach(el=>el.textContent='Calculando rota...');
      const a=await ensurePoint(originAddress,originLat,originLng),b=await ensurePoint(destAddress,destLat,destLng);
      if(!a||!b){summary.forEach(el=>el.textContent='Não foi possível localizar origem ou destino. Use Localizar ou escolha uma sugestão de endereço.');return false;}
      const info=await route(a,b);
      const distanceField=form.elements[form.dataset.distanceField||'distance_km'],durationField=form.elements[form.dataset.durationField||'duration_minutes'],valueField=form.elements[form.dataset.valueField||'estimated_value'];
      if(distanceField)distanceField.value=info.distance.toFixed(2);if(durationField)durationField.value=info.duration;
      const autoFare=form.dataset.autoFare!=='0',perKm=parseFloat(form.dataset.priceKm||'0'),base=parseFloat(form.dataset.baseFare||'0'),minFare=parseFloat(form.dataset.minFare||'0'),value=Math.max(minFare,base+info.distance*perKm);
      if(autoFare){if(valueField)valueField.value=value.toFixed(2);summary.forEach(el=>el.innerHTML=`<strong>${info.distance.toFixed(1)} km</strong><span>aprox. ${info.duration} min</span><b>R$ ${value.toFixed(2).replace('.',',')}</b>`);}else{if(valueField)valueField.value='';summary.forEach(el=>el.innerHTML=`<strong>${info.distance.toFixed(1)} km</strong><span>aprox. ${info.duration} min</span><b>Valor informado pelo motorista</b>`);}
      return info.distance>0&&info.duration>0;
    };
    form.addEventListener('address-selected',()=>setTimeout(()=>calc().catch(()=>{}),40));form.addEventListener('location-ready',()=>setTimeout(()=>calc().catch(()=>{}),40));qsa('[data-calculate-route]',form).forEach(b=>b.addEventListener('click',()=>calc().catch(()=>{})));
    let routeSubmitting=false;form.addEventListener('submit',async e=>{if(routeSubmitting)return;const distance=parseFloat(form.elements[form.dataset.distanceField||'distance_km']?.value||'0'),duration=parseInt(form.elements[form.dataset.durationField||'duration_minutes']?.value||'0',10);if(distance>0&&duration>0)return;e.preventDefault();const ok=await calc().catch(()=>false);if(!ok){alert('Não foi possível calcular a rota. Confirme origem e destino antes de solicitar.');return;}routeSubmitting=true;HTMLFormElement.prototype.submit.call(form);});
  });

  // Corridas antigas que foram gravadas sem distância/tempo: calcula apenas para exibição
  // usando as coordenadas existentes ou geocodificando os endereços no navegador.
  qsa('[data-ride-route-card]').forEach(async card=>{
    const out=qs('[data-ride-route-metrics]',card);if(!out||parseFloat(card.dataset.distance||'0')>0)return;
    const point=async(prefix)=>{const lat=parseFloat(card.dataset[prefix+'Lat']||''),lng=parseFloat(card.dataset[prefix+'Lng']||'');if(Number.isFinite(lat)&&Number.isFinite(lng))return{lat,lng};const text=(card.dataset[prefix+'Address']||'').trim();if(text.length<4)return null;const rows=await searchAddress(text);return rows.length?{lat:parseFloat(rows[0].lat),lng:parseFloat(rows[0].lon)}:null;};
    try{const a=await point('pickup'),b=await point('destination');if(!a||!b)return;const info=await route(a,b);out.textContent=`${info.distance.toFixed(1).replace('.',',')} km • ${info.duration} min`;}catch(e){}
  });

  qsa('[data-shuttle-booking-form]').forEach(form=>{
    let submitting=false;
    const resolveField=async(name,latName,lngName)=>{
      let lat=parseFloat(form.elements[latName]?.value||''),lng=parseFloat(form.elements[lngName]?.value||'');
      if(Number.isFinite(lat)&&Number.isFinite(lng))return true;
      const text=(form.elements[name]?.value||'').trim();if(text.length<4)return false;
      const rows=await searchAddress(text);if(!rows.length)return false;
      if(form.elements[latName])form.elements[latName].value=rows[0].lat;
      if(form.elements[lngName])form.elements[lngName].value=rows[0].lon;
      return true;
    };
    form.addEventListener('submit',async e=>{
      if(submitting)return;
      e.preventDefault();
      const btn=form.querySelector('button[type="submit"],button:not([type])');const old=btn?.textContent;
      if(btn){btn.disabled=true;btn.textContent='Confirmando localização...';}
      try{
        const pickupOk=await resolveField('pickup','pickup_lat','pickup_lng');
        const destOk=await resolveField('destination','destination_lat','destination_lng');
        if(!pickupOk||!destOk){alert('Confirme o embarque e escolha uma sugestão de endereço para o desembarque.');return;}
        submitting=true;HTMLFormElement.prototype.submit.call(form);
      }finally{if(btn&&!submitting){btn.disabled=false;btn.textContent=old;}}
    });
  });

  qsa('[data-reservation-calc]').forEach(form=>{const calc=()=>{const start=new Date(form.elements.start_date.value+'T12:00:00'),end=new Date(form.elements.end_date.value+'T12:00:00'),rate=parseFloat(form.dataset.dailyRate||0);if(!isNaN(start)&&!isNaN(end)&&end>=start){const days=Math.max(1,Math.ceil((end-start)/86400000)+1),total=days*rate;if(form.elements.total)form.elements.total.value=total.toFixed(2);const out=qs('[data-reservation-total]',form);if(out)out.textContent=`${days} diária(s) • R$ ${total.toFixed(2).replace('.',',')}`;}};form.addEventListener('change',calc);calc();});

  const mapEl=qs('#companyMap');
  const mapLayout=qs('.map-layout');
  const companyCards=qsa('[data-company-card]');
  const companySearch=qs('[data-company-search]');
  const companySector=qs('[data-company-sector]');
  const nearbyStatus=qs('[data-nearby-status]');
  let companyMap=null,userMarker=null,mapReady=false,pendingCompanyFocus=null;
  let companyMapData=[];const companyMarkers=new Map();
  try{companyMapData=mapEl?JSON.parse(mapEl.dataset.mapCompanies||'[]'):[];}catch(e){companyMapData=[];}
  let currentPosition=null;
  const registeredLat=parseFloat(mapLayout?.dataset.userLat||''),registeredLng=parseFloat(mapLayout?.dataset.userLng||'');
  const companyRadius=Math.max(1,parseFloat(mapLayout?.dataset.radiusKm||'80')||80);
  const companyEntityLabel=(mapLayout?.dataset.entityLabel||'empresa').trim()||'empresa';
  if(Number.isFinite(registeredLat)&&Number.isFinite(registeredLng))currentPosition={lat:registeredLat,lng:registeredLng};
  const norm=v=>(v||'').normalize('NFD').replace(/[\u0300-\u036f]/g,'').toLowerCase().trim();
  const esc=v=>String(v??'').replace(/[&<>"']/g,ch=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[ch]));

  function companyVisibleIds(){return new Set(companyCards.filter(card=>!card.hidden).map(card=>String(card.dataset.companyId||'')));}
  function updateCompanyMapMarkers(fit=false){
    if(!mapReady||!companyMap||!window.L)return;
    const visibleIds=companyVisibleIds(),bounds=[];
    companyMarkers.forEach((marker,id)=>{const visible=visibleIds.has(String(id));if(visible){if(!companyMap.hasLayer(marker))marker.addTo(companyMap);const ll=marker.getLatLng();bounds.push([ll.lat,ll.lng]);}else if(companyMap.hasLayer(marker))companyMap.removeLayer(marker);});
    if(userMarker&&companyMap.hasLayer(userMarker)){const ll=userMarker.getLatLng();if(!bounds.length)bounds.push([ll.lat,ll.lng]);}
    if(fit&&bounds.length)companyMap.fitBounds(bounds,{padding:[38,38],maxZoom:14});
  }
  function filterCompanies(){
    if(!companyCards.length)return;
    const query=norm(companySearch?.value||''), sector=norm(companySector?.value||'');
    const regCity=norm(mapLayout?.dataset.userCity||'');
    companyCards.forEach(card=>{
      const name=norm(card.dataset.name||''),cardSector=norm(card.dataset.sector||''),city=norm(card.dataset.city||'');
      const searchMatch=!query||name.includes(query);const sectorMatch=!sector||cardSector===sector;
      let nearby=true;let km=null;
      const lat=parseFloat(card.dataset.lat),lng=parseFloat(card.dataset.lng);
      if(currentPosition&&Number.isFinite(lat)&&Number.isFinite(lng)){km=haversine(currentPosition,{lat,lng});nearby=km<=companyRadius;}
      else if(!query&&regCity){nearby=city===regCity;}
      const visible=searchMatch&&sectorMatch&&(query?true:nearby);
      card.hidden=!visible;
      const label=card.querySelector('[data-distance-label]');if(label)label.textContent=km!==null?`${km.toFixed(1)} km`:'';
    });
    const list=qs('[data-company-list]');
    if(list&&currentPosition&&!query){
      companyCards.slice().sort((a,b)=>{
        const alat=parseFloat(a.dataset.lat),alng=parseFloat(a.dataset.lng),blat=parseFloat(b.dataset.lat),blng=parseFloat(b.dataset.lng);
        const ad=Number.isFinite(alat)&&Number.isFinite(alng)?haversine(currentPosition,{lat:alat,lng:alng}):999999;
        const bd=Number.isFinite(blat)&&Number.isFinite(blng)?haversine(currentPosition,{lat:blat,lng:blng}):999999;
        return ad-bd;
      }).forEach(card=>list.appendChild(card));
    }
    const visible=companyCards.filter(c=>!c.hidden).length;
    if(nearbyStatus){
      if(query)nearbyStatus.textContent=visible?`${visible} resultado(s) da pesquisa exibido(s) no mapa.`:'Nenhuma empresa encontrada para esta pesquisa.';
      else if(sector)nearbyStatus.textContent=visible?`${visible} ${companyEntityLabel}(s) deste segmento exibida(s) no mapa.`:`Nenhuma ${companyEntityLabel} próxima neste segmento.`;
      else nearbyStatus.textContent=visible?`${visible} ${companyEntityLabel}(s) encontrada(s), priorizadas por proximidade.`:`Nenhuma ${companyEntityLabel} próxima. Pesquise pelo nome ou ID para ampliar a busca.`;
    }
    updateCompanyMapMarkers(Boolean(query||sector));
  }

  if(mapEl){
    const showMapFallback=(message)=>{
      mapEl.classList.add('map-unavailable');
      mapEl.innerHTML=`<div class="map-fallback"><span>🗺️</span><strong>Mapa temporariamente indisponível</strong><p>${esc(message||'A lista de locais continua disponível logo abaixo.')}</p></div>`;
      if(nearbyStatus&&nearbyStatus.textContent.includes('Localizando'))nearbyStatus.textContent=`Use a lista de ${companyEntityLabel}s abaixo enquanto o mapa carrega.`;
    };
    const loadStyle=(href)=>new Promise((resolve,reject)=>{const existing=Array.from(document.styleSheets||[]).some(s=>String(s.href||'').includes('leaflet'));if(existing)return resolve();const css=document.createElement('link');css.rel='stylesheet';css.href=href;css.onload=resolve;css.onerror=reject;document.head.appendChild(css);});
    const loadScript=(src)=>new Promise((resolve,reject)=>{if(window.L)return resolve();const s=document.createElement('script');s.src=src;s.onload=()=>window.L?resolve():reject(new Error('Leaflet não iniciou'));s.onerror=reject;document.head.appendChild(s);});
    const firstOk=async(loaders)=>{let last;for(const fn of loaders){try{return await fn();}catch(e){last=e;}}throw last||new Error('Recurso indisponível');};
    const loadLeaflet=async()=>{
      if(window.L)return;
      await Promise.all([
        firstOk([()=>loadStyle('https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'),()=>loadStyle('https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css')]),
        firstOk([()=>loadScript('https://unpkg.com/leaflet@1.9.4/dist/leaflet.js'),()=>loadScript('https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js')])
      ]);
    };
    const timeout=new Promise((_,reject)=>setTimeout(()=>reject(new Error('Tempo limite ao carregar o mapa.')),9000));
    Promise.race([loadLeaflet(),timeout]).then(()=>{
      if(!window.L)throw new Error('Biblioteca do mapa indisponível.');
      mapEl.innerHTML='';mapEl.classList.remove('map-unavailable');
      companyMap=L.map(mapEl,{scrollWheelZoom:false}).setView([-14.2,-51.9],4);
      const tiles=L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{maxZoom:19,attribution:'© OpenStreetMap'}).addTo(companyMap);
      let tileErrors=0,tilesLoaded=0;tiles.on('tileload',()=>{tilesLoaded++;});tiles.on('tileerror',()=>{tileErrors++;if(tileErrors>=8&&tilesLoaded===0){try{companyMap.remove();}catch(e){}companyMap=null;mapReady=false;showMapFallback('Não foi possível carregar o mapa agora. Use os cartões e o botão Como chegar.');}});
      companyMapData.forEach(c=>{if(c.lat&&c.lng){const p=[parseFloat(c.lat),parseFloat(c.lng)];if(!Number.isFinite(p[0])||!Number.isFinite(p[1]))return;const icon=L.divIcon({className:'segment-map-icon-wrap',html:`<span class="segment-map-icon" title="${esc(c.sector_label||c.sector)}">${esc(c.icon||'🏢')}</span>`,iconSize:[38,38],iconAnchor:[19,34],popupAnchor:[0,-32]});const marker=L.marker(p,{icon}).bindPopup(`<strong>${esc(c.name)}</strong><br>${esc(c.sector_label||c.sector)}<br>${esc(c.address)}`);companyMarkers.set(String(c.id),marker);}});
      mapReady=true;window.linkExpressCompanyMap=companyMap;filterCompanies();
      if(currentPosition){const icon=L.divIcon({className:'user-map-icon-wrap',html:'<span class="user-map-icon">👤</span>',iconSize:[42,42],iconAnchor:[21,38],popupAnchor:[0,-36]});userMarker=L.marker([currentPosition.lat,currentPosition.lng],{icon}).addTo(companyMap).bindPopup('Você está aqui');}
      updateCompanyMapMarkers(true);
      if(pendingCompanyFocus)setTimeout(()=>focusCompanyOnMap(pendingCompanyFocus),220);
      setTimeout(()=>{try{companyMap.invalidateSize();}catch(e){}},180);
    }).catch(()=>showMapFallback('A conexão com o provedor do mapa falhou. A lista de clínicas/empresas permanece funcionando.'));
  }

  companySearch?.addEventListener('input',filterCompanies);companySector?.addEventListener('change',filterCompanies);filterCompanies();

  function focusCompanyOnMap(id){
    const marker=companyMarkers.get(String(id||''));
    if(!marker||!companyMap||!mapReady){pendingCompanyFocus=String(id||'');return false;}
    try{
      if(!companyMap.hasLayer(marker))marker.addTo(companyMap);
      const ll=marker.getLatLng();companyMap.setView([ll.lat,ll.lng],16,{animate:true});marker.openPopup();
      pendingCompanyFocus=null;mapEl?.scrollIntoView({behavior:'smooth',block:'center'});setTimeout(()=>companyMap.invalidateSize(),260);return true;
    }catch(e){return false;}
  }
  qsa('[data-map-focus-id]').forEach(btn=>btn.addEventListener('click',()=>{
    const id=btn.dataset.mapFocusId;if(focusCompanyOnMap(id))return;
    const card=companyCards.find(c=>String(c.dataset.companyId||'')===String(id||''));
    if(card){card.scrollIntoView({behavior:'smooth',block:'center'});card.classList.add('clinic-card-focus');setTimeout(()=>card.classList.remove('clinic-card-focus'),1800);}
  }));

  async function locateCompanies(btn){
    const old=btn.textContent;btn.disabled=true;btn.textContent='Localizando...';
    try{
      const p=await getLocation();currentPosition=p;filterCompanies();
      if(companyMap&&window.L){if(userMarker)userMarker.remove();const icon=L.divIcon({className:'user-map-icon-wrap',html:'<span class="user-map-icon">👤</span>',iconSize:[42,42],iconAnchor:[21,38],popupAnchor:[0,-36]});userMarker=L.marker([p.lat,p.lng],{icon}).addTo(companyMap).bindPopup('Você está aqui');companyMap.setView([p.lat,p.lng],13);updateCompanyMapMarkers(false);}
      btn.textContent='Localização atualizada';
    }catch(e){if(!btn.dataset.autoLocate)alert('Não foi possível localizar você. Verifique a permissão de localização.');}
    finally{btn.disabled=false;setTimeout(()=>btn.textContent=old,2200);}
  }
  qsa('[data-locate-user]').forEach(btn=>btn.addEventListener('click',()=>locateCompanies(btn)));
  qsa('[data-locate-user][data-auto-locate]').forEach(btn=>setTimeout(()=>locateCompanies(btn),500));


  // Lava-Jato: calcula a distância do usuário e ordena os estabelecimentos mais próximos.
  const washCards=qsa('[data-wash-card]');
  const washLocate=qs('[data-wash-locate]');
  if(washLocate&&washCards.length){
    washLocate.addEventListener('click',async()=>{const old=washLocate.textContent;washLocate.disabled=true;washLocate.textContent='Localizando...';try{const pos=await getLocation();washCards.forEach(card=>{const lat=parseFloat(card.dataset.lat),lng=parseFloat(card.dataset.lng);const dist=Number.isFinite(lat)&&Number.isFinite(lng)?haversine(pos,{lat,lng}):null;card.dataset.distance=dist===null?'999999':String(dist);const label=card.querySelector('[data-wash-distance]');if(label)label.textContent=dist===null?'Localização não cadastrada':`${dist.toFixed(1).replace('.',',')} km de distância`;});const parent=washCards[0].parentElement;washCards.slice().sort((a,b)=>parseFloat(a.dataset.distance)-parseFloat(b.dataset.distance)).forEach(card=>parent.appendChild(card));washLocate.textContent='Mais próximos primeiro';}catch(e){alert('Não foi possível obter sua localização. Autorize o acesso à localização no navegador.');}finally{washLocate.disabled=false;setTimeout(()=>washLocate.textContent=old,2600);}});
  }

  // Prestadores de serviço próximos: localização por distância, pesquisa e paginação
  // de 5 em 5 cards para manter a tela leve no celular.
  const providerNearList=qs('[data-provider-near-list]');
  if(providerNearList){
    const providerCards=qsa('[data-provider-near-card]',providerNearList);
    const providerStatus=qs('[data-provider-near-status]');
    const providerLocateButtons=qsa('[data-provider-locate]');
    const providerSearch=qs('[data-provider-search]');
    const providerPagination=qs('[data-provider-pagination]');
    const providerEmpty=qs('[data-provider-empty]');
    const providerRadius=Math.max(1,parseFloat(providerNearList.dataset.radiusKm||'30')||30);
    const pageSize=Math.max(1,parseInt(providerNearList.dataset.providerPageSize||'5',10)||5);
    const regLat=parseFloat(providerNearList.dataset.userLat||''),regLng=parseFloat(providerNearList.dataset.userLng||'');
    const regCity=(providerNearList.dataset.userCity||'').trim();
    const regState=(providerNearList.dataset.userState||'').trim();
    let providerPosition=(Number.isFinite(regLat)&&Number.isFinite(regLng))?{lat:regLat,lng:regLng}:null;
    let providerPositionSource=providerPosition?'saved':'';
    let providerRun=0,providerPage=1;
    const providerCityCache=new Map();
    providerCards.forEach(card=>card.dataset.providerDistanceVisible='1');

    const geocodeProviderPlace=(text,key='')=>{
      text=(text||'').trim();if(!text)return Promise.resolve(null);
      const cacheKey=norm(key||text);if(providerCityCache.has(cacheKey))return providerCityCache.get(cacheKey);
      const task=(async()=>{try{const rows=await searchAddress(text);if(!rows.length)return null;const lat=parseFloat(rows[0].lat),lng=parseFloat(rows[0].lon);return Number.isFinite(lat)&&Number.isFinite(lng)?{lat,lng}:null;}catch(e){return null;}})();
      providerCityCache.set(cacheKey,task);return task;
    };
    const geocodeProviderCity=(city,state='')=>geocodeProviderPlace([city,state,'Brasil'].filter(Boolean).join(', '),`${city}|${state}`);

    const ensureProviderPosition=async()=>{
      if(providerPosition)return providerPosition;
      if(regCity){const p=await geocodeProviderCity(regCity,regState);if(p){providerPosition=p;providerPositionSource='profile_city';}}
      return providerPosition;
    };

    const providerPoint=async card=>{
      const lat=parseFloat(card.dataset.providerLat||''),lng=parseFloat(card.dataset.providerLng||'');
      if(Number.isFinite(lat)&&Number.isFinite(lng))return {point:{lat,lng},approx:false};
      const address=(card.dataset.providerAddress||'').trim();
      if(address){const point=await geocodeProviderPlace(address,`address|${address}`);if(point)return {point,approx:true};}
      const city=(card.dataset.providerCity||'').trim(),state=(card.dataset.providerState||'').trim();
      const point=await geocodeProviderCity(city,state);return point?{point,approx:true}:null;
    };

    const renderProviderPage=()=>{
      const term=norm(providerSearch?.value||'');
      const eligible=providerCards.filter(card=>{
        const distanceOk=card.dataset.providerDistanceVisible!=='0';
        const text=norm(card.dataset.providerSearchText||card.textContent||'');
        return distanceOk&&(!term||text.includes(term));
      });
      const pages=Math.max(1,Math.ceil(eligible.length/pageSize));providerPage=Math.min(Math.max(1,providerPage),pages);
      const from=(providerPage-1)*pageSize,to=from+pageSize;
      providerCards.forEach(card=>card.hidden=true);eligible.slice(from,to).forEach(card=>card.hidden=false);
      if(providerEmpty)providerEmpty.hidden=eligible.length>0;
      if(providerPagination){
        providerPagination.innerHTML='';
        if(eligible.length>pageSize){
          const add=(label,page,disabled=false,active=false)=>{const b=document.createElement('button');b.type='button';b.className=`btn btn-sm ${active?'btn-primary':'btn-secondary'}`;b.textContent=label;b.disabled=disabled;b.addEventListener('click',()=>{providerPage=page;renderProviderPage();providerNearList.scrollIntoView({behavior:'smooth',block:'start'});});providerPagination.appendChild(b);};
          add('‹ Anterior',providerPage-1,providerPage<=1);
          const start=Math.max(1,providerPage-2),finish=Math.min(pages,start+4);for(let i=start;i<=finish;i++)add(String(i),i,false,i===providerPage);
          add('Próxima ›',providerPage+1,providerPage>=pages);
          const info=document.createElement('small');info.style.width='100%';info.style.textAlign='center';info.textContent=`Mostrando ${from+1}–${Math.min(to,eligible.length)} de ${eligible.length} prestador(es)`;providerPagination.appendChild(info);
        }else if(eligible.length){const info=document.createElement('small');info.textContent=`${eligible.length} prestador(es) encontrado(s)`;providerPagination.appendChild(info);}
      }
    };

    const applyProviderDistance=async()=>{
      const run=++providerRun;if(providerStatus)providerStatus.textContent='Calculando distância dos profissionais...';
      const origin=await ensureProviderPosition();if(run!==providerRun)return;
      let visible=0,known=0;
      const rows=await Promise.all(providerCards.map(async card=>{
        if(!origin)return {card,show:true,dist:null,approx:false};
        const resolved=await providerPoint(card);let show=false,dist=null,approx=false;
        if(resolved){dist=haversine(origin,resolved.point);known++;approx=resolved.approx;show=dist<=providerRadius;}
        return {card,show,dist,approx};
      }));
      if(run!==providerRun)return;
      rows.forEach(({card,show,dist,approx})=>{
        card.dataset.providerDistanceVisible=show?'1':'0';card.dataset.providerDistance=dist===null?'999999':String(dist);
        const label=card.querySelector('[data-provider-distance]');if(label){if(dist!==null)label.textContent=`📍 ${approx?'≈ ':''}${dist.toFixed(1).replace('.',',')} km${approx?' (aprox.)':''}`;else label.textContent='📍 distância não calculada';}
        if(show)visible++;
      });
      providerCards.sort((a,b)=>parseFloat(a.dataset.providerDistance||'999999')-parseFloat(b.dataset.providerDistance||'999999'));providerCards.forEach(card=>providerNearList.appendChild(card));
      providerPage=1;renderProviderPage();
      if(providerStatus){
        if(origin){const source=providerPositionSource==='live'?'sua localização atual':providerPositionSource==='saved'?'sua localização salva':'a cidade cadastrada no perfil';providerStatus.textContent=visible?`${visible} prestador(es) em até ${providerRadius.toFixed(0)} km de ${source}, do mais próximo para o mais distante.`:`${known?'Nenhum prestador está':'Não foi possível calcular prestadores'} em até ${providerRadius.toFixed(0)} km de ${source}.`;}
        else providerStatus.textContent='Localização não disponível. Mostrando os prestadores sem filtro de distância; use “Usar minha localização” para ordenar por proximidade.';
      }
    };

    const locateProviders=async(btn=null)=>{
      const old=btn?.textContent;if(btn){btn.disabled=true;btn.textContent='Localizando...';}
      try{providerPosition=await getLocation();providerPositionSource='live';await applyProviderDistance();if(btn)btn.textContent='Localização atualizada';}
      catch(e){await applyProviderDistance();if(btn&&!btn.dataset.autoLocate)alert('Não foi possível obter sua localização. Verifique a permissão do navegador.');}
      finally{if(btn){btn.disabled=false;setTimeout(()=>btn.textContent=old,2200);}}
    };
    providerSearch?.addEventListener('input',()=>{providerPage=1;renderProviderPage();});providerSearch?.addEventListener('keydown',e=>{if(e.key==='Enter')e.preventDefault();});
    providerLocateButtons.forEach(btn=>btn.addEventListener('click',()=>locateProviders(btn)));
    renderProviderPage();applyProviderDistance();
    if(providerLocateButtons.some(btn=>btn.hasAttribute('data-auto-locate')))setTimeout(()=>locateProviders(providerLocateButtons.find(btn=>btn.hasAttribute('data-auto-locate'))||null),450);
  }

})();
