Files
dylanmazzei-website/static/assets/site.js
T
Alejandro Veras b2eff3d3be Only show the booking calendars after the lead form is sent
/contact/book/ now needs ?submitted=1 (set in the GHL form redirect) to load the
calendars; other visitors get a prompt that links to the form. The page is noindex
and out of the sitemap, the contact page card points to the form, and visitors are
sent back to the language they filled the form in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 13:16:14 -04:00

174 lines
7.1 KiB
JavaScript

(function () {
window.__site = true;
var root = document.documentElement;
// The booking page uses this to keep visitors in the language they filled the form in.
if (!/\/contact\/book\//.test(location.pathname)) { try { sessionStorage.setItem('dm-lang', root.lang || 'en'); } catch (e) {} }
// Translations for the current page's language, written into the page by the build.
var T = function (s) { return (window.__i18n && window.__i18n[s]) || s; };
var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
// Theme toggle: remembers the visitor's choice; otherwise follows the system.
var themeBtn = document.getElementById('theme-btn');
var current = function () { return root.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'; };
var paint = function () {
if (!themeBtn) return;
var dark = current() === 'dark';
themeBtn.setAttribute('aria-label', T(dark ? 'Switch to light mode' : 'Switch to dark mode'));
themeBtn.setAttribute('aria-pressed', String(dark));
};
var apply = function (t, save) {
root.setAttribute('data-theme', t);
if (save) { try { localStorage.setItem('theme', t); } catch (e) {} }
paint();
};
paint();
if (themeBtn) themeBtn.addEventListener('click', function () { apply(current() === 'dark' ? 'light' : 'dark', true); });
// Nav border on scroll
var nav = document.getElementById('nav');
var progress = document.getElementById('progress');
var onScroll = function () {
nav && nav.classList.toggle('is-scrolled', window.scrollY > 8);
if (progress) {
var max = Math.max(1, document.documentElement.scrollHeight - window.innerHeight);
progress.style.transform = 'scaleX(' + Math.min(1, Math.max(0, window.scrollY / max)) + ')';
}
};
onScroll();
window.addEventListener('scroll', onScroll, { passive: true });
// Mobile menu
var menuBtn = document.getElementById('menu-btn');
var menu = document.getElementById('mobile-menu');
if (menuBtn && menu) {
menuBtn.addEventListener('click', function () {
var open = menu.hidden;
menu.hidden = !open;
menuBtn.setAttribute('aria-expanded', String(open));
menuBtn.setAttribute('aria-label', T(open ? 'Close menu' : 'Open menu'));
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && !menu.hidden) { menu.hidden = true; menuBtn.setAttribute('aria-expanded', 'false'); menuBtn.focus(); }
});
}
// Reveal on scroll
var reveals = document.querySelectorAll('.reveal');
if ('IntersectionObserver' in window && !reduce) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) { en.target.classList.add('is-in'); io.unobserve(en.target); }
});
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.05 });
reveals.forEach(function (el) { io.observe(el); });
} else {
reveals.forEach(function (el) { el.classList.add('is-in'); });
}
// Count-up numbers: <b data-count="8" data-suffix="+">8+</b>
var counters = document.querySelectorAll('[data-count]');
var run = function (el) {
var end = parseInt(el.getAttribute('data-count'), 10);
var suffix = el.getAttribute('data-suffix') || '';
var start = null;
var dur = 1200;
var step = function (t) {
if (!start) start = t;
var p = Math.min((t - start) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
el.textContent = Math.round(end * eased) + suffix;
if (p < 1) requestAnimationFrame(step);
};
requestAnimationFrame(step);
};
if ('IntersectionObserver' in window && !reduce) {
var co = new IntersectionObserver(function (entries) {
entries.forEach(function (en) { if (en.isIntersecting) { run(en.target); co.unobserve(en.target); } });
}, { threshold: 0.6 });
counters.forEach(function (el) { co.observe(el); });
}
// Tabs (service lines)
document.querySelectorAll('[data-tabs]').forEach(function (wrap) {
var btns = wrap.querySelectorAll('[role="tab"]');
var panels = wrap.querySelectorAll('[role="tabpanel"]');
var select = function (i, focus) {
btns.forEach(function (b, j) {
var on = i === j;
b.setAttribute('aria-selected', String(on));
b.tabIndex = on ? 0 : -1;
panels[j].hidden = !on;
});
if (focus) btns[i].focus();
};
btns.forEach(function (b, i) {
b.addEventListener('click', function () { select(i); });
b.addEventListener('keydown', function (e) {
var k = e.key;
if (k === 'ArrowDown' || k === 'ArrowRight') { e.preventDefault(); select((i + 1) % btns.length, true); }
if (k === 'ArrowUp' || k === 'ArrowLeft') { e.preventDefault(); select((i - 1 + btns.length) % btns.length, true); }
});
});
var hash = location.hash.replace('#', '');
var start = 0;
panels.forEach(function (p, j) { if (p.id === hash) start = j; });
select(start);
});
// Copy buttons
document.querySelectorAll('[data-copy]').forEach(function (b) {
b.addEventListener('click', function () {
var text = b.getAttribute('data-copy');
var label = b.textContent;
var done = function () { b.textContent = T('Copied'); setTimeout(function () { b.textContent = label; }, 1600); };
try { navigator.clipboard.writeText(text).then(done, function () {}); } catch (e) {}
});
});
// Inquiry form: opens the visitor's email client with the message prefilled.
var form = document.getElementById('inquiry');
if (form) {
form.addEventListener('submit', function (e) {
e.preventDefault();
if (!form.reportValidity()) return;
var d = new FormData(form);
var body = [
'Name: ' + d.get('name'),
'Email: ' + d.get('email'),
d.get('company') ? 'Company: ' + d.get('company') : '',
d.get('topic') ? 'Topic: ' + d.get('topic') : '',
'',
d.get('message')
].filter(function (l, i) { return l !== '' || i === 4; }).join('\n');
var subject = 'Inquiry from ' + d.get('name') + (d.get('topic') ? ' — ' + d.get('topic') : '');
window.location.href = 'mailto:' + form.getAttribute('data-to') + '?subject=' + encodeURIComponent(subject) + '&body=' + encodeURIComponent(body);
var status = document.getElementById('form-status');
if (status) status.textContent = T('Your email app should open with the message ready to send.');
});
}
// GoHighLevel's form_embed.js hides each embed until the iframe reports it is
// ready. If that message never arrives, show the embed anyway so the form is
// never left invisible.
var reveal = function (f) {
f.style.opacity = '1';
f.style.visibility = 'visible';
f.style.pointerEvents = 'auto';
f.style.position = 'relative';
if (f.style.left === '-9999px') f.style.left = '';
};
var ghl = document.querySelectorAll('.ghl-frame');
if (ghl.length) {
[2500, 6000].forEach(function (ms) {
setTimeout(function () {
ghl.forEach(function (f) {
if (f.closest('[data-off]')) return;
if (getComputedStyle(f).visibility === 'hidden') reveal(f);
});
}, ms);
});
}
root.classList.add('ready');
})();