State Chamber Live HHS Region 8 FEMA Region VIII Census West

Utah Chamber of Health™

From the Wasatch Front to red rock country. One State Chamber, three Super-Regions, and nine sub-chambers activating communities across 29 counties and 3.5 million Utahns.

3
Super-Regions
9
Sub-Chambers
29
Counties
3.5M
Population
Super-Region Chambers

Three Utahs. One Chamber.

Utah is organized into three Super-Region Chambers, each pairing a metro with its adjacent rural and frontier zones. Click any Super-Region to drill in.

Northern Utah & Cache Valley

Northern UT Chamber of Health™

6 counties · ~280k population
Logan-Cache MetroMetro
Park City · Wasatch BackResort & Rural
Bear River FrontierFrontier
PHIT™ Score71Strong
Open Northern UT →
Southern & Eastern Utah

Southern & Eastern UT Chamber of Health™

17 counties · ~520k population
Greater St. George MetroMetro
Four Corners Rural (Moab · Blanding)Rural Zone
Uintah Basin & Carbon FrontierFrontier
PHIT™ Score63At Risk
Open Southern & Eastern UT →
PHIT™ Systems Snapshot

Utah by the numbers.

Population Health Intelligence Tracker (PHIT™) — the five-component composite that powers every Utah Chamber of Health activation, refreshed quarterly.

Health Literacy Index
78
+4 YoY
FFH Academy assessments
Daily Action Consistency
71
+6 YoY
LIVE It Tracker streaks
Community Activation Rate
68
+9 YoY
SHARE It pledges & events
Workforce Wellness Index
74
flat
Employer cohort panels
Rural Access Equity
61
-2 YoY
Frontier zone delta vs metro
Foundational Partner Opportunity

Become the Founding Partner of the Utah Chamber of Health™.

Utah is WCF Insurance's home state. Anchoring the Utah Chamber of Health as Foundational Partner puts WCF's "People Matter"™ promise at the center of community health activation across all 29 counties.

What Foundational Partnership Activates

For an aligned $25,000 partnership matching the Arizona pilot, a Foundational Partner anchors the entire Utah Chamber of Health and gets:

  • Founding Partner naming on every Utah Chamber activation, statewide
  • 5 high school STEAM teams across the Wasatch Front, Northern UT, and Southern & Eastern UT
  • 1 inaugural Utah Chamber of Health convening (Salt Lake or HQ-adjacent venue, your call)
  • Capital Command Center reporting on every dollar — tied to PHIT lift, students reached, and employer cohort engagement
  • First seat at the Utah Director's Table — the policy/strategy convener for state-level public health leaders
  • Right of first refusal on Phase 2 expansion across the remaining four WCF states
$25,000
Foundational Partner · Utah
Same number as Arizona — deliberately. This is the head-to-head pairing that lets WCF anchor both AZ (largest growth opportunity) and UT (your home state) in a single coordinated launch.
View the Full WCF Pitch →

Anchor Partners & Aligned Convenings

WCF Insurance · Founding Partner Candidate
Utah Department of Health & Human Services
Intermountain Health
University of Utah Health
Utah Hospital Association
Utah State Board of Education
Activation Roadmap

What's launching in Year 1.

Phase 1 deliverables for any Foundational Partner who anchors the Utah Chamber in 2026.

STEAM Teams

5 Statewide STEAM Teams

Health-literacy + STEAM-integrated programs at 5 high schools across the three Super-Regions, with full FFH Academy access.

Wasatch Front (2) · Northern (1) · Southern & Eastern (2)
Director's Table

Inaugural Utah Convening

Founding statewide convening of public health, healthcare, education, and employer leaders to set the Utah Chamber's first-year priorities.

Q3 2026 · Salt Lake area · Founding Partner naming
Reality Health Games

Wasatch Prevention Bingo Pilot

Cardiovascular and Mental Health bingo cards rolled out across employer cohorts, with the Founding Partner branded into the engagement layer.

Q4 2026 · Employer cohort launch
PHIT Reporting

Quarterly Utah PHIT™ Brief

Branded quarterly intelligence report for Founding Partner: state PHIT trends, super-region deltas, and outcome attribution.

Quarterly · Capital Command Center dashboard
Get Involved

Three doors into the Utah Chamber.

Whether you're a foundational partner, a healthcare or education leader, or a Utahn who wants to live healthier — there's a way in.

