/* 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 = `
Tweaks
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' }, '*'); })();