// Auto-reveal form and initialize Turnstile (function() { function revealFormAndInitTurnstile() { var wrapper = document.getElementById('gform_wrapper_1'); if (wrapper) { wrapper.style.removeProperty('display'); wrapper.style.setProperty('display', 'block', 'important'); wrapper.style.setProperty('visibility', 'visible', 'important'); wrapper.style.setProperty('opacity', '1', 'important'); }
if (window.gform) { window.gform.domLoaded = true; window.gform.scriptsLoaded = true; window.gform.themeScriptsLoaded = true; try { document.dispatchEvent(new Event('gform_main_scripts_loaded')); document.dispatchEvent(new Event('gform/theme/scripts_loaded')); } catch(e) {} }
var t = document.getElementById('cf-turnstile-gf-1'); if (t && window.turnstile && typeof window.turnstile.render === 'function') { if (!t.querySelector('iframe')) { try { window.turnstile.render(t, { sitekey: t.getAttribute('data-sitekey') || '0x4AAAAAAFKBt99W0mOQ3jYd', action: t.getAttribute('data-action') || 'gravity-form-1', callback: function(token) { if (typeof window.turnstileGravityCallback === 'function') { window.turnstileGravityCallback(token); } document.querySelectorAll('.gform_button').forEach(function(el) { el.style.pointerEvents = 'auto'; el.style.opacity = '1'; }); } }); } catch(err) {} } }
var btn = document.getElementById('gform_submit_button_1'); if (btn) { btn.style.pointerEvents = 'auto'; btn.style.opacity = '1'; } }
if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', revealFormAndInitTurnstile); } else { revealFormAndInitTurnstile(); } window.addEventListener('load', revealFormAndInitTurnstile); document.addEventListener('gform_post_render', revealFormAndInitTurnstile);
var attempts = 0; var interval = setInterval(function() { revealFormAndInitTurnstile(); attempts++; var t = document.getElementById('cf-turnstile-gf-1'); if ((t && t.querySelector('iframe')) || attempts > 25) { clearInterval(interval); } }, 200); })();
(function() { const DISPOSABLE_DOMAINS = new Set([ 'mailinator.com', 'tempmail.com', '10minutemail.com', 'guerrillamail.com', 'trashmail.com', 'yopmail.com', 'sharklasers.com', 'getnada.com', 'dispostable.com', 'throwawaymail.com', 'temp-mail.org', 'fakemailgenerator.com', 'maildrop.cc', 'inboxkitten.com', 'generator.email', 'crazymailing.com', 'mytemp.email', 'burnermail.io', 'mohmal.com', 'emailondeck.com', 'tempail.com', 'tempm.com', 'minuteinbox.com', 'guerrillamailblock.com', 'mailcatch.com', 'meltmail.com', 'spambox.us', 'trashmail.net', 'trashmail.me', 'jetable.org', 'incognitomail.org', 'fakeinbox.com', 'armyspy.com', 'cuvox.de', 'dayrep.com', 'fleckens.hu', 'gustr.com', 'jourrapide.com', 'rhyta.com', 'superrito.com', 'teleworm.us', 'tinypulse.top', 'temporary-mail.net', 'zillamail.com' ]);
const SPAM_PHRASES = [ 'wire transfer', 'western union', 'crypto investment', 'bitcoin profit', 'double your money', 'double your btc', 'lottery winner', 'claim your prize', 'inheritance fund', 'urgent assistance needed', 'million dollars usd', 'seo rank #1', 'first page of google', 'buy followers', 'viagra', 'cialis', 'adult dating', 'escort service', 'earn $5000 daily' ];
const SUSPICIOUS_HANDLES = new Set([ 'test', 'testing', 'fake', 'spam', 'scam', 'asdf', 'qwerty', '12345', '123456', 'noreply', 'no-reply', 'admin', 'root', 'null', 'sample' ]);
async function checkDomainMx(domain) { try { const controller = new AbortController(); const tid = setTimeout(() => controller.abort(), 3500); let res = null; try { res = await fetch('https://dns.google/resolve?name=' + encodeURIComponent(domain) + '&type=MX', { signal: controller.signal }); } catch(e) { res = await fetch('https://cloudflare-dns.com/dns-query?name=' + encodeURIComponent(domain) + '&type=MX', { headers: { 'Accept': 'application/dns-json' }, signal: controller.signal }); } clearTimeout(tid);
if (res && res.ok) { const data = await res.json(); if (data.Status === 3) return { exists: false, reason: 'The email domain "@' + domain + '" does not exist. Please check your spelling.' }; const hasMx = Array.isArray(data.Answer) && data.Answer.some(r => r.type === 15); if (hasMx) return { exists: true };
// Fallback check for A record try { const aResp = await fetch('https://dns.google/resolve?name=' + encodeURIComponent(domain) + '&type=A'); if (aResp.ok) { const aData = await aResp.json(); if (aData.Status === 3) return { exists: false, reason: 'The email domain "@' + domain + '" does not exist.' }; const hasA = Array.isArray(aData.Answer) && aData.Answer.some(r => r.type === 1); if (hasA) return { exists: true }; } } catch(e) {}
return { exists: false, reason: 'The email domain "@' + domain + '" cannot receive emails (no mail server found).' }; } } catch(err) { console.warn('DNS lookup skipped:', err); } return { exists: true }; }
function isValidPhoneNumber(phone) { phone = (phone || '').trim(); if (!phone) return true; if (/[^\d\+\-\(\)\.\s]/.test(phone)) return false; const digits = phone.replace(/\D/g, ''); const len = digits.length; if (len < 7 || len > 15) return false; if (/^(.)\1+$/.test(digits)) return false; const fakeSequences = ['1234567', '12345678', '123456789', '1234567890', '0123456', '01234567', '012345678', '0123456789', '9876543', '98765432', '987654321', '9876543210']; for (const seq of fakeSequences) { if (digits.includes(seq)) return false; } if (len === 10 || (len === 11 && digits[0] === '1')) { const nanp = (len === 11) ? digits.substring(1) : digits; if (nanp[0] === '0' || nanp[0] === '1') return false; if (nanp[3] === '0' || nanp[3] === '1') return false; if (nanp.substring(3, 6) === '555' && nanp.substring(6, 8) === '01') return false; } return true; }
function getFormElements() { const form = document.querySelector('.contact-form-floating-card form'); if (!form) return null; const emailInput = form.querySelector('input[type="email"]') || form.querySelector('input[name*="15"]'); const phoneInput = form.querySelector('input[type="tel"]') || form.querySelector('input[name*="16"]'); const nameInput = form.querySelector('input[name*="14"]') || form.querySelector('input[name*="name"]'); const messageInput = form.querySelector('textarea[name*="17"]') || form.querySelector('textarea'); const submitBtn = form.querySelector('input[type="submit"]') || form.querySelector('button[type="submit"]'); return { form, emailInput, phoneInput, nameInput, messageInput, submitBtn }; }
function clearCustomErrors(form) { if (!form) return; form.querySelectorAll('.has-validation-error').forEach(el => el.classList.remove('has-validation-error')); form.querySelectorAll('.gf-custom-error-msg').forEach(el => el.remove()); }
function showCustomError(inputEl, message) { if (!inputEl) return; const fieldWrap = inputEl.closest('.gfield') || inputEl.parentElement; if (fieldWrap) { fieldWrap.classList.add('has-validation-error'); let msgEl = fieldWrap.querySelector('.gf-custom-error-msg'); if (!msgEl) { msgEl = document.createElement('div'); msgEl.className = 'gf-custom-error-msg'; inputEl.parentElement.appendChild(msgEl); } msgEl.textContent = message; } inputEl.focus(); }
function attachListeners() { const els = getFormElements(); if (!els || !els.form || els.form.dataset.antiSpamBound === '1') return; els.form.dataset.antiSpamBound = '1';
if (els.emailInput) { els.emailInput.addEventListener('input', function() { const wrap = this.closest('.gfield'); if (wrap) { wrap.classList.remove('has-validation-error'); const msg = wrap.querySelector('.gf-custom-error-msg'); if (msg) msg.remove(); } }); }
if (els.phoneInput) { els.phoneInput.addEventListener('input', function() { const wrap = this.closest('.gfield'); if (wrap) { wrap.classList.remove('has-validation-error'); const msg = wrap.querySelector('.gf-custom-error-msg'); if (msg) msg.remove(); } }); }
if (els.submitBtn) { let isInternalValidationRunning = false;
els.submitBtn.addEventListener('click', async function(e) { if (isInternalValidationRunning) return;
const elements = getFormElements(); if (!elements || !elements.emailInput) return;
const email = (elements.emailInput.value || '').trim().toLowerCase(); const phone = elements.phoneInput ? (elements.phoneInput.value || '').trim() : ''; const name = elements.nameInput ? (elements.nameInput.value || '').trim() : ''; const message = elements.messageInput ? (elements.messageInput.value || '').trim() : '';
if (!email) return;
clearCustomErrors(elements.form);
// Validate Phone Number if provided if (phone && !isValidPhoneNumber(phone)) { e.preventDefault(); e.stopImmediatePropagation(); showCustomError(elements.phoneInput, 'Please enter a valid phone number (e.g. +1 954-708-2387).'); return; }
// 1. Structure & RFC Check const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/; if (!emailRegex.test(email)) { e.preventDefault(); e.stopImmediatePropagation(); showCustomError(elements.emailInput, 'Please enter a valid email address structure.'); return; }
const atIdx = email.lastIndexOf('@'); const localPart = email.substring(0, atIdx); const domain = email.substring(atIdx + 1);
// 2. Generic fake / placeholder handles if (SUSPICIOUS_HANDLES.has(localPart)) { e.preventDefault(); e.stopImmediatePropagation(); showCustomError(elements.emailInput, 'Generic or placeholder email addresses are not permitted.'); return; }
if (/^(.)\1{4,}@/.test(email)) { e.preventDefault(); e.stopImmediatePropagation(); showCustomError(elements.emailInput, 'Email contains invalid repetitive characters.'); return; }
// 3. Disposable & Burner Providers if (DISPOSABLE_DOMAINS.has(domain)) { e.preventDefault(); e.stopImmediatePropagation(); showCustomError(elements.emailInput, 'Disposable or burner emails are blocked. Please use a genuine email.'); return; }
// 4. Content Spam / Scam Check const fullText = (name + ' ' + message).toLowerCase(); for (const phrase of SPAM_PHRASES) { if (fullText.includes(phrase)) { e.preventDefault(); e.stopImmediatePropagation(); showCustomError(elements.messageInput || elements.emailInput, 'Message blocked by internal spam protection filters.'); return; } }
// 5. Asynchronous DNS MX check e.preventDefault(); e.stopImmediatePropagation();
isInternalValidationRunning = true; elements.submitBtn.classList.add('is-validating'); const originalVal = elements.submitBtn.value; elements.submitBtn.value = 'VERIFYING...';
try { const dns = await checkDomainMx(domain); if (!dns.exists) { isInternalValidationRunning = false; elements.submitBtn.classList.remove('is-validating'); elements.submitBtn.value = originalVal; showCustomError(elements.emailInput, dns.reason); return; }
// Passed all tests! Trigger native submission isInternalValidationRunning = false; elements.submitBtn.classList.remove('is-validating'); elements.submitBtn.value = originalVal;
if (typeof gform !== 'undefined' && gform.submission && gform.submission.handleButtonClick) { gform.submission.handleButtonClick(elements.submitBtn); } else { elements.form.submit(); } } catch(err) { isInternalValidationRunning = false; elements.submitBtn.classList.remove('is-validating'); elements.submitBtn.value = originalVal; elements.form.submit(); } }, true); } }
// Dynamically sync dark container minHeight with the floating card height so it never overlaps or clips function syncCardHeight() { const formCard = document.querySelector('.contact-form-floating-card'); const darkContainer = document.querySelector('.contact-card-container'); const wrapper = document.querySelector('.contact-section-wrapper'); if (!formCard || !darkContainer) return;
if (window.innerWidth <= 980) { darkContainer.style.minHeight = 'auto'; return; } const cardHeight = formCard.offsetHeight; const neededMinHeight = cardHeight + 40; if (neededMinHeight > 560) { darkContainer.style.minHeight = neededMinHeight + 'px'; if (wrapper) wrapper.style.marginBottom = '60px'; } else { darkContainer.style.minHeight = '560px'; } }
function initAll() { attachListeners(); syncCardHeight(); }
document.addEventListener('DOMContentLoaded', initAll); window.addEventListener('load', syncCardHeight); window.addEventListener('resize', syncCardHeight); document.addEventListener('gform_post_render', function() { attachListeners(); setTimeout(syncCardHeight, 60); });
const cardElement = document.querySelector('.contact-form-floating-card'); if (cardElement && window.MutationObserver) { new MutationObserver(syncCardHeight).observe(cardElement, { childList: true, subtree: true, attributes: true }); } })();