This Privacy Policy explains how First Coast Property Experts (“FCPE,” “we,” “us”) collects, uses, shares, and protects your information when you visit firstcoastpropertyexperts.com or use our services.
Last Updated: April 18, 2026
Information We Collect
We collect information in three ways — directly from you, automatically, and from service providers that help us operate our website.
- Contact & service details you provide: name, email, phone, address, service interests, project notes, and preferred schedule (e.g., via our request-a-quote form or by phone/text).
- Transactional & communication data: messages you send us, internal notes related to your project, appointment history, and correspondence (email/SMS/calls).
- Device & usage data: pages viewed, links clicked, approximate location, IP address, browser/OS, and referrer. Collected via cookies or similar technologies (see Cookies & Tracking).
- Media & reviews you share: testimonials, before/after photos, and ratings you authorize us to display.
Sensitive information is not required to receive a quote; please do not include payment card numbers or government IDs in free-text fields.
How We Use Information
- Provide quotes, schedule and deliver services, and manage client relationships.
- Communicate about appointments, updates, and service recommendations.
- Improve site performance, content, and user experience.
- Prevent fraud, secure our services, and comply with legal obligations.
- Show social proof (reviews/testimonials) with your permission.
How We Share Information
We do not sell personal information. We share limited data with trusted providers that help us run our business:
- Hosting & infrastructure: managed WordPress hosting and security (e.g., WP Engine) to deliver this site reliably.
- Analytics & performance: aggregated website analytics and CDN/WAF services to keep the site fast and secure.
- Forms, reviews & embeds: services that power forms, review widgets, and videos you play on our site.
- Professional services or legal compliance: if required by law or to protect our rights, users, or the public.
Service providers are bound by agreements to use information only for our instructions and to safeguard it appropriately.
Cookies & Tracking
We use first-party and third-party cookies to keep the site secure and understand how visitors use it.
- Strictly necessary: security, load balancing, and session continuity.
- Performance/analytics: anonymized insights into pages visited and general engagement.
- Preference: remembers choices like cookie dismissal.
Controls: You can accept, reject, or clear cookies via your browser settings. Blocking some cookies may affect site features.
Analytics & Embedded Content
Our pages may include analytics and embeds that set their own cookies when you view or interact:
Your Choices & Rights
Depending on your location (e.g., CA/VA/CO/CT/UT, EEA/UK), you may have rights to access, correct, delete, or receive a copy of your information, and to opt out of certain uses.
- Access/Portability: request a copy of the data we maintain about you.
- Correction: ask us to fix inaccuracies.
- Deletion: request deletion where allowed.
- Opt-out: we do not sell personal information; if we ever engage in cross-context interest-based advertising, you will have an opt-out.
We may ask you to verify your identity before fulfilling a request. Authorized agents can submit requests with proof of authorization.
How We Protect Information
- HTTPS/TLS encryption for data in transit.
- Hosting with modern security, backups, and firewall/WAF protections.
- Principle of least privilege for accounts and tools.
No system can be 100% secure. If you believe your information has been compromised, please contact us immediately.
Data Retention
We keep information only as long as needed for the purposes above and to meet legal/operational requirements. Typical durations:
- Quote & service records: ~3 years after last interaction (unless required longer for tax/accounting/claims).
- Website analytics: 14–26 months in aggregated form.
- Server/security logs: ~90–180 days.
Children’s Privacy
Our website and services are not directed to children under 13, and we do not knowingly collect information from them.
International Visitors
Our services are offered in the United States. If you access our site from outside the U.S., your information may be processed in the U.S., where data protection laws may differ. Where required, we rely on consent, contract necessity, or legitimate interests as lawful bases.
Do Not Track
Some browsers send a “Do Not Track” signal. Because there is no common industry standard for DNT, our site doesn’t respond to these signals. You can control cookies using your browser settings.
Third-Party Services We Use
Links above go to each provider’s privacy notice for transparency.
Your Privacy Choices (CCPA / CalOPPA)
California residents, and residents of states with similar privacy laws (Virginia, Colorado, Connecticut, Utah), have specific rights under their state privacy statutes. First Coast Property Experts does not sell or share personal information for cross-context behavioral advertising, and we have not done so in the past twelve months.
- Right to know what personal information we collect, use, and disclose.
- Right to delete personal information we hold about you.
- Right to correct inaccurate personal information.
- Right to opt out of the sale or sharing of personal information (not applicable — we don’t sell).
- Right to limit use of sensitive personal information.
- Right to non-discrimination for exercising any of these rights.
Do Not Sell My Personal Information: We do not sell your data. If you still wish to submit a formal request or exercise any privacy right, contact us using the actions below.
We respond to verified requests within 45 days (extendable by an additional 45 days where necessary). Authorized agents may submit requests with proof of authorization.
GDPR Courtesy Notice (EU / UK Visitors)
First Coast Property Experts does not target or market to residents of the European Economic Area (EEA) or the United Kingdom, and we do not offer our services outside the United States. As a matter of good-faith practice, we honor data-subject requests from EU/UK visitors who interact with our website.
- Lawful basis: legitimate interest (website operation and security), consent (marketing communications), and contract necessity (when you request an estimate or become a client).
- Your GDPR rights include: access, rectification, erasure, restriction, portability, objection, and the right to withdraw consent at any time.
- Data transfers: our website is hosted in the United States; if you access it from the EEA/UK, your information will be processed in the U.S.
- Supervisory authority: you have the right to lodge a complaint with your local data protection authority.
EU/UK data-subject requests: email info@firstcoastpropertyexperts.com with the subject line “GDPR Data Request.” We respond within 30 days.
Policy Updates
We may update this policy to reflect changes to our practices or for legal/operational reasons. We’ll revise the “Last updated” date and, if changes are material, we’ll provide a more prominent notice.
(function(){
function killRevealAnimations(){
document.querySelectorAll(‘.reveal’).forEach(function(el){
if(el.getAnimations){
el.getAnimations().forEach(function(a){a.cancel()});
}
el.removeAttribute(‘style’);
});
}
if(document.readyState===’loading’){
document.addEventListener(‘DOMContentLoaded’,function(){
killRevealAnimations();
setTimeout(killRevealAnimations,500);
setTimeout(killRevealAnimations,2000);
});
} else {
killRevealAnimations();
setTimeout(killRevealAnimations,500);
setTimeout(killRevealAnimations,2000);
}
/* Also kill animations when .is-visible is added (scroll reveal fires) */
if(typeof MutationObserver!==’undefined’){
var mo=new MutationObserver(function(mutations){
mutations.forEach(function(m){
if(m.type===’attributes’&&m.attributeName===’class’){
var el=m.target;
if(el.classList.contains(‘reveal’)&&el.classList.contains(‘is-visible’)){
if(el.getAnimations){
el.getAnimations().forEach(function(a){a.cancel()});
}
el.removeAttribute(‘style’);
}
}
});
});
function observeReveals(){
document.querySelectorAll(‘.reveal’).forEach(function(el){
mo.observe(el,{attributes:true,attributeFilter:[‘class’]});
});
}
if(document.readyState===’loading’){
document.addEventListener(‘DOMContentLoaded’,observeReveals);
} else {
observeReveals();
}
}
})();
/* ═══════════════════════════════════════════════════════════════════
FCPE MASTER SCRIPT — v1.0
Header interactivity + Premium luxury effects
═══════════════════════════════════════════════════════════════════ */
/* ─────────────────────────────────────────────────────────────────
SECTION 1: HEADER INTERACTIVITY
Mobile menu, mega dropdowns, scroll glass effect, sparkles
───────────────────────────────────────────────────────────────── */
function fcpeHdrInit(){
‘use strict’;
if(window._fcpeHdrDone)return true;window._fcpeHdrDone=true;
var wrap = document.querySelector(‘.fcpe-hdr-wrap’);
var hdr = document.querySelector(‘.fcpe-hdr’);
var burger = document.querySelector(‘.fcpe-hdr-burger’);
var panel = document.querySelector(‘.fcpe-hdr-panel’);
var overlay = document.querySelector(‘.fcpe-hdr-panel-overlay’);
if (!wrap || !hdr) return false;
/* Kill Elementor parent constraints */
(function(){
var el = wrap.parentElement;
while(el && el !== document.body){
el.style.background = ‘transparent’;
el.style.backgroundColor = ‘transparent’;
el.style.padding = ‘0’;
el.style.margin = ‘0’;
el.style.maxWidth = ‘none’;
el.style.overflow = ‘visible’;
el.style.border = ‘none’;
el.style.boxShadow = ‘none’;
el.style.minHeight = ‘0’;
el.style.transform = ‘none’;
el.style.webkitTransform = ‘none’;
el.style.willChange = ‘auto’;
el.style.filter = ‘none’;
el.style.perspective = ‘none’;
el.style.contain = ‘none’;
el.style.containerType = ‘normal’;
if(el.classList && (el.classList.contains(‘elementor-section’) || el.classList.contains(‘e-con’))) break;
el = el.parentElement;
}
if(el) el = el.parentElement;
while(el && el !== document.body){
el.style.transform = ‘none’;
el.style.webkitTransform = ‘none’;
el.style.willChange = ‘auto’;
el.style.filter = ‘none’;
el.style.perspective = ‘none’;
el.style.contain = ‘none’;
el.style.overflow = ‘visible’;
el = el.parentElement;
}
if(window.innerWidth 60);
ticking = false;
});
ticking = true;
}
}
window.addEventListener(‘scroll’, onScroll, { passive: true });
onScroll();
/* Desktop mega dropdowns */
var navItems = hdr.querySelectorAll(‘.fcpe-hdr-nav > li’);
var closeTimer = null;
navItems.forEach(function(item) {
var btn = item.querySelector(‘button’);
var mega = item.querySelector(‘.fcpe-hdr-mega’);
if (!btn || !mega) return;
function openMega() {
clearTimeout(closeTimer);
navItems.forEach(function(other) {
if (other !== item) {
other.classList.remove(‘fcpe-hdr-open’);
var ob = other.querySelector(‘button’);
if (ob) ob.setAttribute(‘aria-expanded’, ‘false’);
}
});
item.classList.add(‘fcpe-hdr-open’);
btn.setAttribute(‘aria-expanded’, ‘true’);
}
function closeMega() {
closeTimer = setTimeout(function() {
item.classList.remove(‘fcpe-hdr-open’);
btn.setAttribute(‘aria-expanded’, ‘false’);
}, 250);
}
item.addEventListener(‘mouseenter’, openMega);
item.addEventListener(‘mouseleave’, closeMega);
btn.addEventListener(‘click’, function(e) {
e.preventDefault();
if (item.classList.contains(‘fcpe-hdr-open’)) {
item.classList.remove(‘fcpe-hdr-open’);
btn.setAttribute(‘aria-expanded’, ‘false’);
} else {
openMega();
}
});
mega.addEventListener(‘mouseenter’, function() { clearTimeout(closeTimer); });
mega.addEventListener(‘mouseleave’, closeMega);
});
/* Close dropdowns on outside click */
document.addEventListener(‘click’, function(e) {
if (!hdr.contains(e.target)) {
navItems.forEach(function(item) {
item.classList.remove(‘fcpe-hdr-open’);
var b = item.querySelector(‘button’);
if (b) b.setAttribute(‘aria-expanded’, ‘false’);
});
}
});
/* Mobile hamburger */
function togglePanel() {
var isOpen = panel.classList.contains(‘fcpe-hdr-panel-open’);
panel.classList.toggle(‘fcpe-hdr-panel-open’);
overlay.classList.toggle(‘fcpe-hdr-panel-open’);
burger.classList.toggle(‘fcpe-hdr-active’);
burger.setAttribute(‘aria-expanded’, String(!isOpen));
burger.setAttribute(‘aria-label’, isOpen ? ‘Open menu’ : ‘Close menu’);
document.body.style.overflow = isOpen ? ” : ‘hidden’;
document.body.classList.toggle(‘fcpe-panel-is-open’, !isOpen);
}
var panelX = panel ? panel.querySelector(‘.fcpe-hdr-panel-x’) : null;
if (burger) {
burger.addEventListener(‘click’, function(e) {
e.stopPropagation();
togglePanel();
});
}
if (overlay) overlay.addEventListener(‘click’, togglePanel);
if (panelX) panelX.addEventListener(‘click’, togglePanel);
/* Mobile accordions */
var mnavBtns = panel ? panel.querySelectorAll(‘.fcpe-hdr-mnav > li > button’) : [];
mnavBtns.forEach(function(btn) {
btn.addEventListener(‘click’, function() {
var li = btn.parentElement;
var wasOpen = li.classList.contains(‘fcpe-hdr-mopen’);
panel.querySelectorAll(‘.fcpe-hdr-mnav > li’).forEach(function(item) {
item.classList.remove(‘fcpe-hdr-mopen’);
var b = item.querySelector(‘button’);
if (b) b.setAttribute(‘aria-expanded’, ‘false’);
});
if (!wasOpen) {
li.classList.add(‘fcpe-hdr-mopen’);
btn.setAttribute(‘aria-expanded’, ‘true’);
}
});
});
/* CTA Sparkle Magic */
var ctaBtn = document.querySelector(‘.fcpe-hdr-cta’);
if (ctaBtn && window.innerWidth > 980) {
var sparkleWrap = document.createElement(‘span’);
sparkleWrap.style.cssText = ‘position:absolute;inset:-8px;pointer-events:none;overflow:visible;z-index:0’;
ctaBtn.style.position = ‘relative’;
ctaBtn.appendChild(sparkleWrap);
function createSparkle() {
var s = document.createElement(‘span’);
var size = Math.random() * 4 + 2;
var x = Math.random() * 100;
var y = Math.random() * 100;
s.style.cssText = ‘position:absolute;width:’+size+’px;height:’+size+’px;’ +
‘background:radial-gradient(circle,#FFF8DC,#D4AF37);border-radius:50%;’ +
‘left:’+x+’%;top:’+y+’%;opacity:0;pointer-events:none;’ +
‘animation:fcpeSparkle ‘+(.6+Math.random()*.8)+’s ease-out forwards’;
sparkleWrap.appendChild(s);
setTimeout(function(){s.remove()}, 1400);
}
setInterval(function(){
if (document.visibilityState === ‘visible’) createSparkle();
}, 400);
ctaBtn.addEventListener(‘mouseenter’, function() {
for (var i = 0; i < 8; i++) {
setTimeout(createSparkle, i * 40);
}
});
var sparkleStyle = document.createElement('style');
sparkleStyle.textContent = '@keyframes fcpeSparkle{0%{opacity:0;transform:scale(0) translateY(0)}30%{opacity:1;transform:scale(1.2) translateY(-4px)}100%{opacity:0;transform:scale(0) translateY(-12px)}}';
document.head.appendChild(sparkleStyle);
}
/* Escape key closes everything */
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
navItems.forEach(function(item) {
item.classList.remove('fcpe-hdr-open');
var b = item.querySelector('button');
if (b) b.setAttribute('aria-expanded', 'false');
});
if (panel && panel.classList.contains('fcpe-hdr-panel-open')) {
togglePanel();
}
}
});
/* Sticky Floating Quote Button */
var stickyQuote = document.querySelector('.fcpe-hdr-sticky-quote');
if (stickyQuote && window.innerWidth showThreshold && !stickyVisible) {
stickyQuote.classList.add(‘fcpe-sticky-visible’);
stickyVisible = true;
} else if (scrollY <= showThreshold && stickyVisible) {
stickyQuote.classList.remove('fcpe-sticky-visible');
stickyVisible = false;
}
}, {passive: true});
}
return true;
}
/* Header init with retry */
function fcpeHdrInitOnce() {
if (window._fcpeHdrDone) return true;
var ok = fcpeHdrInit();
if (ok) window._fcpeHdrDone = true;
return ok;
}
if (!fcpeHdrInitOnce()) {
document.addEventListener('DOMContentLoaded', fcpeHdrInitOnce);
setTimeout(fcpeHdrInitOnce, 500);
setTimeout(fcpeHdrInitOnce, 1500);
}
/* ─────────────────────────────────────────────────────────────────
SECTION 2: PREMIUM EFFECTS (FIXED — with noReveal filter)
Lenis smooth scroll, GSAP reveals, gold particles,
before/after slider, 3D tilt, magnetic cursor, sticky nav,
CTA glow, horizontal scroll
NOTE: Uses _fcpeFixedPremiumDone guard (not _fcpePremiumDone)
so this ALWAYS runs even if the header template's broken copy
already executed. The CSS !important override above ensures
.reveal elements stay visible regardless.
───────────────────────────────────────────────────────────────── */
(function(){
'use strict';
if(window._fcpeFixedPremiumDone) return;
window._fcpeFixedPremiumDone=true;
var REDUCED=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
var IS_MOBILE=window.innerWidth0;
function ready(fn){
if(document.readyState!==’loading’) fn();
else document.addEventListener(‘DOMContentLoaded’,fn);
}
function waitForLib(name,cb,timeout){
timeout=timeout||8000;
var start=Date.now();
(function check(){
if(window[name]) return cb(window[name]);
if(Date.now()-start>timeout) return;
setTimeout(check,80);
})();
}
/* ═══════ 1. LENIS SMOOTH SCROLL ═══════ */
function initLenis(){
if(REDUCED) return;
waitForLib(‘Lenis’,function(Lenis){
var lenis=new Lenis({
duration:1.15,
easing:function(t){return Math.min(1,1.001-Math.pow(2,-10*t))},
orientation:’vertical’,
gestureOrientation:’vertical’,
smoothWheel:true,
touchMultiplier:1.5,
autoResize:true
});
waitForLib(‘ScrollTrigger’,function(ST){
lenis.on(‘scroll’,ST.update);
gsap.ticker.add(function(time){lenis.raf(time*1000)});
gsap.ticker.lagSmoothing(0);
});
if(!window.gsap){
function raf(time){lenis.raf(time);requestAnimationFrame(raf)}
requestAnimationFrame(raf);
}
document.querySelectorAll(‘a[href^=”#”]’).forEach(function(a){
a.addEventListener(‘click’,function(e){
var sel=this.getAttribute(‘href’);
if(!sel||sel.length<2) return;
var target=document.querySelector(sel);
if(!target) return;
e.preventDefault();
lenis.scrollTo(target,{offset:-80});
});
});
window._fcpeLenis=lenis;
});
}
/* ═══════ 2. GSAP CINEMATIC REVEALS (FIXED) ═══════
IMPORTANT: Skip elements with .reveal class — those already have
their own CSS IntersectionObserver system. GSAP inline styles
(opacity:0) would override the CSS and make cards invisible.
Also cleans up any broken GSAP animations from the header template. */
function initGSAPReveals(){
if(REDUCED) return;
waitForLib('gsap',function(){
waitForLib('ScrollTrigger',function(ST){
gsap.registerPlugin(ST);
/* ── CLEANUP: Remove broken GSAP inline styles from .reveal elements ──
The header template's unfixed premium effects JS may have already run
gsap.from({opacity:0}) on .reveal elements, setting inline opacity:0
that overrides the CSS animation system. Clean that up now. */
document.querySelectorAll('.reveal').forEach(function(el){
if(typeof gsap.killTweensOf==='function') gsap.killTweensOf(el);
el.style.removeProperty('opacity');
el.style.removeProperty('transform');
el.style.removeProperty('translate');
el.style.removeProperty('rotate');
el.style.removeProperty('scale');
});
/* Helper: filter out elements that use the .reveal CSS system */
function noReveal(els){
return Array.prototype.filter.call(els,function(el){
return !el.classList.contains('reveal');
});
}
/* Section headers stagger (skip if .reveal) */
document.querySelectorAll('.section-header').forEach(function(header){
var children=noReveal(header.children);
if(!children.length) return;
gsap.from(children,{
y:32,opacity:0,duration:.7,
stagger:.12,ease:'power2.out',
scrollTrigger:{trigger:header,start:'top 82%',toggleActions:'play none none none'}
});
});
/* Service cards stagger cascade (skip if .reveal) */
document.querySelectorAll('.service-grid,.trust-grid,.testimonials-grid,.gold-standard__pillars').forEach(function(grid){
var items=noReveal(grid.children);
if(!items.length) return;
gsap.from(items,{
y:48,opacity:0,duration:.65,
stagger:{each:.1,from:'start'},ease:'power2.out',
scrollTrigger:{trigger:grid,start:'top 78%',toggleActions:'play none none none'}
});
});
/* Gold rules grow from center (skip if .reveal) */
document.querySelectorAll('.gold-rule').forEach(function(rule){
if(rule.classList.contains('reveal')) return;
gsap.from(rule,{
scaleX:0,duration:.85,ease:'power2.out',
scrollTrigger:{trigger:rule,start:'top 88%',toggleActions:'play none none none'}
});
});
/* Cert badges cascade (skip if .reveal) */
var certBadges=document.querySelector('.cert-badges');
if(certBadges){
var badges=noReveal(certBadges.children);
if(badges.length){
gsap.from(badges,{
y:20,opacity:0,duration:.55,stagger:.08,ease:'power2.out',
scrollTrigger:{trigger:certBadges,start:'top 85%',toggleActions:'play none none none'}
});
}
}
/* Stats bar items (skip if .reveal) */
document.querySelectorAll('.stats-bar__item').forEach(function(item,i){
if(item.classList.contains('reveal')) return;
gsap.from(item,{
y:24,opacity:0,duration:.6,delay:i*.12,ease:'power2.out',
scrollTrigger:{trigger:item,start:'top 88%',toggleActions:'play none none none'}
});
});
/* Gift band entrance (skip if .reveal) */
var giftBand=document.querySelector('.gift-band');
if(giftBand && !giftBand.classList.contains('reveal')){
gsap.from(giftBand,{
y:40,opacity:0,scale:.97,duration:.8,ease:'power2.out',
scrollTrigger:{trigger:giftBand,start:'top 80%',toggleActions:'play none none none'}
});
}
/* God Standard badge + copy */
var godBadge=document.querySelector('.gold-standard__badge');
var godCopy=document.querySelector('.gold-standard__copy');
if(godBadge && !godBadge.classList.contains('reveal')){
gsap.from(godBadge,{
x:-60,opacity:0,rotation:-5,duration:.9,ease:'power2.out',
scrollTrigger:{trigger:godBadge,start:'top 78%',toggleActions:'play none none none'}
});
}
if(godCopy){
var copyKids=noReveal(godCopy.children);
if(copyKids.length){
gsap.from(copyKids,{
x:40,opacity:0,duration:.65,stagger:.12,ease:'power2.out',
scrollTrigger:{trigger:godCopy,start:'top 78%',toggleActions:'play none none none'}
});
}
}
});
});
}
/* ═══════ 3. GOLD PARTICLE ATMOSPHERE ═══════ */
function initParticles(){
if(REDUCED||IS_MOBILE) return;
var canvas=document.createElement('canvas');
canvas.className='fcpe-particles-canvas';
canvas.setAttribute('aria-hidden','true');
document.body.appendChild(canvas);
var ctx=canvas.getContext('2d');
var particles=[];
var PARTICLE_COUNT=22;
var dpr=window.devicePixelRatio||1;
function resize(){
canvas.width=window.innerWidth*dpr;
canvas.height=window.innerHeight*dpr;
canvas.style.width=window.innerWidth+'px';
canvas.style.height=window.innerHeight+'px';
ctx.scale(dpr,dpr);
}
resize();
window.addEventListener('resize',resize,{passive:true});
for(var i=0;i<PARTICLE_COUNT;i++){
particles.push({
x:Math.random()*window.innerWidth,
y:Math.random()*window.innerHeight,
size:Math.random()*1.8+0.5,
speedX:(Math.random()-0.5)*0.4,
speedY:(Math.random()-0.5)*0.3-0.15,
opacity:Math.random()*0.5+0.15,
pulse:Math.random()*Math.PI*2,
pulseSpeed:Math.random()*0.008+0.003
});
}
var running=true;
function draw(){
if(!running) return;
ctx.clearRect(0,0,window.innerWidth,window.innerHeight);
particles.forEach(function(p){
p.x+=p.speedX;p.y+=p.speedY;p.pulse+=p.pulseSpeed;
if(p.xwindow.innerWidth+10) p.x=-10;
if(p.ywindow.innerHeight+10) p.y=-10;
var op=p.opacity*(0.5+0.5*Math.sin(p.pulse));
ctx.beginPath();ctx.arc(p.x,p.y,p.size*3,0,Math.PI*2);
ctx.fillStyle=’rgba(212,170,55,’+op*0.15+’)’;ctx.fill();
ctx.beginPath();ctx.arc(p.x,p.y,p.size,0,Math.PI*2);
ctx.fillStyle=’rgba(245,223,162,’+op+’)’;ctx.fill();
});
requestAnimationFrame(draw);
}
document.addEventListener(‘visibilitychange’,function(){
if(document.hidden){running=false}
else{running=true;requestAnimationFrame(draw)}
});
requestAnimationFrame(draw);
}
/* ═══════ 4. BEFORE/AFTER SLIDER (dormant — activates when HTML exists) ═══════ */
function initBASliders(){
document.querySelectorAll(‘.fcpe-ba-slider’).forEach(function(slider){
var afterImg=slider.querySelector(‘.fcpe-ba-after’);
var handle=slider.querySelector(‘.fcpe-ba-handle’);
if(!afterImg||!handle) return;
var isDragging=false;
function setPosition(x){
var rect=slider.getBoundingClientRect();
var pct=Math.max(0,Math.min(1,(x-rect.left)/rect.width));
var percent=pct*100;
afterImg.style.clipPath=’inset(0 0 0 ‘+percent+’%)’;
handle.style.left=percent+’%’;
}
function onStart(e){
isDragging=true;
var x=e.touches?e.touches[0].clientX:e.clientX;
setPosition(x);
}
function onMove(e){
if(!isDragging) return;
e.preventDefault();
var x=e.touches?e.touches[0].clientX:e.clientX;
setPosition(x);
}
function onEnd(){isDragging=false}
slider.addEventListener(‘mousedown’,onStart);
slider.addEventListener(‘touchstart’,onStart,{passive:true});
window.addEventListener(‘mousemove’,onMove);
window.addEventListener(‘touchmove’,onMove,{passive:false});
window.addEventListener(‘mouseup’,onEnd);
window.addEventListener(‘touchend’,onEnd);
});
}
/* ═══════ 5. 3D TILT SERVICE CARDS ═══════ */
function initTiltCards(){
if(IS_TOUCH||IS_MOBILE) return;
document.querySelectorAll(‘.fcpe-card,.trust-card,.testimonial-card’).forEach(function(card){
var parent=card.parentElement;
if(parent) parent.classList.add(‘fcpe-tilt-active’);
var glow=document.createElement(‘div’);
glow.className=’fcpe-card-glow’;
card.style.position=’relative’;
card.appendChild(glow);
card.addEventListener(‘mousemove’,function(e){
var rect=card.getBoundingClientRect();
var x=(e.clientX-rect.left)/rect.width;
var y=(e.clientY-rect.top)/rect.height;
var tiltX=(y-0.5)*-8;
var tiltY=(x-0.5)*8;
card.style.transform=’perspective(800px) rotateX(‘+tiltX+’deg) rotateY(‘+tiltY+’deg) scale(1.02)’;
glow.style.background=’radial-gradient(circle at ‘+x*100+’% ‘+y*100+’%, rgba(212,170,55,.25), transparent 55%)’;
});
card.addEventListener(‘mouseleave’,function(){
card.style.transform=’perspective(800px) rotateX(0) rotateY(0) scale(1)’;
glow.style.background=’none’;
});
});
}
/* ═══════ 6. MAGNETIC CURSOR ═══════ */
function initMagneticCursor(){
if(IS_TOUCH||IS_MOBILE||REDUCED) return;
var cursor=document.createElement(‘div’);
cursor.className=’fcpe-mag-cursor’;
cursor.setAttribute(‘aria-hidden’,’true’);
document.body.appendChild(cursor);
var mouseX=0,mouseY=0,cursorX=0,cursorY=0,isVisible=false;
document.addEventListener(‘mousemove’,function(e){
mouseX=e.clientX;mouseY=e.clientY;
if(!isVisible){isVisible=true;cursor.classList.add(‘is-active’)}
},{passive:true});
document.addEventListener(‘mouseleave’,function(){
isVisible=false;cursor.classList.remove(‘is-active’);
});
function updateCursor(){
cursorX+=(mouseX-cursorX)*0.15;
cursorY+=(mouseY-cursorY)*0.15;
cursor.style.left=cursorX+’px’;
cursor.style.top=cursorY+’px’;
requestAnimationFrame(updateCursor);
}
requestAnimationFrame(updateCursor);
document.querySelectorAll(‘.btn–gold,.btn–ghost,.fcpe-card’).forEach(function(el){
el.addEventListener(‘mouseenter’,function(){
cursor.classList.add(el.classList.contains(‘btn–gold’)?’is-cta’:’is-hover’);
});
el.addEventListener(‘mouseleave’,function(){
cursor.classList.remove(‘is-hover’,’is-cta’);
});
if(el.classList.contains(‘btn–gold’)||el.classList.contains(‘btn–ghost’)){
el.addEventListener(‘mousemove’,function(e){
var rect=el.getBoundingClientRect();
var dx=(e.clientX-(rect.left+rect.width/2))*0.2;
var dy=(e.clientY-(rect.top+rect.height/2))*0.2;
el.style.transform=’translate(‘+dx+’px,’+dy+’px)’;
});
el.addEventListener(‘mouseleave’,function(){el.style.transform=”});
}
});
}
/* ═══════ 7. STICKY GLASSMORPHISM NAV ═══════ */
function initStickyNav(){
var chips=document.querySelectorAll(‘.anchor-chip[data-target]’);
if(!chips.length) return;
var stickyNav=document.createElement(‘div’);
stickyNav.className=’fcpe-sticky-nav’;
stickyNav.setAttribute(‘aria-label’,’Section navigation’);
chips.forEach(function(chip){
var a=document.createElement(‘a’);
a.href=chip.getAttribute(‘href’);
a.textContent=chip.textContent;
a.setAttribute(‘data-target’,chip.getAttribute(‘data-target’)||”);
stickyNav.appendChild(a);
});
document.body.appendChild(stickyNav);
var anchorSection=document.querySelector(‘.anchors’);
if(!anchorSection) return;
var showThreshold=anchorSection.getBoundingClientRect().bottom+window.scrollY+50;
var isShowing=false;
function checkScroll(){
var sy=window.scrollY||window.pageYOffset;
if(sy>showThreshold&&!isShowing){stickyNav.classList.add(‘is-visible’);isShowing=true}
else if(sy<=showThreshold&&isShowing){stickyNav.classList.remove('is-visible');isShowing=false}
}
window.addEventListener('scroll',checkScroll,{passive:true});
checkScroll();
if('IntersectionObserver' in window){
var stickyLinks=stickyNav.querySelectorAll('a[data-target]');
var obs=new IntersectionObserver(function(entries){
entries.forEach(function(entry){
if(entry.isIntersecting){
var id=entry.target.getAttribute('id');
stickyLinks.forEach(function(link){
link.classList.toggle('is-active',link.getAttribute('data-target')===id);
});
}
});
},{threshold:.1,rootMargin:'-80px 0px -55% 0px'});
stickyLinks.forEach(function(link){
var t=link.getAttribute('data-target');
if(t){var sec=document.getElementById(t);if(sec)obs.observe(sec)}
});
}
stickyNav.querySelectorAll('a').forEach(function(a){
a.addEventListener('click',function(e){
var sel=this.getAttribute('href');
if(!sel||sel.length<2||sel.indexOf('#')!==0) return;
var target=document.querySelector(sel);
if(!target) return;
e.preventDefault();
if(window._fcpeLenis){window._fcpeLenis.scrollTo(target,{offset:-80})}
else{target.scrollIntoView({behavior:'smooth',block:'start'})}
});
});
}
/* ═══════ 8. CTA GLOW PULSE ═══════ */
function initCTAGlow(){
if(REDUCED) return;
document.querySelectorAll('.btn–gold').forEach(function(btn){
btn.classList.add('fcpe-glow-pulse');
});
}
/* ═══════ 9. HORIZONTAL SCROLL (for .fcpe-hscroll-wrap) ═══════ */
function initHorizontalScroll(){
if(REDUCED) return;
var wraps=document.querySelectorAll('.fcpe-hscroll-wrap');
if(!wraps.length) return;
waitForLib('gsap',function(){
waitForLib('ScrollTrigger',function(ST){
gsap.registerPlugin(ST);
wraps.forEach(function(wrap){
var track=wrap.querySelector('.fcpe-hscroll-track');
if(!track) return;
var totalWidth=track.scrollWidth-wrap.offsetWidth;
gsap.to(track,{x:-totalWidth,ease:'none',
scrollTrigger:{trigger:wrap,pin:true,scrub:1,
start:'center center',end:'+='+totalWidth,invalidateOnRefresh:true}
});
});
});
});
}
/* ═══════ INIT ALL ═══════ */
ready(function(){
initLenis();
initGSAPReveals();
initParticles();
initBASliders();
initTiltCards();
initMagneticCursor();
initStickyNav();
initCTAGlow();
initHorizontalScroll();
});
})();
/* Hide the WordPress theme page-title H1 on all FCPE pages.
Our content already has its own H1; the theme’s entry-title creates
a duplicate H1 (bad for SEO). Targets GeneratePress/Astra page-header. */
.page-header { display: none !important; }