(function(){ var form=document.getElementById('quote-configurator'); if(!form)return; var pageTitle=document.getElementById('quote-page-title'); var pageLede=document.getElementById('quote-page-lede'); var progressAddress=document.getElementById('progress-address'); var progressService=document.getElementById('progress-service'); var progressCoverage=document.getElementById('progress-coverage'); var changeButton=document.getElementById('change-service'); var serviceSection=document.getElementById('choose-service'); var serviceRail=serviceSection.querySelector('.quote-choice-grid'); var servicePrev=serviceSection.querySelector('.service-carousel-prev'); var serviceNext=serviceSection.querySelector('.service-carousel-next'); var serviceOverview=document.getElementById('selected-service-overview'); var serviceDetails={ 'Unarmed Security':{title:'Unarmed Security',mark:'U',description:'A professional, visible presence for properties that need consistent observation, access support, and public-facing service.',features:['Uniformed officer assigned to your property','Access, visitor, contractor, and delivery support','Foot patrols and observation of priority areas','Daily activity and incident documentation']}, 'Armed Security':{title:'Armed Security',mark:'A',description:'An elevated protective posture for environments whose risk assessment supports a licensed armed presence.',features:['Licensed and professionally outfitted armed officer','Visible deterrence and defined post responsibilities','Incident response within training and authority','Management oversight and documented activity']}, 'Fire Watch':{title:'Fire Watch',mark:'FW',description:'Dedicated life-safety monitoring when fire protection is impaired, during hot work, or when ordered by the authority having jurisdiction.',features:['Documented patrol routes and required intervals','Observation for smoke, fire, and unsafe conditions','Immediate notification and emergency escalation','Fire-watch-only duties with detailed logs']}, 'Mobile Patrol':{title:'Mobile Patrol',mark:'MP',description:'Overnight visibility and response without the cost of placing an officer at one fixed post for the entire shift.',features:['Armed officers in marked patrol vehicles','Randomized property patrols','Response to calls at contracted properties','Electronic activity and incident reporting']} }; var modal=document.createElement('div'); modal.className='service-modal'; modal.id='service-modal'; modal.hidden=true; modal.innerHTML='
'; document.body.appendChild(modal); var modalService=''; function closeModal(){modal.hidden=true;document.body.classList.remove('modal-open')} function openModal(service){var details=serviceDetails[service];if(!details)return;modalService=service;modal.querySelector('#modal-title').textContent=details.title;modal.querySelector('#modal-description').textContent=details.description;modal.querySelector('#modal-features').innerHTML=details.features.map(function(item,index){return '
'+String(index+1).padStart(2,'0')+''+item+'
'}).join('');modal.querySelectorAll('[data-modal-service]').forEach(function(button){button.classList.toggle('active',button.dataset.modalService===service)});modal.hidden=false;document.body.classList.add('modal-open');modal.querySelector('.service-modal-close').focus()} form.querySelectorAll('.closer-look').forEach(function(button){button.addEventListener('click',function(event){event.preventDefault();event.stopPropagation();openModal(button.dataset.service)})}); modal.querySelectorAll('[data-modal-close]').forEach(function(button){button.addEventListener('click',closeModal)}); modal.querySelectorAll('[data-modal-service]').forEach(function(button){button.addEventListener('click',function(){openModal(button.dataset.modalService)})}); modal.querySelector('#modal-build').addEventListener('click',function(){var input=form.querySelector('input[name="service"][value="'+modalService+'"]');closeModal();if(input&&!input.disabled){input.checked=true;input.dispatchEvent(new Event('change',{bubbles:true}))}}); modal.querySelector('#modal-explore').addEventListener('click',function(){var paths={'Unarmed Security':'/armed-unarmed-security/','Armed Security':'/armed-unarmed-security/','Fire Watch':'/fire-watch/','Mobile Patrol':'/patrol/'};window.location.href=paths[modalService]||'/services/'}); document.addEventListener('keydown',function(event){if(event.key==='Escape'&&!modal.hidden)closeModal()}); function updateServiceArrows(){ if(!serviceRail||!servicePrev||!serviceNext)return; var maxScroll=Math.max(0,serviceRail.scrollWidth-serviceRail.clientWidth); servicePrev.disabled=serviceRail.scrollLeft<=2; serviceNext.disabled=serviceRail.scrollLeft>=maxScroll-2; } function scrollServices(direction){ var card=serviceRail&&serviceRail.querySelector('.quote-choice'); if(!card)return; var gap=parseFloat(window.getComputedStyle(serviceRail).gap)||0; serviceRail.scrollBy({left:direction*(card.getBoundingClientRect().width+gap),behavior:'smooth'}); } if(serviceRail&&servicePrev&&serviceNext){ servicePrev.addEventListener('click',function(){scrollServices(-1)}); serviceNext.addEventListener('click',function(){scrollServices(1)}); serviceRail.addEventListener('scroll',updateServiceArrows,{passive:true}); window.addEventListener('resize',updateServiceArrows); updateServiceArrows(); } function showBuilder(input){ var details=serviceDetails[input.value]; form.classList.remove('builder-pending'); form.classList.add('builder-configuring'); if(serviceOverview&&details){serviceOverview.hidden=false;serviceOverview.querySelector('#overview-title').textContent=details.title;serviceOverview.querySelector('#overview-description').textContent=details.description;serviceOverview.querySelector('#overview-features').innerHTML=details.features.map(function(item,index){return '
'+String(index+1).padStart(2,'0')+''+item+'
'}).join('')} pageTitle.textContent='Build your '+input.value.toLowerCase()+' plan.'; pageLede.textContent='Choose the coverage that fits your property. Our team will review the completed plan and prepare a proposal.'; progressService.classList.remove('active'); progressCoverage.classList.add('active'); } form.querySelectorAll('input[name="service"]').forEach(function(input){ input.addEventListener('change',function(){ if(input.checked)showBuilder(input); }); }); changeButton.addEventListener('click',function(){ form.querySelectorAll('input[name="service"]').forEach(function(input){input.checked=false}); form.classList.add('builder-pending'); form.classList.remove('builder-configuring'); if(serviceOverview)serviceOverview.hidden=true; pageTitle.textContent='Choose your security service.'; pageLede.textContent='Start with the protection your property needs. We’ll help you configure the coverage next.'; progressCoverage.classList.remove('active'); progressService.classList.add('active'); form.dispatchEvent(new Event('change',{bubbles:true})); serviceSection.scrollIntoView({behavior:'smooth',block:'start'}); }); })(); (function(){ var form=document.getElementById('quote-area-form'); var input=document.getElementById('quote-area-line1'); var cityInput=document.getElementById('quote-area-city'); var stateInput=document.getElementById('quote-area-state'); var zipInput=document.getElementById('quote-area-zip'); var list=document.getElementById('quote-area-suggestions'); var result=document.getElementById('quote-area-result'); var continueButton=document.getElementById('quote-area-continue'); var partnerButton=document.getElementById('quote-area-partner'); var contactButton=document.getElementById('quote-area-contact'); var changeAddress=document.getElementById('change-address'); var store=document.getElementById('quote-store'); var pageTitle=document.getElementById('quote-page-title'); var pageLede=document.getElementById('quote-page-lede'); var eligibilityGate=document.getElementById('quote-eligibility'); var addressEntry=document.getElementById('quote-address-entry'); var eligibilityAck=document.getElementById('quote-eligibility-ack'); var eligibilityContinue=document.getElementById('quote-eligibility-continue'); var progressAddress=document.getElementById('progress-address'); var progressService=document.getElementById('progress-service'); var progressCoverage=document.getElementById('progress-coverage'); var configurator=document.getElementById('quote-configurator'); if(!form||!input||!cityInput||!stateInput||!zipInput||!list||!result||!eligibilityGate||!addressEntry||!eligibilityAck||!eligibilityContinue)return; var loader=form.querySelector('.quote-area-loader'); var timer=null,controller=null,suggestions=[],activeIndex=-1; var fullServiceCounties={NC:['new hanover county'],SC:['horry county']}; var limitedServiceCounties={NC:['pender county','brunswick county'],SC:['georgetown county']}; var partnerCounties={NC:['guilford county','mecklenburg county'],SC:['york county']}; var patrolInput=configurator.querySelector('input[name="service"][value="Mobile Patrol"]'); function normalizeCounty(county){return String(county||'').toLowerCase().replace(/\s+county\b.*$/,'').trim()} function formatCounty(county){var label=String(county||'').trim();return /\s+county$/i.test(label)?label:label+' County'} function countyIn(list,state,county){var normalized=normalizeCounty(county);return (list[state]||[]).some(function(item){return normalizeCounty(item)===normalized})} function setPatrolAvailability(available){ if(!patrolInput)return;var card=patrolInput.closest('.quote-choice'),note=card.querySelector('.service-unavailable-note'),details=card.querySelector('.closer-look'); patrolInput.disabled=!available;patrolInput.checked=available?patrolInput.checked:false;card.classList.toggle('is-unavailable',!available);card.setAttribute('aria-disabled',available?'false':'true');if(note)note.hidden=available;if(details)details.disabled=!available; } function carryAddressToServices(){ var values={street:input.value.trim(),city:cityInput.value.trim(),state:stateInput.value,zip:zipInput.value.trim()}; ['patrol','standard'].forEach(function(prefix){ Object.keys(values).forEach(function(part){var field=document.getElementById(prefix+'-service-'+part);if(field){field.value=values[part];field.classList.add('carried-service-address');field.setAttribute('aria-readonly','true');if(field.tagName==='SELECT'){field.tabIndex=-1}else{field.readOnly=true}field.dispatchEvent(new Event('input',{bubbles:true}));field.dispatchEvent(new Event('change',{bubbles:true}))}}); }); } function fullAddress(){return [input.value.trim(),cityInput.value.trim(),stateInput.value,zipInput.value.trim()].filter(Boolean).join(', ')} function showAddressEntry(){ eligibilityGate.hidden=true;addressEntry.hidden=false; pageTitle.textContent='First, confirm your property.';pageLede.textContent='Enter the service address to confirm whether it is within our standard operating area.'; input.focus(); } function resetEligibilityGate(){ addressEntry.hidden=true;eligibilityGate.hidden=false;eligibilityAck.checked=false;eligibilityContinue.disabled=true; pageTitle.textContent='First, confirm this request is eligible.';pageLede.textContent='Review the service exclusions below before entering the property address.'; } eligibilityAck.addEventListener('change',function(){eligibilityContinue.disabled=!eligibilityAck.checked}); eligibilityContinue.addEventListener('click',function(){if(eligibilityAck.checked)showAddressEntry()}); var addressConfirm=document.createElement('div'); addressConfirm.className='address-change-modal'; addressConfirm.hidden=true; addressConfirm.innerHTML='
'; document.body.appendChild(addressConfirm); var addressConfirmText=addressConfirm.querySelector('#address-change-current'); function closeAddressConfirm(){addressConfirm.hidden=true;document.body.classList.remove('address-change-open');changeAddress.focus()} function openAddressConfirm(){addressConfirmText.textContent=fullAddress()||'Current verified address';addressConfirm.hidden=false;document.body.classList.add('address-change-open');addressConfirm.querySelector('.address-change-cancel').focus()} function restartAddressProcess(){ addressConfirm.hidden=true;document.body.classList.remove('address-change-open'); var changeService=document.getElementById('change-service'); if(configurator.classList.contains('builder-configuring')&&changeService)changeService.click(); configurator.reset(); configurator.querySelectorAll('input[name="service"]').forEach(function(service){service.checked=false}); configurator.classList.add('builder-pending');configurator.classList.remove('builder-configuring'); store.classList.remove('address-confirmed');progressCoverage.classList.remove('active');progressService.classList.remove('active');progressAddress.classList.add('active'); resetEligibilityGate(); document.querySelector('.quote-store-head').scrollIntoView({behavior:'smooth',block:'start'});eligibilityAck.focus({preventScroll:true}); } addressConfirm.querySelectorAll('[data-address-cancel]').forEach(function(button){button.addEventListener('click',closeAddressConfirm)}); addressConfirm.querySelector('.address-change-confirm').addEventListener('click',restartAddressProcess); document.addEventListener('keydown',function(event){if(event.key==='Escape'&&!addressConfirm.hidden)closeAddressConfirm()}); var coverageOutcome=document.createElement('div'); coverageOutcome.className='coverage-outcome-modal'; coverageOutcome.hidden=true; coverageOutcome.innerHTML='
'; document.body.appendChild(coverageOutcome); var outcomeWindow=coverageOutcome.querySelector('.coverage-outcome-window'); var outcomeIcon=coverageOutcome.querySelector('#coverage-outcome-icon'); var outcomeEyebrow=coverageOutcome.querySelector('#coverage-outcome-eyebrow'); var outcomeTitle=coverageOutcome.querySelector('#coverage-outcome-title'); var outcomeMessage=coverageOutcome.querySelector('#coverage-outcome-message'); var outcomeAddress=coverageOutcome.querySelector('#coverage-outcome-address'); var outcomePrimary=coverageOutcome.querySelector('.coverage-outcome-primary'); var outcomeSecondary=coverageOutcome.querySelector('.coverage-outcome-secondary'); var currentOutcome=''; function closeCoverageOutcome(){coverageOutcome.hidden=true;document.body.classList.remove('coverage-outcome-open')} function editCoverageAddress(){closeCoverageOutcome();clearAddressDetails();input.focus()} function openCoverageOutcome(state,title,message,address){ var settings={ inside:{eyebrow:'Service available',icon:'✓',primary:'Continue to services',secondary:'Use another address'}, limited:{eyebrow:'Limited coverage',icon:'!',primary:'Continue to services',secondary:'Use another address'}, partner:{eyebrow:'Regional provider',icon:'↗',primary:'Visit regional provider',secondary:'Return to homepage'}, outside:{eyebrow:'Outside service area',icon:'–',primary:'Return to homepage',secondary:'Check another address'} }[state]; if(!settings)return; currentOutcome=state;outcomeWindow.dataset.outcome=state;outcomeIcon.textContent=settings.icon;outcomeEyebrow.textContent=settings.eyebrow; outcomeTitle.textContent=title;outcomeMessage.textContent=message;outcomeAddress.textContent=address||fullAddress(); outcomePrimary.textContent=settings.primary;outcomeSecondary.textContent=settings.secondary; outcomePrimary.href=state==='partner'?'https://www.piedmontpatrol.com/':(state==='outside'?'/':'#'); if(state==='partner'){outcomePrimary.target='_blank';outcomePrimary.rel='noopener noreferrer'}else{outcomePrimary.removeAttribute('target');outcomePrimary.removeAttribute('rel')} coverageOutcome.hidden=false;document.body.classList.add('coverage-outcome-open');outcomePrimary.focus(); } outcomePrimary.addEventListener('click',function(event){ if(currentOutcome==='inside'||currentOutcome==='limited'){event.preventDefault();closeCoverageOutcome();continueButton.click()} }); outcomeSecondary.addEventListener('click',function(){if(currentOutcome==='partner')window.location.href='/';else editCoverageAddress()}); coverageOutcome.querySelector('.coverage-outcome-close').addEventListener('click',editCoverageAddress); coverageOutcome.querySelector('.coverage-outcome-backdrop').addEventListener('click',closeCoverageOutcome); document.addEventListener('keydown',function(event){if(event.key==='Escape'&&!coverageOutcome.hidden)closeCoverageOutcome()}); function fillAddress(address){ var parts=address.split(',').map(function(part){return part.trim()}).filter(Boolean);if(parts.length<3){input.value=address;return} var tail=parts.pop(),stateZip=tail.match(/^([A-Z]{2})\s+(\d{5}(?:-\d{4})?)$/i); if(!stateZip&&/^\d{5}(?:-\d{4})?$/.test(tail)&&parts.length){stateZip=(parts.pop()+' '+tail).match(/^([A-Z]{2})\s+(\d{5}(?:-\d{4})?)$/i)} var city=parts.pop(); input.value=parts.join(', ');cityInput.value=city||''; if(stateZip){var state=stateZip[1].toUpperCase();if(state==='NC'||state==='SC')stateInput.value=state;zipInput.value=stateZip[2]} } function censusUrl(address,geographies){ var endpoint=geographies?'geographies':'locations'; var params=new URLSearchParams({address:address,benchmark:'Public_AR_Current',format:'jsonp'}); if(geographies)params.set('vintage','Current_Current'); return 'https://geocoding.geo.census.gov/geocoder/'+endpoint+'/onelineaddress?'+params.toString(); } function lookup(address,geographies,signal){ return new Promise(function(resolve,reject){ var callback='tfpAddressCallback'+Date.now()+Math.random().toString(36).slice(2); var script=document.createElement('script'); var timeout=window.setTimeout(function(){finish(new Error('Address lookup timed out'))},12000); var settled=false; function cleanup(){window.clearTimeout(timeout);delete window[callback];script.remove();if(signal)signal.removeEventListener('abort',abort)} function finish(error,data){if(settled)return;settled=true;cleanup();if(error)reject(error);else resolve(data&&data.result&&Array.isArray(data.result.addressMatches)?data.result.addressMatches:[])} function abort(){var error=new Error('Address lookup cancelled');error.name='AbortError';finish(error)} window[callback]=function(data){finish(null,data)}; script.src=censusUrl(address,geographies)+'&callback='+encodeURIComponent(callback); script.async=true;script.onerror=function(){finish(new Error('Address lookup unavailable'))}; if(signal){if(signal.aborted){abort();return}signal.addEventListener('abort',abort,{once:true})} document.head.appendChild(script); }); } function autocompleteLookup(query,signal){ var localQuery=query.trim(); if(/\bwilmington\b/i.test(localQuery)&&!/\b(?:NC|North Carolina)\b/i.test(localQuery))localQuery+=', NC'; if(/\bmyrtle\s+beach\b/i.test(localQuery)&&!/\b(?:SC|South Carolina)\b/i.test(localQuery))localQuery+=', SC'; var params=new URLSearchParams({q:localQuery,limit:'10',bbox:'-83.5,32.0,-75.0,36.7',lang:'en'}); if(/\bwilmington\b/i.test(localQuery)){params.set('lat','34.2257');params.set('lon','-77.9447')} if(/\bmyrtle\s+beach\b/i.test(localQuery)){params.set('lat','33.6891');params.set('lon','-78.8867')} var photon=fetch('https://photon.komoot.io/api/?'+params.toString(),{signal:signal,headers:{Accept:'application/json'}}).then(function(response){if(!response.ok)throw new Error('Address suggestions unavailable');return response.json()}).then(function(data){ var typedNumber=(input.value.trim().match(/^\d+[A-Za-z-]*/)||[])[0]||''; return (data.features||[]).map(function(feature){ var p=feature.properties||{},street=p.street||p.name||'',number=p.housenumber||typedNumber; if(number&&street&&!new RegExp('^'+number.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')+'\\b','i').test(street))street=number+' '+street; var city=p.city||p.town||p.village||p.locality||p.county||'',state=p.state==='North Carolina'?'NC':p.state==='South Carolina'?'SC':'',zip=p.postcode||''; if(!street||!city||!state)return null; return {label:[street,city,state,zip].filter(Boolean).join(', '),address:[street,city,state+(zip?' '+zip:'')].filter(Boolean).join(', '),county:p.county||'',state:state}; }).filter(Boolean); }); var census=lookup(localQuery,false,signal).then(function(matches){ return matches.map(function(match){ var c=match.addressComponents||{},matched=match.matchedAddress||''; return matched?{label:matched,address:matched,county:'',state:(c.state||'').toUpperCase()}:null; }).filter(Boolean); }).catch(function(error){if(error.name==='AbortError')throw error;return[]}); var photonSafe=photon.catch(function(error){if(error.name==='AbortError')throw error;return[]}); function rank(items){ var expectedCity=/\bwilmington\b/i.test(localQuery)?'wilmington':(/\bmyrtle\s+beach\b/i.test(localQuery)?'myrtle beach':''); var expectedState=/\b(?:NC|North Carolina)\b/i.test(localQuery)?'NC':(/\b(?:SC|South Carolina)\b/i.test(localQuery)?'SC':''); return items.filter(function(item,index,all){return all.findIndex(function(other){return other.address.toLowerCase()===item.address.toLowerCase()})===index}).map(function(item,index){ var label=item.label.toLowerCase(),score=0; if(expectedCity&&label.indexOf(', '+expectedCity+',')>=0)score+=100; else if(expectedCity&&label.indexOf(expectedCity)>=0)score+=60; if(expectedState&&item.state===expectedState)score+=25; if(/^109\s+discovery\s+(?:place|pl)\b/i.test(item.label))score+=20; return {item:item,score:score,index:index}; }).sort(function(a,b){return b.score-a.score||a.index-b.index}).map(function(entry){return entry.item}).slice(0,5); } return Promise.all([census,photonSafe]).then(function(results){return rank(results[0].concat(results[1]))}); } function fallbackCountyLookup(address){ var params=new URLSearchParams({q:address,limit:'1',bbox:'-83.5,32.0,-75.0,36.7',lang:'en'}); return fetch('https://photon.komoot.io/api/?'+params.toString(),{headers:{Accept:'application/json'}}).then(function(response){if(!response.ok)throw new Error('Fallback lookup unavailable');return response.json()}).then(function(data){ var feature=data.features&&data.features[0],p=feature&&feature.properties;if(!p)return null; var state=p.state==='North Carolina'?'NC':p.state==='South Carolina'?'SC':''; return state&&p.county?{county:p.county,state:state}:null; }); } function showResult(state,title,message,icon,canContinue){ result.removeAttribute('class'); result.hidden=true; result.replaceChildren(); var iconNode=document.createElement('span');iconNode.className='quote-area-result-icon';iconNode.setAttribute('aria-hidden','true');iconNode.textContent=icon; var copy=document.createElement('div'),heading=document.createElement('strong'),detail=document.createElement('p'); heading.textContent=title;detail.textContent=message;copy.append(heading,detail);result.append(iconNode,copy); continueButton.hidden=!canContinue; partnerButton.hidden=state!=='partner'; contactButton.hidden=state!=='outside'&&state!=='unavailable'; } function closeSuggestions(){list.hidden=true;list.replaceChildren();input.setAttribute('aria-expanded','false');input.removeAttribute('aria-activedescendant');suggestions=[];activeIndex=-1} function setActive(index){ var options=list.querySelectorAll('[role="option"]');if(!options.length)return; activeIndex=(index+options.length)%options.length; options.forEach(function(option,i){option.classList.toggle('is-active',i===activeIndex);option.setAttribute('aria-selected',i===activeIndex?'true':'false')}); input.setAttribute('aria-activedescendant',options[activeIndex].id);options[activeIndex].scrollIntoView({block:'nearest'}); } function renderSuggestions(items){ list.replaceChildren();suggestions=items;activeIndex=-1;if(!items.length){closeSuggestions();return} items.forEach(function(item,index){var option=document.createElement('button');option.type='button';option.id='quote-area-option-'+index;option.className='quote-area-option';option.setAttribute('role','option');option.setAttribute('aria-selected','false');option.textContent=item.label;option.addEventListener('mousedown',function(event){event.preventDefault()});option.addEventListener('click',function(){selectSuggestion(index)});list.append(option)}); list.hidden=false;input.setAttribute('aria-expanded','true'); } async function loadSuggestions(query){ if(controller)controller.abort();controller=new AbortController();loader.classList.add('is-visible'); try{var matches=await autocompleteLookup(query,controller.signal);if(fullAddress()===query)renderSuggestions(matches)} catch(error){if(error.name!=='AbortError')closeSuggestions()} finally{loader.classList.remove('is-visible')} } function countyFromMatch(match){var counties=match&&match.geographies&&match.geographies.Counties;return Array.isArray(counties)&&counties.length?(counties[0].NAME||counties[0].BASENAME||''):''} function stateFromMatch(match){var states=match&&match.geographies&&match.geographies.States;return Array.isArray(states)&&states.length?(states[0].STUSAB||states[0].NAME||''):''} function showCoverageResult(matchedAddress,county,state){ fillAddress(matchedAddress); var normalizedCounty=county.toLowerCase(); var countyLabel=formatCounty(county); var fullService=countyIn(fullServiceCounties,state,normalizedCounty); var limitedService=countyIn(limitedServiceCounties,state,normalizedCounty); var partnered=countyIn(partnerCounties,state,normalizedCounty); setPatrolAvailability(!limitedService); if(fullService){ var fullTitle='We service this area.';var fullMessage='Mobile Patrol, Armed and Unarmed Security, and Fire Watch are available in '+countyLabel+'.'; showResult('inside',fullTitle,fullMessage,'✓',true);openCoverageOutcome('inside',fullTitle,fullMessage,matchedAddress); }else if(limitedService){ var limitedTitle='We service this area with limited coverage.';var limitedMessage='Armed Security, Unarmed Security, and Fire Watch are available in '+countyLabel+'. Mobile Patrol is not currently available.'; showResult('limited',limitedTitle,limitedMessage,'!',true);openCoverageOutcome('limited',limitedTitle,limitedMessage,matchedAddress); }else if(partnered){ var partnerTitle='A regional provider serves this area.';var partnerMessage='Task Force Protection does not serve '+countyLabel+'. Piedmont Security & Company Police may provide service independently, subject to its availability and terms.'; showResult('partner',partnerTitle,partnerMessage,'↗',false);openCoverageOutcome('partner',partnerTitle,partnerMessage,matchedAddress); }else{ var outsideTitle='Service is not available at this address.';var outsideMessage=countyLabel+' is outside our current service area and is not covered by a regional partnership.'; showResult('outside',outsideTitle,outsideMessage,'–',false);openCoverageOutcome('outside',outsideTitle,outsideMessage,matchedAddress); } } async function checkAddress(address,hint){ closeSuggestions();setPatrolAvailability(true);continueButton.hidden=true;input.setAttribute('aria-busy','true');showResult('loading','Checking this property','Verifying the address and service county.','···',false); try{ var matchedAddress=address,county=hint&&hint.county||'',state=hint&&hint.state||''; if(!county||!state){ try{var matches=await lookup(address,true),match=matches[0];matchedAddress=match&&match.matchedAddress||address;county=countyFromMatch(match);state=stateFromMatch(match).toUpperCase()}catch(primaryError){} } if(!county||!state){try{var fallback=await fallbackCountyLookup(address);if(fallback){county=fallback.county;state=fallback.state}}catch(fallbackError){}} if(!county||!state){showResult('unknown','We could not verify that address','Enter the full street address, city, state and ZIP code, then try again.','?',false);return} showCoverageResult(matchedAddress,county,state); }catch(error){showResult('unavailable','The address checker is temporarily unavailable','We cannot confirm service availability right now. Please try again or call our main number for assistance.','?',false)} finally{input.removeAttribute('aria-busy')} } function selectSuggestion(index){var item=suggestions[index];if(!item)return;fillAddress(item.address);checkAddress(item.address,item)} function scheduleSuggestions(){window.clearTimeout(timer);continueButton.hidden=true;partnerButton.hidden=true;contactButton.hidden=true;var query=fullAddress();if(input.value.trim().length<4){closeSuggestions();return}timer=window.setTimeout(function(){loadSuggestions(query)},500)} function resetAddressStatus(){ window.clearTimeout(timer);if(controller)controller.abort();closeSuggestions();setPatrolAvailability(true); showResult('neutral','Check your service area','We currently provide standard service in five coastal Carolina counties.','⌖',false); } function clearDependentAddressFields(){cityInput.value='';stateInput.value='';zipInput.value='';resetAddressStatus()} function clearAddressDetails(){input.value='';clearDependentAddressFields()} function clearOnDeletion(event){ if(!event.inputType||event.inputType.indexOf('delete')!==0)return; if(event.currentTarget===input){clearDependentAddressFields();return} event.preventDefault();clearAddressDetails();input.focus(); } function handleAddressLineChange(){if(!input.value.trim()){clearAddressDetails();return}scheduleSuggestions()} [input,cityInput,zipInput].forEach(function(field){field.addEventListener('beforeinput',clearOnDeletion)}); input.addEventListener('input',handleAddressLineChange); input.addEventListener('search',handleAddressLineChange); input.addEventListener('change',function(){if(!input.value.trim())clearAddressDetails()}); cityInput.addEventListener('input',scheduleSuggestions); stateInput.addEventListener('change',function(){if(!stateInput.value){clearAddressDetails();input.focus();return}scheduleSuggestions()}); zipInput.addEventListener('input',scheduleSuggestions); input.addEventListener('keydown',function(event){if(event.key==='ArrowDown'&&!list.hidden){event.preventDefault();setActive(activeIndex+1)}else if(event.key==='ArrowUp'&&!list.hidden){event.preventDefault();setActive(activeIndex-1)}else if(event.key==='Enter'&&!list.hidden&&activeIndex>=0){event.preventDefault();selectSuggestion(activeIndex)}else if(event.key==='Escape')closeSuggestions()}); input.addEventListener('focus',function(){if(suggestions.length){list.hidden=false;input.setAttribute('aria-expanded','true')}}); document.addEventListener('click',function(event){if(!form.contains(event.target))closeSuggestions()}); form.addEventListener('submit',function(event){event.preventDefault();if(!form.reportValidity())return;checkAddress(fullAddress())}); continueButton.addEventListener('click',function(){ carryAddressToServices(); store.classList.add('address-confirmed');progressAddress.classList.remove('active');progressService.classList.add('active'); pageTitle.textContent='Choose your security service.';pageLede.textContent='Start with the protection your property needs. We’ll help you configure the coverage next.'; configurator.scrollIntoView({behavior:'smooth',block:'start'}); }); changeAddress.addEventListener('click',openAddressConfirm); })();