/* DVS Company — shared site JS (vanilla, no deps) */
(function () {
// ---------- Mobile nav ----------
const burger = document.querySelector('.burger');
const nav = document.querySelector('.nav');
if (burger && nav) {
burger.addEventListener('click', () => {
burger.classList.toggle('open');
nav.classList.toggle('open');
});
}
// ---------- Fade-up on scroll ----------
const observed = document.querySelectorAll('.fade-up');
if ('IntersectionObserver' in window && observed.length) {
const io = new IntersectionObserver(
(entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
e.target.classList.add('in');
io.unobserve(e.target);
}
});
},
{ rootMargin: '0px 0px -10% 0px', threshold: 0.05 }
);
observed.forEach((el) => io.observe(el));
} else {
observed.forEach((el) => el.classList.add('in'));
}
// ---------- Tweaks panel (host protocol) ----------
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"headingFont": "Inter Tight"
}/*EDITMODE-END*/;
const FONT_MAP = {
'Inter Tight': { stack: '"Inter Tight", "Helvetica Neue", Arial, sans-serif', google: 'Inter+Tight:wght@400;500;600;700' },
'Manrope': { stack: '"Manrope", "Helvetica Neue", Arial, sans-serif', google: 'Manrope:wght@400;500;600;700' },
'Fraunces': { stack: '"Fraunces", Georgia, serif', google: 'Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600' },
'Cormorant': { stack: '"Cormorant Garamond", Georgia, serif', google: 'Cormorant+Garamond:wght@400;500;600;700' },
'Playfair': { stack: '"Playfair Display", Georgia, serif', google: 'Playfair+Display:wght@400;500;600;700' },
'DM Serif': { stack: '"DM Serif Display", Georgia, serif', google: 'DM+Serif+Display' },
};
let state = { ...TWEAK_DEFAULTS };
const ensureFont = (key) => {
const meta = FONT_MAP[key];
if (!meta) return;
const id = 'gfont-' + key.replace(/\s+/g, '-');
if (document.getElementById(id)) return;
const link = document.createElement('link');
link.id = id;
link.rel = 'stylesheet';
link.href = `https://fonts.googleapis.com/css2?family=${meta.google}&display=swap`;
document.head.appendChild(link);
};
const applyState = (s) => {
const meta = FONT_MAP[s.headingFont] || FONT_MAP['Inter Tight'];
ensureFont(s.headingFont);
document.documentElement.style.setProperty('--font-heading', meta.stack);
};
applyState(state);
let panel;
const buildPanel = () => {
if (panel) return panel;
panel = document.createElement('div');
panel.className = 'dvs-tweaks';
panel.innerHTML = `
Heading font
${Object.keys(FONT_MAP).map((k) => `
`).join('')}
Adjusts every heading across the site.
`;
document.body.appendChild(panel);
panel.querySelector('.tw-close').addEventListener('click', () => {
panel.classList.remove('open');
window.parent.postMessage({ type: '__edit_mode_dismissed' }, '*');
});
panel.querySelectorAll('.tw-opt').forEach((btn) => {
btn.addEventListener('click', () => {
const key = btn.parentElement.dataset.key;
const val = btn.dataset.val;
panel.querySelectorAll(`[data-key="${key}"] .tw-opt`).forEach((b) => b.classList.remove('on'));
btn.classList.add('on');
state = { ...state, [key]: val };
applyState(state);
window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { [key]: val } }, '*');
});
});
return panel;
};
// Inject CSS for panel
const css = document.createElement('style');
css.textContent = `
.dvs-tweaks {
position: fixed;
right: 20px; bottom: 20px;
width: 280px;
background: #fff;
border: 1px solid var(--gray-line, #e4e4df);
border-radius: 12px;
box-shadow: 0 18px 40px rgba(14,42,74,0.18);
font-family: var(--font-body, system-ui);
z-index: 9999;
display: none;
overflow: hidden;
}
.dvs-tweaks.open { display: block; }
.tw-head {
display: flex; justify-content: space-between; align-items: center;
padding: 14px 18px;
border-bottom: 1px solid var(--gray-line, #e4e4df);
background: var(--navy, #0E2A4A);
color: #fff;
}
.tw-title {
font-family: var(--font-heading);
font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; font-weight: 600;
color: var(--gold, #C9A85C);
}
.tw-close { background: transparent; border: 0; color: #fff; font-size: 22px; cursor: pointer; line-height: 1; }
.tw-body { padding: 18px; }
.tw-section { display: grid; gap: 10px; }
.tw-label { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gray-mute, #8A8A85); font-weight: 600; font-family: var(--font-heading); }
.tw-options { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.tw-opt {
background: var(--gray-soft, #f2f2f0);
border: 1px solid transparent;
padding: 10px 12px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
color: var(--navy, #0E2A4A);
text-align: left;
transition: border-color .15s ease, background .15s ease;
}
.tw-opt:hover { border-color: var(--gold, #C9A85C); }
.tw-opt.on { background: var(--navy); color: #fff; border-color: var(--navy); }
.tw-hint { font-size: 12px; color: var(--gray-mute, #8A8A85); margin-top: 14px; font-family: var(--font-heading); }
`;
document.head.appendChild(css);
// Host protocol — register listener FIRST
window.addEventListener('message', (e) => {
const d = e.data || {};
if (d.type === '__activate_edit_mode') {
buildPanel().classList.add('open');
} else if (d.type === '__deactivate_edit_mode') {
if (panel) panel.classList.remove('open');
}
});
window.parent.postMessage({ type: '__edit_mode_available' }, '*');
})();