(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='
Security service
Service
Service planningBuilt around your propertyCoverage is reviewed before a formal proposal is prepared.
What’s included
';
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='
⌖
Property address
Change this property?
Changing the property address will restart the entire quote process. Your selected service, schedule, contact details, and estimate will be cleared.
Current property—
';
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);
})();