Sponsor

Become a Foundational Partner

Anchor the Utah Chamber and put your "People Matter" promise to work across all 29 counties.

$25K/year · Founding Partner level
Director

Apply to the Utah Director's Table

Public health, healthcare, education, employer, and Tribal nation leaders convene quarterly to drive Utah Chamber priorities.

By application · Quarterly cadence
Citizen

Join the Utah Chamber as a Member

Earn PHIT points through the Force for Health Academy — Learn It, Live It, Share It across all your favorite body systems.

Free · Open to all Utahns
* to any FFH page. No other changes required. * * Edit-mode triggers (any one will activate): * - URL contains ?edit=1 or #edit * - localStorage 'ffh_edit_mode' === 'on' (persists across page loads) * - Click the floating toggle button * * Author: Coach Lucy + Claude * Version: 1.0 (2026-04-25) * ────────────────────────────────────────────────────────────────────────── */ (function() { 'use strict'; // Avoid double-loading if (window.__FFH_EDITOR_LOADED__) return; window.__FFH_EDITOR_LOADED__ = true; // ── State ────────────────────────────────────────────────────────────── var STORE_KEY_MODE = 'ffh_edit_mode'; var STORE_KEY_EDITS = 'ffh_pending_edits'; var pendingEdits = []; // {before, after, tag, snippet} var editMode = false; var currentEditEl = null; var currentBeforeText = null; // Page metadata — try hard to figure out the source file path function getPageMeta() { var path = window.location.pathname; // Strip trailing slashes / index.html var clean = path.replace(/index\.html$/i, '').replace(/\/$/, '') || '/'; // Best-guess source file path inside Deploy Ready var slug = clean.replace(/^\//, '').replace(/\/$/, '') || 'index'; return { url: clean, sourceFile: 'Deploy Ready/' + slug + '/index.html', title: document.title || 'FFH Page' }; } // ── Mode detection ───────────────────────────────────────────────────── function detectModeFromURL() { var qs = window.location.search; var hash = window.location.hash; if (qs.indexOf('edit=1') !== -1) return true; if (hash.indexOf('edit') !== -1) return true; return null; // null = use stored value } function loadEditMode() { var fromUrl = detectModeFromURL(); if (fromUrl !== null) return fromUrl; return localStorage.getItem(STORE_KEY_MODE) === 'on'; } function saveEditMode(on) { if (on) localStorage.setItem(STORE_KEY_MODE, 'on'); else localStorage.removeItem(STORE_KEY_MODE); } function loadPendingEdits() { try { var raw = localStorage.getItem(STORE_KEY_EDITS); return raw ? JSON.parse(raw) : []; } catch (e) { return []; } } function savePendingEdits() { try { localStorage.setItem(STORE_KEY_EDITS, JSON.stringify(pendingEdits)); } catch (e) { /* ignore quota */ } } // ── Styles ───────────────────────────────────────────────────────────── function injectStyles() { if (document.getElementById('ffh-editor-styles')) return; var css = ` .ffh-edit-toggle { position: fixed; bottom: 18px; right: 18px; z-index: 9999; background: #0f2044; color: #fff; border: 2px solid #fff; border-radius: 28px; padding: 10px 18px; font-size: 13px; font-weight: 700; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; box-shadow: 0 6px 20px rgba(15,32,68,.35); cursor: pointer; transition: all .2s; display: flex; align-items: center; gap: 8px; } .ffh-edit-toggle:hover { background: #e8450a; transform: translateY(-2px); } .ffh-edit-toggle.on { background: #16a34a; border-color: #fff; } .ffh-edit-toggle.on:hover { background: #dc2626; } .ffh-edit-banner { position: fixed; top: 0; left: 0; right: 0; z-index: 9998; background: linear-gradient(135deg, #16a34a 0%, #0f766e 100%); color: #fff; text-align: center; padding: 6px 12px; font-size: 12px; font-weight: 700; font-family: -apple-system, sans-serif; letter-spacing: .04em; box-shadow: 0 2px 10px rgba(0,0,0,.2); } body.ffh-edit-on { padding-top: 28px !important; } /* Hover highlight + pencil */ .ffh-editable-hover { outline: 2px dashed rgba(232, 69, 10, .55) !important; outline-offset: 3px !important; cursor: pointer !important; position: relative !important; } .ffh-pencil-btn { position: absolute; top: -10px; right: -10px; z-index: 100; width: 28px; height: 28px; border-radius: 50%; background: #e8450a; color: #fff; border: 2px solid #fff; box-shadow: 0 2px 8px rgba(0,0,0,.25); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 14px; line-height: 1; transition: transform .15s; } .ffh-pencil-btn:hover { transform: scale(1.12); background: #c73a08; } /* In-place editing */ .ffh-editing { outline: 3px solid #16a34a !important; outline-offset: 4px !important; background: rgba(22, 163, 74, .07) !important; cursor: text !important; } .ffh-edit-toolbar { position: absolute; background: #0f2044; color: #fff; border-radius: 8px; padding: 4px; box-shadow: 0 6px 18px rgba(0,0,0,.25); display: flex; gap: 4px; z-index: 9997; font-family: -apple-system, sans-serif; } .ffh-edit-toolbar button { background: transparent; border: none; color: #fff; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit; } .ffh-edit-toolbar button.save { background: #16a34a; } .ffh-edit-toolbar button.save:hover { background: #15803d; } .ffh-edit-toolbar button.cancel { background: #dc2626; } .ffh-edit-toolbar button.cancel:hover { background: #b91c1c; } /* Edits panel (bottom-right above toggle) */ .ffh-edits-panel { position: fixed; bottom: 76px; right: 18px; z-index: 9996; width: 360px; max-height: 60vh; background: #fff; border: 2px solid #0f2044; border-radius: 14px; box-shadow: 0 12px 32px rgba(15,32,68,.3); font-family: -apple-system, sans-serif; display: none; flex-direction: column; overflow: hidden; } .ffh-edits-panel.open { display: flex; } .ffh-edits-panel-header { background: #0f2044; color: #fff; padding: 12px 16px; display: flex; align-items: center; justify-content: space-between; } .ffh-edits-panel-header h4 { margin: 0; font-size: 14px; font-weight: 800; color: #fff; } .ffh-edits-panel-count { background: #e8450a; color: #fff; border-radius: 12px; padding: 2px 10px; font-size: 11px; font-weight: 800; } .ffh-edits-panel-list { flex: 1; overflow-y: auto; padding: 8px 12px; } .ffh-edit-row { background: #f4f6fa; border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px 12px; margin-bottom: 8px; font-size: 12px; color: #0f2044; position: relative; } .ffh-edit-row .row-tag { font-size: 9px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: #6b7a99; margin-bottom: 4px; } .ffh-edit-row .row-before, .ffh-edit-row .row-after { background: #fff; border: 1px solid #e2e8f0; border-radius: 4px; padding: 4px 8px; margin-bottom: 4px; font-family: ui-monospace, 'SF Mono', monospace; font-size: 11px; overflow-wrap: break-word; word-break: break-word; line-height: 1.35; } .ffh-edit-row .row-after { background: #dcfce7; border-color: #86efac; } .ffh-edit-row .row-before { background: #fee2e2; border-color: #fca5a5; } .ffh-edit-row .row-remove { position: absolute; top: 4px; right: 4px; background: transparent; border: none; color: #dc2626; cursor: pointer; font-size: 14px; padding: 4px; border-radius: 4px; } .ffh-edit-row .row-remove:hover { background: rgba(220,38,38,.1); } .ffh-edits-panel-footer { padding: 12px; border-top: 1px solid #e2e8f0; display: flex; gap: 8px; flex-direction: column; } .ffh-copy-btn { background: #e8450a; color: #fff; border: none; border-radius: 22px; padding: 12px 16px; font-size: 13px; font-weight: 800; cursor: pointer; transition: all .2s; font-family: inherit; display: flex; align-items: center; justify-content: center; gap: 8px; } .ffh-copy-btn:hover { background: #c73a08; } .ffh-copy-btn.copied { background: #16a34a; } .ffh-clear-btn { background: transparent; color: #6b7a99; border: 1px solid #e2e8f0; border-radius: 16px; padding: 6px 12px; font-size: 11px; font-weight: 700; cursor: pointer; font-family: inherit; } .ffh-clear-btn:hover { color: #dc2626; border-color: #dc2626; } .ffh-empty-state { text-align: center; padding: 20px; color: #6b7a99; font-size: 12px; } /* Modal toast */ .ffh-toast { position: fixed; top: 50px; left: 50%; transform: translateX(-50%); background: #0f2044; color: #fff; padding: 12px 24px; border-radius: 28px; font-size: 13px; font-weight: 700; box-shadow: 0 8px 24px rgba(0,0,0,.3); z-index: 10000; font-family: -apple-system, sans-serif; opacity: 0; transition: opacity .25s; pointer-events: none; } .ffh-toast.show { opacity: 1; } /* Skip elements that should never be editable */ .ffh-no-edit, .ffh-edit-toggle, .ffh-edits-panel, .ffh-edit-banner, .ffh-edit-toolbar, .ffh-pencil-btn, .ffh-toast, .nav-bar, .nav-logo, nav, footer, script, style, head { /* These are excluded from edit hover detection in JS */ } `; var styleEl = document.createElement('style'); styleEl.id = 'ffh-editor-styles'; styleEl.textContent = css; document.head.appendChild(styleEl); } // ── Editable element detection ───────────────────────────────────────── function isElementEditable(el) { if (!el || el.nodeType !== 1) return false; // Skip our own UI if (el.closest('.ffh-edit-toggle, .ffh-edits-panel, .ffh-edit-banner, .ffh-edit-toolbar, .ffh-pencil-btn, .ffh-toast')) return false; // Skip nav and footer chrome if (el.closest('nav.nav-bar, footer.site-footer, footer')) return false; // Skip inputs and form elements var tag = el.tagName.toLowerCase(); if (['input','textarea','select','button','script','style','svg','path','image','img'].indexOf(tag) !== -1) return false; if (el.closest('svg')) return false; // Need text content var text = (el.textContent || '').trim(); if (!text || text.length < 2) return false; // Ideal targets: leaf text elements (no element children, or only inline formatting children) var inlineFormatting = ['b','i','em','strong','u','span','br','a','small','sub','sup','code','mark']; var hasNonInlineChildren = false; for (var i = 0; i < el.children.length; i++) { var childTag = el.children[i].tagName.toLowerCase(); if (inlineFormatting.indexOf(childTag) === -1) { hasNonInlineChildren = true; break; } } if (hasNonInlineChildren) return false; // Filter: only keep "text-bearing" tags var allowedTags = ['p','h1','h2','h3','h4','h5','h6','li','td','th','span','strong','em','figcaption','blockquote','dt','dd','div','a','small']; if (allowedTags.indexOf(tag) === -1) return false; // Skip very short or whitespace-only or layout-only divs if (tag === 'div' && el.children.length > 0) return false; return true; } // ── UI ───────────────────────────────────────────────────────────────── var toggleBtn, editsPanel, editsList, editsCount, banner; function injectUI() { // Floating toggle toggleBtn = document.createElement('button'); toggleBtn.className = 'ffh-edit-toggle'; toggleBtn.innerHTML = '✏ Edit Mode'; toggleBtn.addEventListener('click', toggleEditMode); document.body.appendChild(toggleBtn); // Edits panel editsPanel = document.createElement('div'); editsPanel.className = 'ffh-edits-panel'; editsPanel.innerHTML = `

Pending Edits

0
`; document.body.appendChild(editsPanel); editsList = editsPanel.querySelector('.ffh-edits-panel-list'); editsCount = editsPanel.querySelector('.ffh-edits-panel-count'); editsPanel.querySelector('.ffh-copy-btn').addEventListener('click', copyEditsToClipboard); editsPanel.querySelector('.ffh-clear-btn').addEventListener('click', clearEdits); } function showBanner() { if (banner) return; banner = document.createElement('div'); banner.className = 'ffh-edit-banner'; banner.innerHTML = '✏ Edit Mode is ON — hover any text to reveal the edit pencil'; document.body.appendChild(banner); document.body.classList.add('ffh-edit-on'); } function hideBanner() { if (banner) { banner.remove(); banner = null; } document.body.classList.remove('ffh-edit-on'); } function toast(msg) { var t = document.createElement('div'); t.className = 'ffh-toast'; t.textContent = msg; document.body.appendChild(t); setTimeout(function() { t.classList.add('show'); }, 10); setTimeout(function() { t.classList.remove('show'); }, 2200); setTimeout(function() { t.remove(); }, 2600); } // ── Hover handling ───────────────────────────────────────────────────── var hoverEl = null, pencilBtn = null; function clearHover() { if (hoverEl) { hoverEl.classList.remove('ffh-editable-hover'); hoverEl = null; } if (pencilBtn) { pencilBtn.remove(); pencilBtn = null; } } function attachPencil(el) { clearHover(); if (!editMode || currentEditEl) return; if (!isElementEditable(el)) return; el.classList.add('ffh-editable-hover'); // Make sure positioning works var origPos = window.getComputedStyle(el).position; if (origPos === 'static') el.style.position = 'relative'; // Pencil button pencilBtn = document.createElement('button'); pencilBtn.className = 'ffh-pencil-btn'; pencilBtn.innerHTML = '✏'; pencilBtn.title = 'Edit this text'; pencilBtn.addEventListener('mousedown', function(e) { e.preventDefault(); e.stopPropagation(); startEdit(el); }); el.appendChild(pencilBtn); hoverEl = el; } function onMouseOver(e) { if (!editMode || currentEditEl) return; var target = e.target; // Walk up to find nearest editable ancestor var maxDepth = 5, depth = 0, el = target; while (el && depth < maxDepth) { if (isElementEditable(el)) { attachPencil(el); return; } el = el.parentElement; depth++; } clearHover(); } function onMouseOut(e) { // Only clear if we're truly leaving the hovered element if (!hoverEl) return; var related = e.relatedTarget; if (related && (hoverEl.contains(related) || related.classList && related.classList.contains('ffh-pencil-btn'))) return; // small delay so the pencil button is clickable setTimeout(function() { if (!pencilBtn || !pencilBtn.matches(':hover')) clearHover(); }, 80); } // ── Edit lifecycle ───────────────────────────────────────────────────── function startEdit(el) { clearHover(); currentEditEl = el; currentBeforeText = (el.innerText || el.textContent || '').replace(/\s+/g, ' ').trim(); el.contentEditable = 'true'; el.classList.add('ffh-editing'); el.spellcheck = true; el.focus(); // Place cursor at end var range = document.createRange(); range.selectNodeContents(el); range.collapse(false); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); // Toolbar var toolbar = document.createElement('div'); toolbar.className = 'ffh-edit-toolbar'; toolbar.innerHTML = ''; document.body.appendChild(toolbar); positionToolbar(toolbar, el); toolbar.querySelector('.save').addEventListener('mousedown', function(e) { e.preventDefault(); finishEdit(true, toolbar); }); toolbar.querySelector('.cancel').addEventListener('mousedown', function(e) { e.preventDefault(); finishEdit(false, toolbar); }); // Esc cancels el.addEventListener('keydown', function ek(ev) { if (ev.key === 'Escape') { ev.preventDefault(); finishEdit(false, toolbar); el.removeEventListener('keydown', ek); } else if (ev.key === 'Enter' && (ev.metaKey || ev.ctrlKey)) { ev.preventDefault(); finishEdit(true, toolbar); el.removeEventListener('keydown', ek); } }); } function positionToolbar(toolbar, el) { var rect = el.getBoundingClientRect(); var top = rect.top + window.scrollY - 44; if (top < window.scrollY + 36) top = rect.bottom + window.scrollY + 8; var left = rect.left + window.scrollX; toolbar.style.top = top + 'px'; toolbar.style.left = left + 'px'; } function finishEdit(save, toolbar) { if (!currentEditEl) return; var el = currentEditEl; var afterText = (el.innerText || el.textContent || '').replace(/\s+/g, ' ').trim(); el.contentEditable = 'false'; el.classList.remove('ffh-editing'); if (toolbar && toolbar.parentNode) toolbar.remove(); if (save && afterText && afterText !== currentBeforeText) { var edit = { tag: el.tagName.toLowerCase(), snippet: shortSnippet(currentBeforeText), before: currentBeforeText, after: afterText, timestamp: new Date().toISOString() }; pendingEdits.push(edit); savePendingEdits(); renderEditsPanel(); toast('Edit captured (' + pendingEdits.length + ' pending)'); } else if (!save) { // Restore el.innerText = currentBeforeText; } currentEditEl = null; currentBeforeText = null; } function shortSnippet(s) { if (!s) return ''; if (s.length <= 60) return s; return s.slice(0, 57) + '…'; } // ── Edits panel rendering ────────────────────────────────────────────── function renderEditsPanel() { editsCount.textContent = String(pendingEdits.length); if (pendingEdits.length === 0) { editsList.innerHTML = '
No edits yet. Click any pencil to start.
'; editsPanel.classList.remove('open'); } else { editsList.innerHTML = pendingEdits.map(function(e, i) { return `
[${i+1}] <${e.tag}> · ${shortSnippet(e.snippet)}
${escapeHtml(e.before)}
${escapeHtml(e.after)}
`; }).join(''); editsPanel.classList.add('open'); editsList.querySelectorAll('.row-remove').forEach(function(btn) { btn.addEventListener('click', function() { var idx = parseInt(btn.dataset.idx, 10); pendingEdits.splice(idx, 1); savePendingEdits(); renderEditsPanel(); }); }); } } function escapeHtml(s) { return String(s).replace(/&/g, '&').replace(//g, '>'); } function clearEdits() { if (pendingEdits.length === 0) return; if (!confirm('Discard all ' + pendingEdits.length + ' pending edit' + (pendingEdits.length > 1 ? 's' : '') + '?')) return; pendingEdits = []; savePendingEdits(); renderEditsPanel(); toast('Edits cleared'); } function copyEditsToClipboard() { if (pendingEdits.length === 0) { toast('No edits to copy'); return; } var meta = getPageMeta(); var lines = []; lines.push('=== FFH INLINE EDITS ==='); lines.push('File: ' + meta.sourceFile); lines.push('URL: ' + meta.url); lines.push('Page Title: ' + meta.title); lines.push('Captured: ' + new Date().toISOString()); lines.push('Edits: ' + pendingEdits.length); lines.push(''); pendingEdits.forEach(function(e, i) { lines.push('[' + (i+1) + '] <' + e.tag + '>'); lines.push('--- BEFORE ---'); lines.push(e.before); lines.push('--- AFTER ---'); lines.push(e.after); lines.push(''); }); lines.push('=== END EDITS ==='); var payload = lines.join('\n'); function fallbackCopy() { var ta = document.createElement('textarea'); ta.value = payload; ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); } catch (e) { /* ignore */ } ta.remove(); } if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(payload).then(function() { onCopySuccess(); }, function() { fallbackCopy(); onCopySuccess(); }); } else { fallbackCopy(); onCopySuccess(); } } function onCopySuccess() { var btn = editsPanel.querySelector('.ffh-copy-btn'); var orig = btn.innerHTML; btn.innerHTML = '✓ Copied! Paste into Cowork chat'; btn.classList.add('copied'); toast('Copied ' + pendingEdits.length + ' edit' + (pendingEdits.length > 1 ? 's' : '') + ' to clipboard'); setTimeout(function() { btn.innerHTML = orig; btn.classList.remove('copied'); }, 2400); } // ── Mode toggle ──────────────────────────────────────────────────────── function setEditMode(on) { editMode = on; saveEditMode(on); if (on) { toggleBtn.classList.add('on'); toggleBtn.innerHTML = '✗ Exit Edit Mode'; showBanner(); renderEditsPanel(); } else { toggleBtn.classList.remove('on'); toggleBtn.innerHTML = '✏ Edit Mode'; hideBanner(); clearHover(); editsPanel.classList.remove('open'); } } function toggleEditMode() { setEditMode(!editMode); if (editMode) toast('Edit mode ON — hover any text to edit'); else toast('Edit mode OFF'); } // ── Init ─────────────────────────────────────────────────────────────── function init() { injectStyles(); injectUI(); pendingEdits = loadPendingEdits(); renderEditsPanel(); // Hover listeners (always attached, gated by editMode flag inside) document.addEventListener('mouseover', onMouseOver); document.addEventListener('mouseout', onMouseOut); // Activate if mode was on var startOn = loadEditMode(); if (startOn) setEditMode(true); else setEditMode(false); // Re-position toolbar on scroll/resize during edit var repositionPending = false; function rep() { if (currentEditEl && !repositionPending) { repositionPending = true; requestAnimationFrame(function() { var tb = document.querySelector('.ffh-edit-toolbar'); if (tb && currentEditEl) positionToolbar(tb, currentEditEl); repositionPending = false; }); } } window.addEventListener('scroll', rep, { passive: true }); window.addEventListener('resize', rep); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();