{"id":58031,"date":"2026-07-31T21:40:09","date_gmt":"2026-07-31T21:40:09","guid":{"rendered":"http:\/\/trueomni.com\/?p=58031"},"modified":"2026-07-31T21:42:51","modified_gmt":"2026-07-31T21:42:51","slug":"exploreevansville","status":"publish","type":"post","link":"https:\/\/trueomni.com\/french\/true-impact\/exploreevansville\/","title":{"rendered":"Explorez Evansville"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"58031\" class=\"elementor elementor-58031\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cec9d27 e-con e-atomic-element e-flexbox-base e-74bce89 \" data-id=\"cec9d27\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"cec9d27\" data-e-type=\"e-flexbox\" data-id=\"cec9d27\">\n    \t\t<div class=\"elementor-element elementor-element-27134db elementor-widget elementor-widget-html\" data-id=\"27134db\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"en\" data-theme=\"light\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\"><link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700;800;900&display=swap\" rel=\"stylesheet\">\n<title>TrueImpact \u2014 Executive Dashboard \u00b7 Explore Evansville<\/title>\n<!--\n  TrueImpact Executive Dashboard  \u00b7  TrueOmni  \u00b7  Destination Performance Intelligence\n  ---------------------------------------------------------------------------------\n  Single-file, dependency-free reference build. All data lives in the DATA object\n  (see <script id=\"model\">). Metrics are DERIVED from base inputs in deriveMetrics()\n  so the math is transparent and re-wireable to a live attribution API.\n  OPPORTUNITY SCENARIO for Explore Evansville (Evansville \/ Vanderburgh County, IN).\n  Real cited destination statistics are surfaced first; the kiosk + digital-signage\n  network downstream of them is MODELED. Figures in USD. Brand per TrueOmni house style.\n-->\n<style>\n:root{\n  \/* ---- TrueOmni Design System tokens (blue #0EA1DC \u00b7 ink #0A0A0A \u00b7 bg #F5F7FA \u00b7 Inter) ---- *\/\n  --navy:#0D1A2D; --navy-2:#0A1420; --azure:#0EA1DC; --azure-d:#0B8AC4;\n  --deep:#0B8AC4; --ink:#0A0A0A; --slate:#6B7280; --amber:#C2641F;\n  \/* ---- validated chart palette (dataviz skill; passes CVD + normal-vision gates) ---- *\/\n  --s-hotels:#0EA1DC; --s-dining:#EB6834; --s-attractions:#008300; --s-events:#E87BA4;\n  --s-direct:#0EA1DC; --s-influenced:#0B8AC4; --s-local:#0EA1DC; --s-state:#1BAF7A;\n  --good:#0ca30c; --warn:#C2641F;\n  \/* ---- surfaces \/ ink (light) ---- *\/\n  --bg:#F5F7FA; --surface:#ffffff; --surface-2:#F1F5F9; --line:#E5E7EB;\n  --text:#0A0A0A; --text-2:#6B7280; --muted:#9CA3AF; --grid:#E5E7EB;\n  --tint:#E0F2FE;\n  --shadow:0 1px 2px rgba(13,26,45,.06),0 8px 24px rgba(13,26,45,.06);\n  --shadow-lg:0 24px 60px rgba(13,26,45,.16);\n  --radius:16px; --radius-sm:11px;\n  --font:'Inter','Segoe UI',system-ui,-apple-system,Roboto,Helvetica,Arial,sans-serif;\n}\nhtml[data-theme=\"dark\"]{\n  --navy:#0D1A2D; --azure:#3BB8ED; --deep:#0B8AC4;\n  --s-hotels:#38b6ec; --s-dining:#f0854f; --s-attractions:#37a637; --s-events:#e493b5;\n  --s-direct:#38b6ec; --s-influenced:#2f77c4; --s-local:#38b6ec; --s-state:#22c48a;\n  --bg:#0a1420; --surface:#101d2e; --surface-2:#0c1826; --line:#1e2f45;\n  --text:#eaf1f8; --text-2:#a9b7c8; --muted:#6f8098; --grid:#182636;\n  --shadow:0 1px 2px rgba(0,0,0,.4),0 10px 30px rgba(0,0,0,.35);\n  --shadow-lg:0 24px 60px rgba(0,0,0,.55);\n}\n*{box-sizing:border-box;margin:0;padding:0}\nhtml,body{background:var(--bg);color:var(--text);font-family:var(--font);-webkit-font-smoothing:antialiased;scroll-behavior:smooth}\nbody{font-size:15px;line-height:1.5}\na{color:inherit;text-decoration:none}\nbutton{font-family:inherit;cursor:pointer;border:0;background:none;color:inherit}\n.tnum{font-variant-numeric:tabular-nums}\n\n\/* ---------- Top bar ---------- *\/\n.topbar{position:sticky;top:0;z-index:50;background:linear-gradient(100deg,var(--navy) 0%,var(--navy-2) 100%);color:#fff;box-shadow:0 6px 20px rgba(10,26,49,.28)}\n.topbar-inner{max-width:1320px;margin:0 auto;padding:12px 24px;display:flex;align-items:center;gap:18px}\n.brand{display:flex;align-items:center;gap:11px;font-weight:700;letter-spacing:.2px}\n.brand .mark{width:30px;height:30px;border-radius:8px;background:linear-gradient(135deg,var(--azure),#0f6fa0);display:grid;place-items:center;box-shadow:0 4px 14px rgba(28,156,216,.45)}\n.brand .mark svg{width:17px;height:17px}\n.brand .name{font-size:16px}.brand .name b{color:var(--azure)}\n.brand .sub{font-size:10px;font-weight:600;letter-spacing:1.6px;color:#9fc7de;text-transform:uppercase;margin-top:1px;white-space:nowrap}\n.brand{flex:none}\n.segset button{white-space:nowrap}\n@media (max-width:1280px){.brand .sub{display:none}.live{display:none}}\n.destpick{display:flex;align-items:center;gap:7px;background:rgba(255,255,255,.11);border:1px solid rgba(255,255,255,.14);border-radius:9px;padding:6px 10px;color:#dceaf5}\n.destpick svg{width:15px;height:15px;flex:none;color:var(--azure)}\n.destpick select{background:transparent;border:0;color:#fff;font-family:inherit;font-size:13px;font-weight:700;outline:none;cursor:pointer;max-width:190px}\n.destpick select option{color:#12202f}\n.sample{font-size:10px;font-weight:800;letter-spacing:1.2px;color:#ffd79a;background:rgba(194,100,31,.28);border:1px solid rgba(255,183,120,.4);border-radius:6px;padding:4px 8px;white-space:nowrap}\n@media (max-width:1180px){.sample{display:none}}\n.live{display:flex;align-items:center;gap:7px;font-size:12px;color:#bfe0f0;font-weight:600;margin-left:2px}\n.dot{width:8px;height:8px;border-radius:50%;background:#3ee08a;box-shadow:0 0 0 0 rgba(62,224,138,.7);animation:pulse 2s infinite}\n@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(62,224,138,.55)}70%{box-shadow:0 0 0 9px rgba(62,224,138,0)}100%{box-shadow:0 0 0 0 rgba(62,224,138,0)}}\n.spacer{flex:1}\n.controls{display:flex;align-items:center;gap:9px}\n.segset{display:flex;background:rgba(255,255,255,.09);border-radius:10px;padding:3px}\n.segset button{font-size:12.5px;font-weight:600;color:#c5d6e6;padding:6px 12px;border-radius:7px;transition:.15s}\n.segset button.on{background:var(--azure);color:#04141f;box-shadow:0 2px 8px rgba(28,156,216,.4)}\n.icon-btn{width:36px;height:36px;border-radius:9px;background:rgba(255,255,255,.1);display:grid;place-items:center;color:#dceaf5;transition:.15s}\n.icon-btn:hover{background:rgba(255,255,255,.2)}\n.icon-btn svg{width:18px;height:18px}\n.cta{background:var(--azure);color:#04141f;font-weight:700;font-size:13px;padding:9px 15px;border-radius:9px;display:flex;align-items:center;gap:7px;transition:.15s}\n.cta:hover{background:#33abe0;transform:translateY(-1px)}\n.cta svg{width:15px;height:15px}\n\n\/* ---------- Breadcrumb \/ subnav ---------- *\/\n.wrap{max-width:1320px;margin:0 auto;padding:22px 24px 60px}\n.crumbs{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-2);margin-bottom:16px;flex-wrap:wrap}\n.crumbs a{color:var(--azure);font-weight:600}\n.crumbs .sep{color:var(--muted)}\n.pagehead{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:6px;flex-wrap:wrap}\n.pagehead h1{font-size:27px;letter-spacing:-.4px;line-height:1.15}\n.pagehead .eyebrow{font-size:11.5px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:var(--azure);margin-bottom:5px}\n.pagehead .meta{font-size:12.5px;color:var(--muted);text-align:right}\n\n\/* ---------- Cards \/ grid ---------- *\/\n.grid{display:grid;gap:16px}\n.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:18px 18px 16px}\n.card.pad0{padding:0;overflow:hidden}\n.card h3{font-size:13px;font-weight:700;letter-spacing:.2px;display:flex;align-items:center;gap:8px}\n.card h3 .hint{font-size:11px;color:var(--muted);font-weight:600}\n.card .ch-sub{font-size:12px;color:var(--text-2);margin-top:2px}\n.card-h{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:14px}\n\n\/* KPI hero band *\/\n.kpis{display:grid;grid-template-columns:1.5fr 1fr 1fr 1fr;gap:16px}\n.kpi{position:relative;overflow:hidden}\n.kpi.hero{background:linear-gradient(140deg,var(--navy),#123056 90%);color:#fff;border:0}\n.kpi .k-label{font-size:12px;color:var(--text-2);font-weight:600;display:flex;align-items:center;gap:6px}\n.kpi.hero .k-label{color:#a8c6db}\n.kpi .k-val{font-size:34px;font-weight:700;letter-spacing:-1px;margin-top:7px;line-height:1}\n.kpi.hero .k-val{font-size:44px}\n.kpi .k-val .cur{font-size:.62em;opacity:.7;font-weight:600;vertical-align:.14em;margin-right:1px}\n.kpi .k-delta{font-size:12.5px;font-weight:700;margin-top:9px;display:inline-flex;align-items:center;gap:5px}\n.k-delta.up{color:var(--good)} .kpi.hero .k-delta.up{color:#5ef0a5}\n.kpi .k-foot{font-size:11.5px;color:var(--muted);margin-top:8px}\n.kpi.hero .k-foot{color:#8fb2ca}\n.spark{position:absolute;right:14px;bottom:12px;opacity:.9}\n.kpi.hero .glow{position:absolute;right:-40px;top:-40px;width:180px;height:180px;background:radial-gradient(circle,rgba(28,156,216,.5),transparent 70%);pointer-events:none}\n\n.row-2{grid-template-columns:1.35fr 1fr}\n.row-3{grid-template-columns:repeat(3,1fr)}\n.row-map{grid-template-columns:1.15fr .85fr}\n\n\/* Map *\/\n.mapwrap{position:relative;padding:8px}\n.mapwrap svg{width:100%;height:auto;display:block}\n.mk{cursor:pointer;transition:.15s}\n.mk circle.hit{fill:transparent}\n.mk .pin{transition:.15s;stroke:var(--surface);stroke-width:2}\n.mk:hover .pin,.mk.active .pin{filter:brightness(1.08)}\n.mk:hover .ring,.mk.active .ring{opacity:1}\n.mk .ring{fill:none;stroke:var(--azure);stroke-width:2;opacity:0;transition:.15s}\n.mk text{font-size:9.5px;font-weight:700;fill:var(--text);paint-order:stroke;stroke:var(--surface);stroke-width:3px;stroke-linejoin:round}\n.ca-outline{fill:var(--surface-2);stroke:var(--line);stroke-width:1.5}\nhtml[data-theme=\"dark\"] .ca-outline{fill:#0c1c2e;stroke:#20344c}\n\n\/* Location list *\/\n.loclist{display:flex;flex-direction:column;gap:2px}\n.locrow{display:grid;grid-template-columns:1fr auto auto;align-items:center;gap:12px;padding:11px 12px;border-radius:11px;cursor:pointer;transition:.13s;border:1px solid transparent}\n.locrow:hover{background:var(--surface-2);border-color:var(--line);transform:translateX(2px)}\n.locrow .lr-name{font-weight:700;font-size:13.5px}\n.locrow .lr-sub{font-size:11.5px;color:var(--muted);margin-top:1px}\n.locrow .lr-val{font-weight:700;font-size:14px;text-align:right}\n.locrow .lr-bar{grid-column:1\/-1;height:5px;border-radius:3px;background:var(--grid);overflow:hidden;margin-top:2px}\n.locrow .lr-bar i{display:block;height:100%;border-radius:3px;background:linear-gradient(90deg,var(--azure),#0f6fa0)}\n.locrow .chev{color:var(--muted)}\n\n\/* Funnel *\/\n.funnel{display:flex;flex-direction:column;gap:9px;margin-top:4px}\n.fstage{position:relative}\n.fstage .fbar{height:38px;border-radius:9px;display:flex;align-items:center;padding:0 13px;color:#fff;font-weight:700;font-size:13px;transition:width .6s cubic-bezier(.2,.8,.2,1);box-shadow:0 2px 8px rgba(14,34,64,.12)}\n.fstage .fmeta{position:absolute;right:0;top:50%;transform:translateY(-50%);display:flex;gap:12px;align-items:center;font-size:12px;color:var(--text-2);padding-right:4px}\n.fstage .fmeta b{color:var(--text);font-size:13px}\n.fstage .frate{font-size:11px;color:var(--muted);font-weight:600}\n\n\/* Legend *\/\n.legend{display:flex;flex-wrap:wrap;gap:14px;margin-top:12px;font-size:12px;color:var(--text-2)}\n.legend .li{display:flex;align-items:center;gap:6px;font-weight:600}\n.legend .sw{width:11px;height:11px;border-radius:3px}\n.legend .sw.line{height:3px;width:16px;border-radius:2px}\n\n\/* partner segment cards *\/\n.seg-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}\n.seg-card{border:1px solid var(--line);border-radius:var(--radius-sm);padding:14px;cursor:pointer;transition:.15s;background:var(--surface)}\n.seg-card:hover{transform:translateY(-3px);box-shadow:var(--shadow)}\n.seg-card .sc-top{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700}\n.seg-card .sc-ic{width:26px;height:26px;border-radius:7px;display:grid;place-items:center}\n.seg-card .sc-ic svg{width:15px;height:15px;color:#fff}\n.seg-card .sc-val{font-size:23px;font-weight:700;letter-spacing:-.5px;margin-top:11px}\n.seg-card .sc-sub{font-size:11.5px;color:var(--muted);margin-top:3px}\n.seg-card .sc-count{font-size:11.5px;color:var(--text-2);font-weight:600;margin-top:9px;display:flex;justify-content:space-between;border-top:1px solid var(--line);padding-top:8px}\n\n\/* table *\/\ntable{width:100%;border-collapse:collapse;font-size:13px}\nth,td{text-align:right;padding:10px 10px;border-bottom:1px solid var(--line)}\nth{font-size:11px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);font-weight:700}\nth:first-child,td:first-child{text-align:left}\ntbody tr{cursor:pointer;transition:.12s}\ntbody tr:hover{background:var(--surface-2)}\ntd .pill{display:inline-block;font-size:11px;font-weight:700;padding:2px 8px;border-radius:20px}\n.tag-hi{background:rgba(12,163,12,.13);color:var(--good)}\n.tag-mid{background:rgba(28,156,216,.14);color:var(--azure-d)}\n\n\/* AI insight banner *\/\n.ai-banner{display:flex;gap:14px;align-items:flex-start;background:linear-gradient(100deg,rgba(28,156,216,.08),rgba(20,80,140,.05));border:1px solid var(--line);border-left:3px solid var(--azure);border-radius:var(--radius);padding:15px 18px;margin-bottom:16px}\n.ai-banner .ai-ic{flex:none;width:34px;height:34px;border-radius:9px;background:linear-gradient(135deg,var(--azure),var(--deep));display:grid;place-items:center;box-shadow:0 4px 12px rgba(28,156,216,.35)}\n.ai-banner .ai-ic svg{width:18px;height:18px;color:#fff}\n.ai-banner .ai-txt{font-size:13.5px;color:var(--text);line-height:1.55}\n.ai-banner .ai-txt b{color:var(--text)}\n.ai-banner .ai-txt .em{color:var(--azure-d);font-weight:700}\nhtml[data-theme=\"dark\"] .ai-banner .ai-txt .em{color:var(--azure)}\n.ai-banner .ai-tag{font-size:10.5px;font-weight:700;letter-spacing:1.4px;text-transform:uppercase;color:var(--azure-d);margin-bottom:3px;display:block}\n\n\/* tooltip *\/\n.tt{position:fixed;z-index:99;pointer-events:none;background:var(--navy);color:#fff;font-size:12px;padding:9px 12px;border-radius:9px;box-shadow:var(--shadow-lg);opacity:0;transition:opacity .1s;max-width:230px;line-height:1.45}\n.tt .tt-t{font-weight:700;margin-bottom:3px;font-size:12.5px}\n.tt .tt-r{display:flex;justify-content:space-between;gap:16px;color:#bcd4e6}\n.tt .tt-r b{color:#fff}\nhtml[data-theme=\"dark\"] .tt{background:#020a14;border:1px solid #1e3350}\n\n\/* misc *\/\n.chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;padding:5px 11px;border-radius:20px;background:var(--surface-2);border:1px solid var(--line);color:var(--text-2)}\n.chip .sw{width:9px;height:9px;border-radius:50%}\n.stat-inline{display:flex;gap:26px;flex-wrap:wrap;margin-top:2px}\n.stat-inline .si b{display:block;font-size:20px;font-weight:700;letter-spacing:-.4px}\n.stat-inline .si span{font-size:11.5px;color:var(--muted);font-weight:600}\n.backbtn{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--azure);margin-bottom:12px}\n.backbtn svg{width:15px;height:15px}\n.gauge-track{height:9px;border-radius:5px;background:var(--grid);overflow:hidden;margin-top:8px}\n.gauge-track i{display:block;height:100%;border-radius:5px;background:linear-gradient(90deg,var(--s-state),#0f9c6d)}\n.note{font-size:11px;color:var(--muted);margin-top:12px;line-height:1.5}\n\/* engagement filters *\/\n.filters{display:flex;flex-wrap:wrap;gap:10px 18px;align-items:center;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:12px 16px;margin-bottom:16px}\n.fgroup{display:flex;align-items:center;gap:8px}\n.fgroup>.flab{font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--muted)}\n.fseg{display:flex;background:var(--surface-2);border:1px solid var(--line);border-radius:9px;padding:3px;gap:2px}\n.fseg button{font-size:12.5px;font-weight:600;color:var(--text-2);padding:6px 12px;border-radius:6px;transition:.14s;white-space:nowrap}\n.fseg button.on{background:var(--azure);color:#04141f}\n.fsel{font-family:inherit;font-size:13px;font-weight:600;color:var(--text);background:var(--surface-2);border:1px solid var(--line);border-radius:8px;padding:7px 11px;cursor:pointer;outline:none}\n.fspace{flex:1}\n\/* A\/B test card *\/\n.ab-card{border:1px solid var(--line);border-radius:var(--radius-sm);padding:15px 16px;background:var(--surface)}\n.ab-head{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;margin-bottom:12px}\n.ab-head .abt{font-size:13.5px;font-weight:700}\n.ab-head .abs{font-size:11px;color:var(--muted);margin-top:2px}\n.ab-badge{font-size:11px;font-weight:800;padding:4px 9px;border-radius:20px;white-space:nowrap}\n.ab-win{background:rgba(12,163,12,.14);color:var(--good)}\n.ab-none{background:rgba(139,150,165,.16);color:var(--text-2)}\n.ab-var{display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:center;padding:9px 0;border-top:1px solid var(--line)}\n.ab-tag{width:22px;height:22px;border-radius:6px;display:grid;place-items:center;font-size:12px;font-weight:800;color:#fff}\n.ab-nm{font-size:12.5px;font-weight:600}\n.ab-sub{font-size:11px;color:var(--muted)}\n.ab-conv{text-align:right}\n.ab-conv b{font-size:19px;font-weight:700;letter-spacing:-.5px}\n.ab-conv span{font-size:10.5px;color:var(--muted);display:block}\n.ab-bar{grid-column:1\/-1;height:6px;border-radius:3px;background:var(--grid);overflow:hidden;margin-top:-2px}\n.ab-bar i{display:block;height:100%;border-radius:3px}\n.ab-foot{display:flex;justify-content:space-between;font-size:11.5px;color:var(--text-2);margin-top:11px;border-top:1px solid var(--line);padding-top:10px}\n.ab-foot b{color:var(--text)}\n.conv-pill{font-size:11px;font-weight:700;padding:2px 8px;border-radius:20px;background:rgba(28,156,216,.14);color:var(--azure-d)}\nhtml[data-theme=\"dark\"] .conv-pill{color:var(--azure)}\n.toggle-tbl{font-size:11.5px;color:var(--azure-d);font-weight:600;cursor:pointer}\nhtml[data-theme=\"dark\"] .toggle-tbl{color:var(--azure)}\n.hidden{display:none!important}\n.fade{animation:fade .35s ease}\n@keyframes fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}\n.footer{max-width:1320px;margin:0 auto;padding:20px 24px 40px;color:var(--muted);font-size:11.5px;display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;border-top:1px solid var(--line);margin-top:20px}\n\n@media (max-width:1080px){\n  .kpis{grid-template-columns:1fr 1fr}.row-2,.row-map,.row-3{grid-template-columns:1fr}.seg-cards{grid-template-columns:1fr 1fr}\n}\n@media print{\n  .topbar,.cta,.icon-btn,.segset,.toggle-tbl{display:none!important}\n  body{background:#fff}.card{box-shadow:none;border:1px solid #ccc;break-inside:avoid}\n}\n\n\/* ===================== TrueOmni Design System overrides ===================== *\/\n.eyebrow{color:var(--azure)!important;text-transform:uppercase;letter-spacing:.12em;font-weight:600}\n.eyebrow::before{content:'\\2500\\2500  ';color:var(--azure);font-weight:700;letter-spacing:0}\n.card{border-top:3px solid var(--azure)}\n.pagehead h1{letter-spacing:-.01em}\n.pagehead h1::after{content:'\\2022';color:var(--azure);margin-left:3px;font-weight:900}\n.crumbs a{color:var(--azure)}\n<\/style>\n<\/head>\n<body>\n\n<!-- =================== TOP BAR =================== -->\n<header class=\"topbar\">\n  <div class=\"topbar-inner\">\n    <div class=\"brand\">\n      <span class=\"mark\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M3 20h18M6 20V10m4 10V5m4 15v-7m4 7V8\" stroke=\"#fff\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><\/svg><\/span>\n      <div>\n        <div class=\"name\">True<b>Impact<\/b><\/div>\n        <div class=\"sub\">Destination Performance Intelligence<\/div>\n      <\/div>\n    <\/div>\n    <label class=\"destpick\" style=\"display:none\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 21s-7-6.2-7-11a7 7 0 1114 0c0 4.8-7 11-7 11z\" stroke=\"currentColor\" stroke-width=\"1.8\"\/><circle cx=\"12\" cy=\"10\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.8\"\/><\/svg><select id=\"destSel\"><\/select><\/label>\n    <span class=\"sample\" title=\"OPPORTUNITY SCENARIO \u2014 modeled 7\u219220 kiosk \/ 3\u21925 screen ramp for Explore Evansville. Destination-context statistics are real and cited; everything downstream is modeled. Not audited results.\">MODELED<\/span>\n    <div class=\"live\"><span class=\"dot\"><\/span> PROJECTION \u00b7 pre-deployment<\/div>\n    <div class=\"spacer\"><\/div>\n    <div class=\"controls\">\n      <div class=\"segset\" id=\"periodSel\">\n        <button data-p=\"q\" >Quarter<\/button>\n        <button data-p=\"ytd\">YTD<\/button>\n        <button data-p=\"t12\" class=\"on\">Trailing 12 mo<\/button>\n      <\/div>\n      <button class=\"icon-btn\" id=\"themeBtn\" title=\"Toggle theme\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M21 12.8A9 9 0 1111.2 3a7 7 0 009.8 9.8z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\n      <\/button>\n      <button class=\"cta\" onclick=\"window.print()\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 9V3h12v6M6 18H4v-6h16v6h-2M8 14h8v7H8z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\n        Council Briefing\n      <\/button>\n    <\/div>\n  <\/div>\n<\/header>\n\n<div class=\"wrap\">\n  <div id=\"app\"><\/div>\n<\/div>\n\n<footer class=\"footer\">\n  <div>\u00a9 TrueOmni 2026 \u00b7 TrueImpact Executive Dashboard \u00b7 Scottsdale, AZ \u00b7 www.trueomni.com \u00b7 833-300-6664<\/div>\n  <div>Prepared for <b>Explore Evansville<\/b> \u00b7 Evansville \/ Vanderburgh County, Indiana \u00b7 figures in USD.<\/div>\n  <div>OPPORTUNITY SCENARIO \u00b7 pre-deployment. Destination-context statistics are published or client-supplied and cited on the tile; the kiosk and digital-signage network, exposures, media economics and partner mix are MODELED. Annual visitors (3.0M) is a client-directed planning estimate, not a published figure. Tax rates are real: 8% Vanderburgh County innkeeper&rsquo;s tax \u00b7 7% Indiana sales tax \u00b7 11% auto rental. Derived &amp; auditable via the TrueOmni attribution stack. Cite under NDA.<\/div>\n<\/footer>\n\n<div class=\"tt\" id=\"tt\"><\/div>\n\n<!-- =================== DATA MODEL =================== -->\n<script id=\"model\">\n\/* ------------------------------------------------------------------\n   TrueImpact data model \u2014 EXPLORE EVANSVILLE edition.\n   Evansville \/ Vanderburgh County, Indiana. Single-tenant. Currency: USD.\n\n   FRAMING: no discovery call, no TrueOmni hardware in Evansville today.\n   This is an OPPORTUNITY SCENARIO. The destination-context figures\n   (CONTEXT.cited) are REAL \u2014 published by Explore Evansville or supplied\n   by the client. Everything downstream of them (zones, kiosk + screen\n   counts, exposures, media & signage economics, partner mix, modules) is\n   MODELED and labeled as such. See evansville-storytelling-provenance.md.\n\n   VISITOR ANCHOR: Explore Evansville publishes NO total annual visitor\n   count. 3.0M (range 2.8\u20133.2M) is the client-directed planning estimate,\n   badged MODELED ESTIMATE throughout. Sanity cross-check for the reader:\n   3.0M \u00d7 $165 average visitor spend \u2248 $495M direct visitor spending,\n   which sits credibly beside the cited $503M (2022) TOTAL economic\n   impact \u2014 but those are DIFFERENT measures (direct spend vs total impact\n   including indirect\/induced). The alignment is a plausibility check,\n   not an identity.\n\n   TAX IS REAL HERE. Unlike most builds, the three rates below are cited,\n   not assumed: 8% Vanderburgh County innkeeper's tax, 7% Indiana state\n   sales tax (Indiana has no local sales-tax add-on), and 11% on auto\n   rental (7% sales + Indiana's 4% auto rental excise).\n------------------------------------------------------------------ *\/\nconst FUNNEL = { highIntent:0.17, conversion:0.14 };  \/\/ TrueOmni platform benchmarks\nconst INFL_RATE = 0.85;   \/\/ influenced $ per $1 direct (Tourism Economics tail; 0.7\u20131.1)\n\/* Taxable-base split of attributed visitor spend. Blended: published 2023\n   Explore Evansville reporting put food ~40% and retail ~24% of visitor\n   spending; the client's 2025 figure puts retail at 48%. Both are carried in\n   the provenance ledger as a live discrepancy \u2014 this split splits the\n   difference and reserves a lodging share consistent with 48,784 room nights. *\/\nconst LODGING_SHARE = 0.28;       \/\/ accommodation\nconst DINING_RETAIL_SHARE = 0.46; \/\/ dining + retail (the dominant Evansville base)\nconst ATTR_SHARE = 0.22;          \/\/ attractions, admissions, tours\nconst RENTAL_SHARE = 0.04;        \/\/ auto rental\nconst RECIRC_MULT = 0.9;          \/\/ local re-spend of each public tax $ (induced, soft)\n\n\/* INDIANA \/ VANDERBURGH COUNTY TAX MODEL \u2014 rates are REAL and citable.\n   1. Innkeeper's tax, 8% on hotel rooms (Vanderburgh County). This is the\n      CEO's line: it is earmarked for tourism capital projects, destination\n      marketing, and Old National Events Plaza operations \u2014 local money that\n      returns to the destination. (Alexis Berggren via Evansville Living,\n      2025-03-12.)\n   2. Indiana state sales & use tax, 7%. Indiana levies NO local sales-tax\n      add-on, so every sales-tax dollar leaves for Indianapolis. That makes\n      the innkeeper's tax the only tax line that comes home.\n   3. Auto rental: 7% sales + 4% Indiana auto rental excise = 11%.\n   Rates live on each zone as tax:{tot:innkeeper%, sales:state sales%,\n   rental:rental total%}. Uniform county-wide. *\/\n\n\/\/ period scaling (of full-deployment trailing-12 baseline)\nconst PERIODS = { t12:{label:'Trailing 12 months (annualized, full deployment)',k:1}, ytd:{label:'Year to date (2026)',k:0.545}, q:{label:'This quarter (Q2 2026)',k:0.262} };\n\n\/* ==================================================================\n   DESTINATION CONTEXT \u2014 the REAL numbers, surfaced FIRST and above\n   anything modeled. Sources cited on each tile.\n================================================================== *\/\nconst CONTEXT = {\n  cited:[\n    {val:'$503M',           label:'Tourism economic impact',   sub:'Vanderburgh County, 2022 \u00b7 tourism is the county\u2019s 5th-largest industry', src:'Explore Evansville \/ Alexis Berggren via Evansville Living, 2025-03-12'},\n    {val:'10,293',          label:'Tourism-supported jobs',    sub:'county jobs supported by the visitor economy (2022)',                            src:'Explore Evansville via Evansville Living, 2025-03-12'},\n    {val:'$1,149',          label:'Household tax offset \/ yr', sub:'what each Vanderburgh household would pay in extra taxes without tourism',       src:'Explore Evansville via Evansville Living (client cites ~$1,200 current)'},\n    {val:'57.1% \u00b7 $103', label:'Hotel occupancy \u00b7 ADR', sub:'H1 2024 \u2014 occupancy \u22121.7% YoY, ADR +6.4%, avg visitor spend $165', src:'Explore Evansville via Evansville Living, 2025-03-12'},\n    {val:'$23M \u00b7 80+',   label:'Sports tourism (2025)', sub:'direct visitor spending & events \u2014 69% of all booked events are sports', src:'Explore Evansville, client-supplied 2025 season'},\n  ],\n  modeled:{\n    val:'3.0M', label:'Annual visitors', range:'2.8\u20133.2M',\n    note:'Explore Evansville publishes economic impact, jobs, room nights, occupancy and event attendance \u2014 but <b>no total annual visitor count<\/b>. 3.0M is the client-directed planning estimate, not a published figure. Plausibility cross-check: 3.0M \u00d7 $165 average visitor spend \u2248 <b>$495M direct visitor spending<\/b>, which sits credibly beside the cited <b>$503M (2022) total economic impact<\/b>. These are <b>different measures<\/b> \u2014 direct spend vs. total impact including indirect and induced effects \u2014 so the alignment is a sanity check, not an identity.'\n  },\n  visitorDef:'Explore Evansville counts a visitor as someone who travelled <b>more than 30 miles<\/b> from home or work, stayed <b>more than 2 hours<\/b>, and visited <b>at least one place of impact<\/b>. Every exposure figure below is scoped to that definition \u2014 which is also why the digital-signage audience base is larger: screens reach residents and repeat passes that the visitor definition deliberately excludes.'\n};\n\n\/\/ Partner segment metadata. NOTE: retail is carried inside the\n\/\/ \"Retail & Attractions\" segment \u2014 retail is 24\u201348% of Evansville visitor\n\/\/ spending depending on source, too large to bury in dining.\nconst SEG = {\n  hotels:      {name:'Hotels & Lodging',        color:'var(--s-hotels)',      raw:'#1C9CD8'},\n  dining:      {name:'Restaurants & Dining',    color:'var(--s-dining)',      raw:'#EB6834'},\n  attractions: {name:'Retail & Attractions',    color:'var(--s-attractions)', raw:'#008300'},\n  events:      {name:'Events, Sports & Venues', color:'var(--s-events)',      raw:'#E87BA4'},\n};\n\n\/* Seasonal shape (Jan..Dec) \u2014 Evansville is driven by the youth-sports\n   tournament calendar and the events season: a March championship bump\n   (OVC\/MVC basketball, IHSAA wrestling at Ford Center), an Apr\u2013Aug\n   tournament peak at Deaconess Sports Park and Goebel, a solid Sep\u2013Oct\n   (fall tournaments + the zoo's lantern festival), and a winter trough.\n   Less extreme than a single-season resort market, but real. MODELED. *\/\nconst SEASON = {\n  evv:[.68,.72,.94,1.16,1.28,1.34,1.30,1.24,1.10,1.00,.78,.72],\n};\nconst MONTHS=['Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb','Mar','Apr','May','Jun'];\n\n\/* ==================================================================\n   DESTINATION REGISTRY \u2014 single tenant: Explore Evansville.\n   Each \"location\" is a kiosk + signage cluster (deployment zone).\n   x,y = map coords in the 480\u00d7620 space; layout is a stylized\n   Vanderburgh County \u2014 Ohio River along the south\/southwest edge,\n   downtown on the river, East Side retail and the sports complexes to\n   the northeast, USI to the west.\n   exposures = annual >30-mile visitor encounters at this zone (MODELED,\n   anchored to each venue's own published or estimated scale \u2014 see the\n   note on each zone, and the provenance doc for which are which).\n   screens  = digital-signage displays (MODELED: ~2\u20134 per kiosk indoors,\n   ~1\u20132 outdoors, weighted to the arena, events plaza, mall and the\n   sports complexes \u2014 the captive-audience screen environments).\n   tax = {tot:innkeeper 8%, sales:IN state 7%, rental:11%} \u2014 all REAL.\n================================================================== *\/\nconst DESTINATIONS = {\n  evv:{ name:'Explore Evansville', kind:'Destination Marketing Organization', scope:'Vanderburgh County', region:'Evansville, IN',\n    outline:'M60,70 L420,70 L420,420 L380,470 L300,500 L220,492 L150,470 L95,430 L60,360 Z',\n    lake:'M60,360 L95,430 L150,470 L220,492 L300,500 L380,470 L420,420 L420,564 L60,564 Z',\n    lakeLabel:{x:240,y:544,t:'Ohio River'},\n    locations:[\n      {id:'visitorctr', name:'Downtown & Visitor Center', sites:'Explore Evansville Visitor Center \u00b7 Downtown Entertainment District', x:166,y:436, kiosks:2, screens:1, phase:1, exposures:88_000, interactionRate:.52, avgSpend:178, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.30,dining:.34,attractions:.24,events:.12}, note:'The official visitor center \u2014 trip planning, hotel assistance, convention services, sports-tourism support, group tours. Staff-assisted, so the highest interaction rate in the network and the natural Phase-1 flagship.', badge:'Phase 1'},\n      {id:'riverfront', name:'Ohio Riverfront & The Pagoda', sites:'The Pagoda visitor info \u00b7 Dress for Less Riverwalk', x:196,y:476, kiosks:2, screens:0, phase:1, exposures:105_000, interactionRate:.34, avgSpend:132, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.12,dining:.32,attractions:.38,events:.18}, note:'Second official visitor information point and the gateway to the Ohio Riverfront. Outdoor, weather-rated units \u2014 lower interaction rate, high raw exposure. No published visitation exists for the riverwalk; exposure is MODELED.', badge:'Phase 1'},\n      {id:'fordctr', name:'Ford Center & Victory Theatre', sites:'Ford Center (11,000 cap.) \u00b7 Victory Theatre \u00b7 UE Aces \u00b7 Thunderbolts', x:150,y:398, kiosks:2, screens:1, phase:1, exposures:110_000, interactionRate:.44, avgSpend:158, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.20,dining:.26,attractions:.12,events:.42}, note:'The arena anchor \u2014 concerts, UE Aces basketball, SPHL Thunderbolts, IHSAA wrestling and the March championship bump. Screen-rich concourse. No primary-source annual attendance is published; exposure is MODELED.', badge:'Phase 1'},\n      {id:'eventsplaza', name:'Old National Events Plaza', sites:'2,500-seat auditorium \u00b7 38,000 sq ft exhibit hall \u00b7 12 meeting rooms', x:206,y:392, kiosks:1, screens:1, phase:1, exposures:62_000, interactionRate:.46, avgSpend:236, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.42,dining:.24,attractions:.08,events:.26}, note:'Meetings and conventions \u2014 the highest spend per attributed visitor in the network (delegates book rooms). Its operations are part-funded by the same 8% innkeeper\\'s tax this dashboard measures. No published attendance; exposure is MODELED.', badge:'Phase 1'},\n      {id:'eastland', name:'Eastland Mall & East Side Corridor', sites:'Eastland Mall \u00b7 Green River Rd retail & dining', x:352,y:296, kiosks:3, screens:1, phase:2, exposures:185_000, interactionRate:.40, avgSpend:186, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.08,dining:.28,attractions:.58,events:.06}, note:'Eastland Mall is Explore Evansville\\'s #1 visitor point of interest, and 40% of visitors go to the East Side \u2014 so this zone carries the heaviest exposure weight and the most retail-weighted partner mix. Mall footfall is not published; exposure is MODELED.'},\n      {id:'deaconess', name:'Deaconess Sports Park', sites:'Championship softball\/baseball complex \u00b7 tournament HQ', x:396,y:196, kiosks:2, screens:1, phase:2, exposures:58_000, interactionRate:.42, avgSpend:268, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.52,dining:.22,attractions:.08,events:.18}, note:'CITED: 1,500+ teams and 60,000 visitors in 2024. Tournament families stay multiple nights \u2014 the highest lodging-weighted mix and highest per-visitor spend basis. With Goebel it has delivered 160,000 room nights and $125M since 2015.'},\n      {id:'goebel', name:'Goebel Soccer Complex', sites:'Evansville Sports Complex \u00b7 55 tournaments (2025)', x:344,y:136, kiosks:1, screens:0, phase:2, exposures:20_000, interactionRate:.40, avgSpend:244, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.50,dining:.24,attractions:.08,events:.18}, note:'CITED: 320 teams and 20,000 visitors in 2024. Explore Evansville has acquired ~100 acres nearby for expansion, so this zone is the network\\'s growth option.'},\n      {id:'zoo', name:'Mesker Park Zoo & Botanic Garden', sites:'Zoo \u00b7 Amazonia \u00b7 Wild Summer Lights', x:104,y:336, kiosks:1, screens:0, phase:2, exposures:80_000, interactionRate:.38, avgSpend:96, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.10,dining:.18,attractions:.62,events:.10}, note:'CITED: 229,278 visitors in 2025 \u2014 a record, including ~50,000 tickets to the new Wild Summer Lights lantern festival. Exposure here is the >30-mile visitor share of that total (MODELED at ~35%).'},\n      {id:'airport', name:'Evansville Regional Airport (EVV)', sites:'EVV terminal \u00b7 arrivals hall \u00b7 rental counters', x:238,y:146, kiosks:1, screens:0, phase:2, exposures:85_000, interactionRate:.48, avgSpend:205, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.44,dining:.22,attractions:.22,events:.12}, note:'CITED: 193,515 enplanements in 2024 (2025 tracking to 215\u2013220K, +23% through September). Arriving passengers \u2248 enplanements, so exposure is the inbound-visitor share (MODELED at ~45%). The only zone where a visitor is captured before any spend decision is made.'},\n      {id:'museums', name:'Museum District', sites:'Evansville Museum of Arts, History & Science \u00b7 Children\\'s Museum (cMoe)', x:108,y:412, kiosks:1, screens:0, phase:3, exposures:44_000, interactionRate:.42, avgSpend:88, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.12,dining:.20,attractions:.58,events:.10}, note:'CITED: Evansville Museum reports ~70,000 average annual attendance; cMoe reported just under 74,000 in 2018 (its most recent public figure). Exposure is the >30-mile visitor share of the combined base (MODELED).'},\n      {id:'ballys', name:'Bally\u2019s Evansville', sites:'Casino hotel \u00b7 riverfront gaming \u00b7 sportsbook', x:272,y:482, kiosks:1, screens:0, phase:3, exposures:65_000, interactionRate:.36, avgSpend:214, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.34,dining:.26,attractions:.14,events:.26}, note:'A top-five visitor point of interest and a strong drive-market draw. Indiana casinos have not reported admissions since HEA 1350 (2017) took effect 2018-07-01, so no admissions figure exists to anchor to \u2014 exposure is MODELED. What is public: $169.9M FY2025 win, $45.1M total tax.'},\n      {id:'haynies', name:'Haynie\u2019s Corner Arts District', sites:'Arts district \u00b7 galleries \u00b7 independent dining', x:242,y:440, kiosks:1, screens:0, phase:3, exposures:26_000, interactionRate:.32, avgSpend:108, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.10,dining:.50,attractions:.28,events:.12}, note:'The most dining-weighted zone in the network \u2014 culinary and gallery traffic, First Friday events. No published visitation exists; exposure is MODELED and deliberately small.'},\n      {id:'campus', name:'University Corridor \u00b7 UE & USI', sites:'University of Evansville \u00b7 University of Southern Indiana', x:286,y:342, kiosks:1, screens:0, phase:3, exposures:28_000, interactionRate:.34, avgSpend:122, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.30,dining:.28,attractions:.14,events:.28}, note:'CITED enrollment: USI 9,399 (Fall 2025), UE ~2,114 (2024 IPEDS). Universities are a named top visitor point of interest \u2014 the visitor traffic is parents, recruits, commencement and athletics, not students. A distributed two-campus cluster shown at one map point.'},\n      {id:'heritage', name:'Wesselman Woods & Angel Mounds', sites:'Wesselman Woods Nature Preserve \u00b7 Angel Mounds State Historic Site', x:398,y:396, kiosks:1, screens:0, phase:3, exposures:22_000, interactionRate:.30, avgSpend:74, tax:{tot:8.0,sales:7.0,rental:11.0}, season:'evv', mix:{hotels:.14,dining:.16,attractions:.60,events:.10}, note:'Outdoor recreation and heritage. Wesselman Woods states it \"impacts over 30,000 people a year\"; Indiana State Museum & Historic Sites does not publish site-level visitation for Angel Mounds. Exposure is MODELED and the smallest in the network.'},\n    ]},\n};\n\nlet activeDest='evv';\nfunction ACT(){return DESTINATIONS[activeDest];}\nfunction LOCS(){return ACT().locations;}\nfunction findLoc(id){return LOCS().find(l=>l.id===id);}\n\n\/* Deployment ramp \u2014 7 \u2192 15 \u2192 20 kiosks, 3 \u2192 5 \u2192 5 screens.\n   Phase 1 is the fastest proof: the official visitor center, the riverfront\n   Pagoda, and the arena \/ events-plaza cluster \u2014 all downtown, all within\n   walking distance, all already staffed. MODELED phasing; no rollout plan\n   has been agreed with Explore Evansville. *\/\nconst PHASES=[\n  {n:1, name:'Phase 1 \u00b7 Visitor center, riverfront & arena cluster', window:'Weeks 0\u20136',  ids:['visitorctr','riverfront','fordctr','eventsplaza']},\n  {n:2, name:'Phase 2 \u00b7 Sports complexes, East Side retail & EVV',   window:'Weeks 7\u201314', ids:['visitorctr','riverfront','fordctr','eventsplaza','eastland','deaconess','goebel','zoo','airport']},\n  {n:3, name:'Phase 3 \u00b7 Full network',                                   window:'Weeks 15\u201324',ids:['visitorctr','riverfront','fordctr','eventsplaza','eastland','deaconess','goebel','zoo','airport','museums','ballys','haynies','campus','heritage']},\n];\n\n\/* ==================================================================\n   MEDIA NETWORK (kiosk advertising revenue). MODELED \u2014 no rate card and\n   no proposal exists for Explore Evansville.\n   DEVIATION, LABELLED: the platform benchmark is $500\u20131,500\/kiosk\/mo.\n   That band is calibrated to large gateway destinations. Scaled DOWN to\n   $325\u20131,000 for a mid-market Indiana DMO whose local advertiser base is\n   regional (hospitals, universities, auto, restaurant groups, banks)\n   rather than national. imprPerEncounter raised 3.2 \u2192 4.0 to reflect the\n   attract-loop rotations a passer-by sees without touching the unit;\n   that keeps the implied kiosk CPM defensible for INTERACTIVE, high-dwell,\n   QR-convertible inventory (which prices above broadcast DOOH).\n   softwareYr and capital are scaled per-unit from the skill's reference\n   build (~$700\/kiosk\/yr software and ~$8,000\/kiosk capital).\n================================================================== *\/\nconst MEDIA={\n  perKioskMo:{floor:325, mid:650, strong:1000},   \/\/ USD \/ kiosk \/ month at mature fill (MODELED, scaled to mid-market)\n  imprPerEncounter:4.0,        \/\/ ad visualizations per kiosk encounter (attract loop + in-session containers)\n  fillMature:0.65,             \/\/ sell-through at maturity (below the 0.70 large-market benchmark)\n  fillByPhase:{1:0.30, 2:0.50, 3:0.65},\n  streamSplit:{direct:0.68, programmatic:0.32},   \/\/ local direct sales dominate in a mid-market\n  softwareYr:14000,            \/\/ ~$700\/kiosk\/yr \u00d7 20 kiosks (MODELED)\n  capital:160000,              \/\/ ~$8,000\/kiosk \u00d7 20 kiosks (MODELED)\n  inventory:[\n    {id:'video',    name:'Full-screen video (kiosk + video wall)', share:.30},\n    {id:'banner',   name:'Home & footer banners',                  share:.24},\n    {id:'rail',     name:'Sports & events side-rail',              share:.19},\n    {id:'sponsored',name:'Sponsored listings & tiles',              share:.15},\n    {id:'qr',       name:'QR-conversion sponsorships',              share:.12},\n  ],\n};\nfunction mediaMetrics(k=1, locs=LOCS()){\n  const r=rollup(k,locs);\n  const kiosks=r.kiosks;\n  const impressions=r.exposures*MEDIA.imprPerEncounter;\n  const band={}; for(const s in MEDIA.perKioskMo) band[s]=kiosks*MEDIA.perKioskMo[s]*12*k;\n  const rev=band.mid;\n  const cpm=impressions? rev\/(impressions\/1000):0;\n  const byStream={direct:rev*MEDIA.streamSplit.direct, programmatic:rev*MEDIA.streamSplit.programmatic};\n  const byInv=MEDIA.inventory.map(it=>({...it, v:rev*it.share}));\n  return {kiosks,impressions,band,rev,cpm,byStream,byInv};\n}\n\n\/* ==================================================================\n   DIGITAL SIGNAGE \u2014 non-interactive broadcast screens (OMNI Signage).\n   Screens deliver REACH and ad inventory; they do NOT transact, and none\n   of the numbers below feed interactions, attributed visitors, economic\n   impact or tax. Evansville is a signage-rich market: the sports\n   complexes, Ford Center, Old National Events Plaza and Eastland Mall are\n   captive-audience screen environments.\n\n   CALIBRATION NOTE (deviation from the skill defaults, deliberate):\n   the skill's default perScreenMo {200,450,800} with viewShare .55 \/\n   imprPerPasserby 1.4 produced an implied CPM over $500 at this network's\n   scale \u2014 absurd. Two things were wrong for Evansville:\n     (a) revenue per screen was set for a large market; and\n     (b) the audience base was wrong. Explore Evansville's visitor\n         definition (>30 miles from home\/work) deliberately EXCLUDES\n         residents \u2014 but a screen in Eastland Mall or the Ford Center\n         concourse is seen mostly by residents and by repeat passes.\n   So `residentMult` grows the signage audience base from >30-mile visitor\n   exposures to total venue footfall, and perScreenMo is scaled to a\n   mid-market. Result: an implied CPM in the low-$20s, inside the\n   defensible digital-out-of-home range. Both adjustments are MODELED.\n================================================================== *\/\nconst SIGNAGE={\n  enabled:true,\n  perScreenMo:{floor:120, mid:210, strong:340},  \/\/ USD \/ screen \/ month at mature fill (MODELED, mid-market)\n  loopSec:60, spotSec:15,        \/\/ 60s loop \/ 15s spot \u2192 4 spots per loop \u2192 25% share of voice\n  \/* 5-screen network: one display each at the Visitor Center, Ford Center, Old National\n     Events Plaza, Eastland Mall and Deaconess Sports Park. viewShare\/imprPerPasserby are\n     scaled DOWN from the multi-screen defaults accordingly \u2014 a lone screen sees a fraction\n     of a venue's footfall. Implied CPM stays inside the DOOH band. MODELED. *\/\n  residentMult:5.0,              \/\/ venue footfall \u00f7 >30-mile visitor exposures (signage reaches residents + repeat passes)\n  viewShare:0.30,                \/\/ ONE screen per venue, not a cluster \u2014 only ~30% of venue footfall passes its view zone\n  imprPerPasserby:1.2,           \/\/ ~1 screen face seen per visit at a single-screen venue (was 2.6 for multi-screen zones)\n  dwellSec:8,                    \/\/ avg attention seconds \u2014 the DOOH quality metric\n  fillMature:0.65, fillByPhase:{1:0.30,2:0.50,3:0.65},\n  capitalPerScreen:2200, softwarePerScreenYr:300,   \/\/ display + player + mount installed; CMS licence\n  formats:[                      \/\/ revenue share by format, sums to 1.0 \u2014 weighted to arena\/sports\/mall\n    {id:'wall',     name:'Video wall \/ arena & concourse hero',  share:.30},\n    {id:'portrait', name:'Portrait posters (concourse & corridor)', share:.26},\n    {id:'wayfind',  name:'Wayfinding & tournament schedule boards', share:.22},\n    {id:'menu',     name:'Concession \/ retail promo boards',        share:.14},\n    {id:'outdoor',  name:'Outdoor \/ weatherized (riverfront & complexes)', share:.08},\n  ],\n};\nfunction signageMetrics(k=1, locs=LOCS()){\n  if(!SIGNAGE.enabled) return null;\n  const screens=locs.reduce((s,L)=>s+(L.screens||0),0);\n  const screened=locs.filter(L=>L.screens);   \/\/ only zones WITH a screen generate screen impressions\n  const footfall=screened.reduce((s,L)=>s+L.exposures,0)*k*SIGNAGE.residentMult;\n  const reach=footfall*SIGNAGE.viewShare;\n  const impressions=reach*SIGNAGE.imprPerPasserby;\n  const band={}; for(const s in SIGNAGE.perScreenMo) band[s]=screens*SIGNAGE.perScreenMo[s]*12*k;\n  const rev=band.mid;\n  const cpm=impressions? rev\/(impressions\/1000):0;\n  const spotsPerLoop=Math.round(SIGNAGE.loopSec\/SIGNAGE.spotSec);\n  const shareOfVoice=1\/spotsPerLoop;\n  const capital=screens*SIGNAGE.capitalPerScreen, softwareYr=screens*SIGNAGE.softwarePerScreenYr;\n  const revPerScreen=screens? rev\/screens : 0;\n  const byFormat=SIGNAGE.formats.map(f=>({...f, v:rev*f.share}));\n  const byZone=locs.filter(L=>L.screens).map(L=>({id:L.id,name:L.name,screens:L.screens,v:(L.screens\/(screens||1))*rev}));\n  return {screens,footfall,reach,impressions,band,rev,cpm,spotsPerLoop,shareOfVoice,capital,softwareYr,revPerScreen,byFormat,byZone};\n}\n\/* Combined advertising headline \u2014 Doug's vocabulary. *\/\nfunction adTotals(k=1, locs=LOCS()){\n  const km=mediaMetrics(k,locs), sg=signageMetrics(k,locs);\n  const total=km.rev+(sg?sg.rev:0);\n  const capital=MEDIA.capital+(sg?sg.capital:0);\n  const softwareYr=MEDIA.softwareYr+(sg?sg.softwareYr:0);\n  return {km,sg,total,capital,softwareYr,payback:total?capital\/total:0};\n}\n\n\/* ---- derive all metrics for one location at a period scale ---- *\/\nfunction deriveMetrics(L, k=1){\n  const exposures = L.exposures*k;\n  const interactions = exposures*L.interactionRate;\n  const highIntent = interactions*FUNNEL.highIntent;\n  const conversions = highIntent*FUNNEL.conversion;\n  const directSpend = conversions*L.avgSpend;             \/\/ visitor $ captured & attributed (USD)\n  const direct = directSpend;\n  const influenced = directSpend*INFL_RATE;\n  const total = direct+influenced;\n  \/\/ -------- Indiana \/ Vanderburgh County tax engine --------\n  const r = L.tax;                                        \/\/ {tot:innkeeper%, sales:IN sales%, rental:11%}\n  const taxableSpend = directSpend + influenced*0.5;      \/\/ direct + half of influenced re-spend\n  const lodgingBase  = taxableSpend*LODGING_SHARE;\n  const diningBase   = taxableSpend*DINING_RETAIL_SHARE;\n  const attrBase     = taxableSpend*ATTR_SHARE;\n  const rentalBase   = taxableSpend*RENTAL_SHARE;\n  \/\/ taxBreak keys kept stable for the render layer:\n  const hotelTOT   = lodgingBase*(r.tot\/100);                    \/\/ innkeeper's tax \u2014 LOCAL, funds the destination\n  const salesTax   = (lodgingBase+diningBase)*(r.sales\/100);     \/\/ IN sales & use on lodging + dining\/retail\n  const rentalTax  = rentalBase*(r.rental\/100);                  \/\/ auto rental (7% sales + 4% excise)\n  const stateTax   = attrBase*(r.sales\/100);                     \/\/ IN sales & use on attractions\/admissions\n  const taxLocal   = hotelTOT;                            \/\/ the only line that comes home to Evansville\n  const taxState   = salesTax+rentalTax+stateTax;          \/\/ to the State of Indiana\n  const tax        = taxLocal+taxState;\n  const recirc     = tax*RECIRC_MULT;                     \/\/ SOFT: public $ re-spent in community\n  const taxBreak = {hotelTOT,salesTax,rentalTax,stateTax};\n  const partners = {};\n  for(const s in L.mix){ partners[s] = directSpend*L.mix[s]*1.0 + influenced*L.mix[s]*0.6; }\n  const revAssist = L.kiosks*1500 + (L.kiosks>5?L.kiosks*1100:L.kiosks*700); \/\/ sponsored + seasonal ad\n  return {exposures,interactions,highIntent,conversions,directSpend,direct,influenced,total,taxLocal,taxState,tax,taxBreak,recirc,partners,revAssist};\n}\nfunction seriesFor(L,k=1){\n  const m=deriveMetrics(L,k); const sh=SEASON[L.season];\n  const base=m.total\/sh.reduce((a,b)=>a+b,0);\n  const order=[6,7,8,9,10,11,0,1,2,3,4,5];\n  return order.map(i=>base*sh[i]);\n}\nfunction rollup(k=1, locs=LOCS()){\n  const acc={exposures:0,interactions:0,highIntent:0,conversions:0,directSpend:0,direct:0,influenced:0,total:0,taxLocal:0,taxState:0,tax:0,recirc:0,revAssist:0,kiosks:0,screens:0,\n    partners:{hotels:0,dining:0,attractions:0,events:0}, taxBreak:{hotelTOT:0,salesTax:0,rentalTax:0,stateTax:0}};\n  locs.forEach(L=>{const m=deriveMetrics(L,k);for(const key in acc){\n    if(key==='partners'){for(const s in acc.partners)acc.partners[s]+=m.partners[s];}\n    else if(key==='taxBreak'){for(const s in acc.taxBreak)acc.taxBreak[s]+=m.taxBreak[s];}\n    else if(key==='kiosks'){acc.kiosks+=L.kiosks;}\n    else if(key==='screens'){acc.screens+=(L.screens||0);}\n    else if(m[key]!=null)acc[key]+=m[key];}});\n  return acc;\n}\nfunction rollupSeries(k=1, locs=LOCS()){\n  const t=new Array(12).fill(0);\n  locs.forEach(L=>{const s=seriesFor(L,k);s.forEach((v,i)=>t[i]+=v);});\n  return t;\n}\n\n\/* ---------- (network roll-up retained but unused in single-tenant) ---------- *\/\nconst NETWORK={ destinations:1, kiosks:20, targetTotal:0, targetTax:0, targetActions:0 };\nfunction mergeRollups(list){\n  const acc={exposures:0,interactions:0,highIntent:0,conversions:0,directSpend:0,direct:0,influenced:0,total:0,taxLocal:0,taxState:0,tax:0,recirc:0,revAssist:0,kiosks:0,screens:0,\n    partners:{hotels:0,dining:0,attractions:0,events:0}, taxBreak:{hotelTOT:0,salesTax:0,rentalTax:0,stateTax:0}};\n  list.forEach(m=>{for(const key in acc){\n    if(key==='partners'){for(const s in acc.partners)acc.partners[s]+=m.partners[s];}\n    else if(key==='taxBreak'){for(const s in acc.taxBreak)acc.taxBreak[s]+=m.taxBreak[s];}\n    else if(m[key]!=null)acc[key]+=m[key];}});\n  return acc;\n}\nfunction scaleRollup(m,f){const o=JSON.parse(JSON.stringify(m));for(const key in o){ if(key==='partners'||key==='taxBreak'){for(const s in o[key])o[key][s]*=f;} else o[key]*=f; }return o;}\nconst NET_IDS=['evv'];\nfunction destRollup(id,k){return rollup(k, DESTINATIONS[id].locations);}\nfunction networkAgg(k=1){const parts=NET_IDS.map(id=>destRollup(id,k));const real=mergeRollups(parts);const net=scaleRollup(real,1);net.kiosks=real.kiosks;net.destinations=1;return {real,net,others:scaleRollup(real,0),scale:1,parts};}\nfunction networkSeries(k=1){return rollupSeries(k, LOCS());}\n\n\/* ==================================================================\n   ENGAGEMENT DRILL-THROUGH \u2014 ILLUSTRATIVE module and campaign sets.\n   No TrueOmni Product & Scope Definition document exists for Explore\n   Evansville, so these are the modules that fit a sports-tourism-led\n   mid-market DMO, not a contracted scope. Shares sum to 1.0.\n================================================================== *\/\nconst MODULES=[\n  {id:'map',    name:'OMNI Maps',                      tag:'attractions', share:.15, dwell:80,  intentRel:0.9, convRel:0.8},\n  {id:'sports', name:'Sports & Event Schedules',       tag:'events',      share:.14, dwell:112, intentRel:1.5, convRel:1.4},\n  {id:'itin',   name:'OMNI Itinerary',                 tag:'attractions', share:.12, dwell:150, intentRel:1.9, convRel:1.6},\n  {id:'wayfind',name:'OMNI Wayfinding',                tag:'attractions', share:.11, dwell:70,  intentRel:0.7, convRel:0.6},\n  {id:'dine',   name:'Dining & Restaurants',           tag:'dining',      share:.11, dwell:98,  intentRel:1.3, convRel:1.2},\n  {id:'events', name:'Events Calendar',                tag:'events',      share:.10, dwell:86,  intentRel:1.1, convRel:1.0},\n  {id:'deals',  name:'Deals & Coupons',                tag:'events',      share:.10, dwell:120, intentRel:2.1, convRel:1.9},\n  {id:'stay',   name:'Lodging & Hotels',               tag:'hotels',      share:.07, dwell:110, intentRel:1.7, convRel:1.6},\n  {id:'ads',    name:'Advertising \/ Media Network',    tag:'events',      share:.06, dwell:46,  intentRel:0.8, convRel:0.7},\n  {id:'lang',   name:'Multi-language & ADA',           tag:'attractions', share:.04, dwell:40,  intentRel:0.5, convRel:0.4},\n];\nconst CAMP_TYPE={ 'Pass \/ loyalty':'#1C9CD8','Automation':'#1BAF7A','Partner co-op':'#EB6834','Group \/ MICE':'#14508C','Paid media':'#E87BA4','Content':'#008300','Itinerary \/ CRM':'#6B4FB0','Promotions':'#EDA100' };\nconst CAMPAIGNS=[\n  {id:'sports',    name:'Sports Tournament Hosting',            type:'Group \/ MICE',   share:.20, intentRel:1.5, convRel:1.5, cpi:0.85},\n  {id:'sponsored', name:'Sponsored Placements (local advertisers)', type:'Paid media',  share:.16, intentRel:0.9, convRel:0.8, cpi:0.55},\n  {id:'riverfront',name:'Ohio Riverfront & Downtown',           type:'Content',        share:.12, intentRel:1.0, convRel:0.9, cpi:0.70},\n  {id:'meetings',  name:'Meetings & Conventions Co-op',         type:'Group \/ MICE',   share:.11, intentRel:1.2, convRel:1.4, cpi:0.95},\n  {id:'drive',     name:'Drive-Market Getaway (3-hour radius)', type:'Automation',     share:.11, intentRel:1.3, convRel:1.4, cpi:0.60},\n  {id:'passport',  name:'Evansville Attractions Pass',          type:'Pass \/ loyalty', share:.10, intentRel:1.6, convRel:1.5, cpi:0.90},\n  {id:'dineweek',  name:'Restaurant Week & Culinary Trail',     type:'Partner co-op',  share:.10, intentRel:1.3, convRel:1.2, cpi:1.10},\n  {id:'flash',     name:'Flash Deals & Coupons',                type:'Promotions',     share:.10, intentRel:1.4, convRel:1.7, cpi:0.95},\n];\nconst AB_TESTS=[\n  {id:'t1', camp:'sports',    name:'Sports Tournament Hosting \u2014 hero creative', a:'Team photo', b:'Family weekend', split:.5, bLift:1.15, conf:0.95, status:'B winning'},\n  {id:'t2', camp:'drive',     name:'Drive-Market Getaway \u2014 CTA copy',           a:'\u201cPlan your weekend\u201d', b:'\u201cBuild my itinerary\u201d', split:.5, bLift:1.11, conf:0.92, status:'B winning'},\n  {id:'t3', camp:'sponsored', name:'Sponsored placement \u2014 layout',              a:'Carousel', b:'Full-card', split:.5, bLift:0.94, conf:0.88, status:'A winning'},\n  {id:'t4', camp:'passport',  name:'Attractions Pass \u2014 offer framing',          a:'\u201cSave 20%\u201d', b:'\u201c5 attractions, 1 pass\u201d', split:.5, bLift:1.06, conf:0.71, status:'No winner yet'},\n];\nfunction splitFunnel(m, items, segShares){\n  const sSum=items.reduce((a,b)=>a+b.share,0);\n  const rows=items.map(it=>{\n    let w=it.share\/sSum;\n    if(segShares && it.tag){ w*=Math.max(0.35, 1+0.7*((segShares[it.tag]||.25)-0.25)); }\n    return {it, w};\n  });\n  const wSum=rows.reduce((a,b)=>a+b.w,0);\n  rows.forEach(r=>r.w\/=wSum);\n  const hiRaw=rows.map(r=>r.w*r.it.intentRel), hiS=hiRaw.reduce((a,b)=>a+b,0);\n  const cvRaw=rows.map((r,i)=>hiRaw[i]*r.it.convRel), cvS=cvRaw.reduce((a,b)=>a+b,0);\n  return rows.map((r,i)=>{\n    const interactions=m.interactions*r.w;\n    const highIntent=m.highIntent*hiRaw[i]\/hiS;\n    const conversions=m.conversions*cvRaw[i]\/cvS;\n    const exposures=m.exposures*r.w;\n    const impact=m.total*cvRaw[i]\/cvS;\n    const timeHrs=r.it.dwell? interactions*r.it.dwell\/3600 : null;\n    const spend=r.it.cpi!=null? interactions*r.it.cpi : null;\n    return {...r.it, exposures, interactions, highIntent, conversions, impact, timeHrs, spend,\n      convRate:conversions\/interactions, roas:spend?impact\/spend:null, valPerK:impact\/(interactions\/1000)};\n  });\n}\nfunction segSharesOf(m){const t=Object.values(m.partners).reduce((a,b)=>a+b,0)||1;const o={};for(const s in m.partners)o[s]=m.partners[s]\/t;return o;}\n<\/script>\n\n<!-- =================== FORMAT + CHART HELPERS =================== -->\n<script id=\"helpers\">\nconst $=(s,r=document)=>r.querySelector(s);\nconst NS='http:\/\/www.w3.org\/2000\/svg';\nfunction el(t,a={},kids=[]){const e=document.createElementNS(NS,t);for(const k in a)e.setAttribute(k,a[k]);(Array.isArray(kids)?kids:[kids]).forEach(c=>c!=null&&e.appendChild(typeof c==='string'?document.createTextNode(c):c));return e;}\nlet CUR='USD';                 \/\/ US destination \u2014 USD only, no toggle\nconst FX={USD:1};              \/\/ single currency; no FX conversion\nfunction curSym(){return '$';}\nfunction money(v){v=v*FX[CUR];const s=v<0?'-':'';v=Math.abs(v);const c=curSym();\n  if(v>=1e9)return s+c+(v\/1e9).toFixed(v>=1e10?0:2).replace(\/\\.0+$\/,'')+'B';\n  if(v>=1e6)return s+c+(v\/1e6).toFixed(v>=1e7?1:2).replace(\/\\.?0+$\/,'')+'M';\n  if(v>=1e3)return s+c+(v\/1e3).toFixed(0)+'K';\n  return s+c+Math.round(v);}\nfunction money2(v){return curSym()+Math.round(v*FX[CUR]).toLocaleString();}\nfunction num(v){if(v>=1e6)return (v\/1e6).toFixed(v>=1e7?1:2).replace(\/\\.?0+$\/,'')+'M';if(v>=1e3)return (v\/1e3).toFixed(v>=1e4?0:1).replace(\/\\.0$\/,'')+'K';return Math.round(v).toLocaleString();}\nfunction pct(v,d=0){return (v*100).toFixed(d)+'%';}\n\nconst TT=$('#tt');\nfunction showTT(html,e){TT.innerHTML=html;TT.style.opacity=1;moveTT(e);}\nfunction moveTT(e){const p=12;let x=e.clientX+p,y=e.clientY+p;const r=TT.getBoundingClientRect();if(x+r.width>innerWidth-8)x=e.clientX-r.width-p;if(y+r.height>innerHeight-8)y=e.clientY-r.height-p;TT.style.left=x+'px';TT.style.top=y+'px';}\nfunction hideTT(){TT.style.opacity=0;}\n\n\/* ---- Area\/line trend chart with crosshair+tooltip ---- *\/\nfunction areaChart(values,labels,opt={}){\n  const w=opt.w||660,h=opt.h||210,pl=42,pr=16,pt=14,pb=26;\n  const iw=w-pl-pr,ih=h-pt-pb;\n  const max=Math.max(...values)*1.12,min=0;\n  const X=i=>pl+iw*(i\/(values.length-1));\n  const Y=v=>pt+ih*(1-(v-min)\/(max-min));\n  const svg=el('svg',{viewBox:`0 0 ${w} ${h}`,width:'100%',role:'img'});\n  \/\/ gridlines + y ticks\n  const ticks=4;\n  for(let t=0;t<=ticks;t++){const val=max*t\/ticks;const y=Y(val);\n    svg.appendChild(el('line',{x1:pl,x2:w-pr,y1:y,y2:y,stroke:'var(--grid)','stroke-width':1}));\n    svg.appendChild(el('text',{x:pl-8,y:y+3.5,'text-anchor':'end','font-size':10,fill:'var(--muted)'},money(val)));\n  }\n  \/\/ area path\n  let d='M'+X(0)+' '+Y(values[0]);values.forEach((v,i)=>{if(i)d+=' L'+X(i)+' '+Y(v);});\n  let area=d+` L${X(values.length-1)} ${Y(0)} L${X(0)} ${Y(0)} Z`;\n  const gid='g'+Math.random().toString(36).slice(2,7);\n  const defs=el('defs');const lg=el('linearGradient',{id:gid,x1:0,y1:0,x2:0,y2:1});\n  lg.appendChild(el('stop',{offset:'0%','stop-color':'var(--azure)','stop-opacity':.28}));\n  lg.appendChild(el('stop',{offset:'100%','stop-color':'var(--azure)','stop-opacity':.02}));\n  defs.appendChild(lg);svg.appendChild(defs);\n  svg.appendChild(el('path',{d:area,fill:`url(#${gid})`}));\n  svg.appendChild(el('path',{d,fill:'none',stroke:'var(--azure)','stroke-width':2.4,'stroke-linejoin':'round','stroke-linecap':'round'}));\n  \/\/ x labels (every other)\n  labels.forEach((lb,i)=>{if(i%2===0||i===labels.length-1)svg.appendChild(el('text',{x:X(i),y:h-8,'text-anchor':'middle','font-size':10,fill:'var(--muted)'},lb));});\n  \/\/ end dot\n  svg.appendChild(el('circle',{cx:X(values.length-1),cy:Y(values.at(-1)),r:4.5,fill:'var(--azure)',stroke:'var(--surface)','stroke-width':2}));\n  \/\/ crosshair layer\n  const cx=el('line',{x1:0,x2:0,y1:pt,y2:pt+ih,stroke:'var(--azure)','stroke-width':1,'stroke-dasharray':'3 3',opacity:0});\n  const cdot=el('circle',{r:5,fill:'var(--azure)',stroke:'var(--surface)','stroke-width':2,opacity:0});\n  svg.appendChild(cx);svg.appendChild(cdot);\n  const hit=el('rect',{x:pl,y:pt,width:iw,height:ih,fill:'transparent'});\n  hit.addEventListener('mousemove',ev=>{\n    const rect=svg.getBoundingClientRect();const rel=(ev.clientX-rect.left)\/rect.width*w;\n    let i=Math.round((rel-pl)\/iw*(values.length-1));i=Math.max(0,Math.min(values.length-1,i));\n    cx.setAttribute('x1',X(i));cx.setAttribute('x2',X(i));cx.setAttribute('opacity',.6);\n    cdot.setAttribute('cx',X(i));cdot.setAttribute('cy',Y(values[i]));cdot.setAttribute('opacity',1);\n    showTT(`<div class=\"tt-t\">${labels[i]} 2026<\/div><div class=\"tt-r\">Economic impact <b>${money(values[i])}<\/b><\/div>`,ev);\n  });\n  hit.addEventListener('mouseleave',()=>{cx.setAttribute('opacity',0);cdot.setAttribute('opacity',0);hideTT();});\n  svg.appendChild(hit);\n  return svg;\n}\n\n\/* ---- horizontal ranked stacked bars (tax local+state, per location) ---- *\/\nfunction rankedStacked(rows,opt={}){\n  \/\/ rows: [{label, parts:[{v,color,name}], total, sub, onClick}]\n  const fmt=opt.fmt||money, tfmt=opt.tfmt||money2;\n  const w=opt.w||620,rowH=34,gap=10,pl=opt.pl||120,pr=opt.pr||64,pt=6;\n  const h=pt+rows.length*(rowH+gap);\n  const max=Math.max(...rows.map(r=>r.total))*1.02;\n  const iw=w-pl-pr;\n  const svg=el('svg',{viewBox:`0 0 ${w} ${h}`,width:'100%'});\n  rows.forEach((r,ri)=>{\n    const y=pt+ri*(rowH+gap);\n    svg.appendChild(el('text',{x:pl-10,y:y+rowH\/2+4,'text-anchor':'end','font-size':12,'font-weight':600,fill:'var(--text)'},r.label));\n    let x=pl;\n    r.parts.forEach((p,pi)=>{\n      const bw=iw*(p.v\/max);\n      const g=el('g',{class:'barseg',style:'cursor:pointer'});\n      const rc=el('rect',{x:x,y:y,width:Math.max(0,bw-2),height:rowH,rx:(pi===r.parts.length-1?6:0),fill:p.color});\n      g.appendChild(rc);\n      g.addEventListener('mousemove',ev=>showTT(`<div class=\"tt-t\">${r.label}<\/div><div class=\"tt-r\">${p.name} <b>${tfmt(p.v)}<\/b><\/div>`,ev));\n      g.addEventListener('mouseleave',hideTT);\n      if(r.onClick)g.addEventListener('click',r.onClick);\n      svg.appendChild(g);x+=bw;\n    });\n    svg.appendChild(el('text',{x:x+8,y:y+rowH\/2+4,'font-size':12.5,'font-weight':700,fill:'var(--text)'},fmt(r.total)));\n  });\n  return svg;\n}\n\n\/* ---- donut for partner mix ---- *\/\nfunction donut(parts,opt={}){ \/\/ parts:[{v,color,name}]\n  const size=opt.size||190,r=size\/2,rin=r*0.62,cx=r,cy=r;\n  const tot=parts.reduce((a,p)=>a+p.v,0);let a0=-Math.PI\/2;\n  const svg=el('svg',{viewBox:`0 0 ${size} ${size}`,width:size,height:size});\n  parts.forEach(p=>{\n    const a1=a0+ (p.v\/tot)*Math.PI*2;\n    const x0=cx+r*Math.cos(a0),y0=cy+r*Math.sin(a0),x1=cx+r*Math.cos(a1),y1=cy+r*Math.sin(a1);\n    const xi0=cx+rin*Math.cos(a0),yi0=cy+rin*Math.sin(a0),xi1=cx+rin*Math.cos(a1),yi1=cy+rin*Math.sin(a1);\n    const large=(a1-a0)>Math.PI?1:0;\n    const d=`M${x0} ${y0} A${r} ${r} 0 ${large} 1 ${x1} ${y1} L${xi1} ${yi1} A${rin} ${rin} 0 ${large} 0 ${xi0} ${yi0} Z`;\n    const path=el('path',{d,fill:p.color,stroke:'var(--surface)','stroke-width':2,style:'cursor:pointer;transition:.15s'});\n    path.addEventListener('mousemove',ev=>showTT(`<div class=\"tt-t\">${p.name}<\/div><div class=\"tt-r\">Impact <b>${money(p.v)}<\/b><\/div><div class=\"tt-r\">Share <b>${pct(p.v\/tot,0)}<\/b><\/div>`,ev));\n    path.addEventListener('mouseleave',hideTT);\n    if(p.onClick)path.addEventListener('click',p.onClick);\n    svg.appendChild(path);a0=a1;\n  });\n  svg.appendChild(el('text',{x:cx,y:cy-3,'text-anchor':'middle','font-size':20,'font-weight':700,fill:'var(--text)'},money(tot)));\n  svg.appendChild(el('text',{x:cx,y:cy+14,'text-anchor':'middle','font-size':10.5,fill:'var(--muted)'},'partner impact'));\n  return svg;\n}\n\n\/* ---- stacked column: direct vs influenced by location ---- *\/\nfunction stackedCols(rows,opt={}){ \/\/ rows:[{label,direct,influenced,onClick}]\n  const w=opt.w||620,h=opt.h||230,pl=42,pr=10,pt=12,pb=34;\n  const iw=w-pl-pr,ih=h-pt-pb,n=rows.length;\n  const max=Math.max(...rows.map(r=>r.direct+r.influenced))*1.14;\n  const bw=Math.min(30,iw\/n*0.52),slot=iw\/n;\n  const Y=v=>pt+ih*(1-v\/max);\n  const svg=el('svg',{viewBox:`0 0 ${w} ${h}`,width:'100%'});\n  for(let t=0;t<=4;t++){const val=max*t\/4,y=Y(val);svg.appendChild(el('line',{x1:pl,x2:w-pr,y1:y,y2:y,stroke:'var(--grid)','stroke-width':1}));svg.appendChild(el('text',{x:pl-8,y:y+3.5,'text-anchor':'end','font-size':10,fill:'var(--muted)'},money(val)));}\n  rows.forEach((r,i)=>{\n    const cx=pl+slot*i+slot\/2, x=cx-bw\/2;\n    const hD=ih*r.direct\/max, hI=ih*r.influenced\/max;\n    const yD=Y(r.direct), yI=Y(r.direct+r.influenced);\n    const gI=el('rect',{x,y:yI,width:bw,height:Math.max(0,hI-1),rx:5,fill:'var(--s-influenced)',style:'cursor:pointer'});\n    const gD=el('rect',{x,y:yD,width:bw,height:hD,rx:0,fill:'var(--s-direct)',style:'cursor:pointer'});\n    [ ['Direct',r.direct,gD],['Influenced',r.influenced,gI] ].forEach(([nm,v,g])=>{\n      g.addEventListener('mousemove',ev=>showTT(`<div class=\"tt-t\">${r.label}<\/div><div class=\"tt-r\">${nm} <b>${money(v)}<\/b><\/div><div class=\"tt-r\">Total <b>${money(r.direct+r.influenced)}<\/b><\/div>`,ev));\n      g.addEventListener('mouseleave',hideTT);if(r.onClick)g.addEventListener('click',r.onClick);\n    });\n    svg.appendChild(gI);svg.appendChild(gD);\n    svg.appendChild(el('text',{x:cx,y:h-19,'text-anchor':'middle','font-size':10,'font-weight':600,fill:'var(--text-2)'},r.label));\n    svg.appendChild(el('text',{x:cx,y:h-8,'text-anchor':'middle','font-size':9.5,fill:'var(--muted)'},money(r.direct+r.influenced)));\n  });\n  return svg;\n}\n<\/script>\n\n<!-- =================== AI NARRATIVE ENGINE =================== -->\n<script id=\"ai\">\n\/* Lightweight on-device narrative generator. Reads the derived model and writes\n   the dollars-first, council-ready sentence a director takes into a budget meeting.\n   (In production this is the TrueImpact AI summarizer over the live attribution feed.) *\/\nfunction aiOverview(k){\n  const m=rollup(k), locs=LOCS();\n  const best=[...locs].sort((a,b)=>deriveMetrics(b,k).total-deriveMetrics(a,k).total)[0];\n  const rate=[...locs].sort((a,b)=>b.interactionRate-a.interactionRate)[0];\n  const sg=signageMetrics(k);\n  return `Across a modeled <b>${m.kiosks}-kiosk<\/b>${sg?` and <b>${sg.screens}-screen<\/b>`:''} network in <b>${locs.length} Evansville deployment zones<\/b>, TrueImpact projects <span class=\"em\">${money(m.total)}<\/span> in visitor-driven economic impact and <span class=\"em\">${money(m.tax)}<\/span> in estimated public tax \u2014 of which <b>${money(m.taxLocal)}<\/b> is Vanderburgh County innkeeper&rsquo;s tax that comes back to fund the destination. <b>${best.name}<\/b> leads on impact; <b>${rate.name}<\/b> engages the highest share of visitors at <b>${pct(rate.interactionRate)}<\/b>. Evansville is a sports-tourism market \u2014 69% of booked events are sports-related \u2014 and the sports complexes carry the highest per-visitor spend because tournament families book rooms. Figures are modeled against a client-directed 3.0M annual-visitor planning estimate (Explore Evansville publishes no visitor total) and TrueOmni platform benchmarks; at go-live every dollar is ledgered to a live kiosk event. An estimated <span class=\"em\">${money(m.recirc)}<\/span> re-circulates through the local economy.`;\n}\nfunction aiTax(k){\n  const m=rollup(k),b=m.taxBreak,locs=LOCS();\n  const top=Object.entries(b).sort((x,y)=>y[1]-x[1])[0];\n  const nm={hotelTOT:'County innkeeper&rsquo;s tax',salesTax:'Indiana sales & use tax on lodging, dining & retail',rentalTax:'Auto rental excise',stateTax:'Indiana sales & use tax on attractions'}[top[0]];\n  const hi=[...locs].sort((a,b)=>b.tax.tot-a.tax.tot)[0], lo=[...locs].sort((a,b)=>a.tax.tot-b.tax.tot)[0];\n  const cmp = hi.tax.tot!==lo.tax.tot ? ` Because rates are set locally, the same visitor is worth more in <b>${hi.name} (${hi.tax.tot}% innkeeper&rsquo;s tax)<\/b> than in <b>${lo.name} (${lo.tax.tot}%)<\/b>.` : ' Rates are uniform county-wide, so a visitor yields the same tax profile in every zone \u2014 what differs is how much they spend and on what.';\n  return `Attributed visitor spending is projected to generate an estimated <span class=\"em\">${money(m.tax)}<\/span> in tax this period \u2014 <b>${money(m.taxLocal)}<\/b> in <b>Vanderburgh County innkeeper&rsquo;s tax (8%)<\/b> that returns to the destination, and <b>${money(m.taxState)}<\/b> in Indiana state sales, use and rental excise tax. These rates are real, not assumed. Indiana levies no local sales-tax add-on, so the 8% innkeeper&rsquo;s tax is the <i>only<\/i> line that comes home \u2014 and it is earmarked for tourism capital projects, destination marketing and Old National Events Plaza operations. The single largest line is <b>${nm}<\/b> at <span class=\"em\">${money(top[1])}<\/span>.${cmp} Re-spent through public budgets, the local share drives an estimated <span class=\"em\">${money(m.recirc)}<\/span> of induced local activity \u2014 a soft benefit on top of the hard capture.`;\n}\nfunction aiLocation(L,k){\n  const m=deriveMetrics(L,k),r=L.tax;\n  return `<b>${L.name}<\/b> is projected to turn <b>${num(m.interactions)}<\/b> kiosk interactions into <span class=\"em\">${money(m.total)}<\/span> of economic impact and <span class=\"em\">${money(m.tax)}<\/span> of tax (innkeeper&rsquo;s ${r.tot}%, Indiana sales ${r.sales}%, rental ${r.rental}%)${L.screens?`, alongside <b>${L.screens}<\/b> digital-signage screens delivering broadcast reach`:''}. ${L.note} Partners captured <b>${money(Object.values(m.partners).reduce((a,b)=>a+b,0))}<\/b>, led by ${SEG[Object.entries(m.partners).sort((a,b)=>b[1]-a[1])[0][0]].name.toLowerCase()}.`;\n}\nfunction aiNetwork(k){\n  const {net}=networkAgg(k);\n  return `Across the full TrueOmni network \u2014 <b>${net.destinations} destinations<\/b> and <b>${num(net.kiosks)} kiosks<\/b> in North America and Japan \u2014 the platform attributed <span class=\"em\">${money(net.total)}<\/span> of visitor-driven economic impact and <span class=\"em\">${money(net.tax)}<\/span> in estimated public tax revenue this period. This is the first time the destination industry has an aggregate impact number built from <b>ledgered first-party behavioral data<\/b> rather than modeled surveys. Every destination below drills down to its own kiosks.`;\n}\nfunction aiEngagement(rows, mode, scopeName){\n  const attn=[...rows].sort((a,b)=>b.interactions-a.interactions)[0];\n  const val=[...rows].sort((a,b)=>b.impact-a.impact)[0];\n  const invest= mode==='campaigns'\n      ? [...rows].filter(r=>r.roas).sort((a,b)=>b.roas-a.roas)[0]\n      : [...rows].sort((a,b)=>b.valPerK-a.valPerK)[0];\n  const gap = attn.id!==val.id\n      ? ` The gap is the story: <b>${attn.name}<\/b> draws the most attention, but <b>${val.name}<\/b> converts it into the most attributed dollars \u2014 so raw attention isn't the same as value.`\n      : ` <b>${attn.name}<\/b> both draws the most attention and drives the most dollars.`;\n  const investLine = mode==='campaigns'\n      ? ` For spend, <b>${invest.name}<\/b> returns the best ROI at <span class=\"em\">${invest.roas.toFixed(1)}\u00d7<\/span> \u2014 invest here first.`\n      : ` <b>${invest.name}<\/b> punches above its attention (${money(invest.valPerK)} attributed per 1K interactions) \u2014 the efficient place to feature and cross-promote.`;\n  return `In <b>${scopeName}<\/b>, the ${mode==='campaigns'?'campaigns':'kiosk modules'} split the funnel from exposure to attributed conversion.${gap}${investLine} Rank by any funnel stage using the metric toggle; filter by market to see how the mix shifts location to location.`;\n}\nfunction aiPartner(k){\n  const m=rollup(k),tot=Object.values(m.partners).reduce((a,b)=>a+b,0);\n  const top=Object.entries(m.partners).sort((a,b)=>b[1]-a[1])[0];\n  return `TrueImpact attributed <span class=\"em\">${money(tot)}<\/span> of visitor spending to partner businesses \u2014 hotels, restaurants, attractions and event venues \u2014 every dollar tied to a kiosk referral, QR scan, pass pull or partner-POS event. <b>${SEG[top[0]].name}<\/b> captured the most at <span class=\"em\">${money(top[1])}<\/span>. This is the number a partner sees in their own portal \u2014 and for Explore Evansville it is the answer to the question every hotel, restaurant and retailer on the East Side asks: what did the destination&rsquo;s marketing actually do for me?`;\n}\nfunction aiBanner(tag,html){\n  return `<div class=\"ai-banner fade\"><div class=\"ai-ic\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 3l1.9 4.6L18 9l-4.1 1.4L12 15l-1.9-4.6L6 9l4.1-1.4zM19 14l.9 2.2L22 17l-2.1.8L19 20l-.9-2.2L16 17l2.1-.8z\" fill=\"#fff\"\/><\/svg><\/div><div><span class=\"ai-tag\">${tag}<\/span><div class=\"ai-txt\">${html}<\/div><\/div><\/div>`;\n}\n<\/script>\n\n<!-- =================== APP \/ ROUTER \/ PAGES =================== -->\n<script id=\"app-logic\">\nlet PERIOD='t12';\nlet engMode='modules', engLoc='all', engMetric='interactions';   \/\/ engagement drill-through filters\nconst app=$('#app');\nfunction K(){return PERIODS[PERIOD].k;}\nfunction periodLabel(){return PERIODS[PERIOD].label;}\n\n\/* ---------- helpers to build DOM cards ---------- *\/\nfunction h(html){const t=document.createElement('template');t.innerHTML=html.trim();return t.content.firstChild;}\nfunction card(title,hint,bodyNodes,cls=''){\n  const c=h(`<div class=\"card ${cls}\"><div class=\"card-h\"><div><h3>${title}${hint?` <span class=\"hint\">${hint}<\/span>`:''}<\/h3><\/div><\/div><\/div>`);\n  (Array.isArray(bodyNodes)?bodyNodes:[bodyNodes]).forEach(n=>n&&c.appendChild(typeof n==='string'?h(n):n));\n  return c;\n}\nfunction legend(items){const l=h('<div class=\"legend\"><\/div>');items.forEach(it=>l.appendChild(h(`<span class=\"li\"><span class=\"sw ${it.line?'line':''}\" style=\"background:${it.color}\"><\/span>${it.name}<\/span>`)));return l;}\nfunction shortName(n){return n.replace('Downtown & Visitor Center','Downtown \/ Visitor Ctr').replace('Ohio Riverfront & The Pagoda','Riverfront \/ Pagoda').replace('Ford Center & Victory Theatre','Ford Center').replace('Old National Events Plaza','Events Plaza').replace('Eastland Mall & East Side Corridor','Eastland \/ East Side').replace('Deaconess Sports Park','Deaconess Sports').replace('Goebel Soccer Complex','Goebel Soccer').replace('Mesker Park Zoo & Botanic Garden','Mesker Park Zoo').replace('Evansville Regional Airport (EVV)','EVV Airport').replace('Museum District','Museums').replace('Haynie\u2019s Corner Arts District','Haynie\u2019s Corner').replace('University Corridor \u00b7 UE & USI','UE & USI').replace('Wesselman Woods & Angel Mounds','Woods \/ Angel Mounds').replace(' Lake','').replace(' Valley','').replace(' Bay','').replace('Fort ','Ft ').replace(' Springs','').replace('San Francisco','SF').replace('Los Angeles','LA').replace('Magnificent Mile','Mag Mile').replace('McCormick Place','McCormick').replace('Museum Campus','Museum').split(' (')[0];}\nfunction engShort(n){return n.replace(\/\\s*\\(.*\\)\/,'').replace('Interactive Map & Wayfinding','Map & Wayfinding').replace(' Placements','').replace('Local ','').replace('-Season Getaway','-Season').replace(' & Coupons','').replace(' Push','').replace(' Welcome','').replace(' & Restaurants','').replace(' to Do & Attractions',' to Do').replace(' Builder','').replace(' Calendar','').replace(' & Parking','');}\nfunction setDest(id){activeDest=id;engLoc='all';location.hash='#\/overview';render();}\nfunction engMiniCard(k){\n  const sc=engScope(k); const rows=splitFunnel(sc.m, MODULES, sc.seg).sort((a,b)=>b.interactions-a.interactions).slice(0,5);\n  const max=rows[0].interactions;\n  const c=card('Module &amp; campaign engagement','what draws attention \u2014 drill the funnel','',' ');\n  const list=h('<div class=\"loclist\"><\/div>');\n  rows.forEach(r=>{const row=h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div><div class=\"lr-name\" style=\"display:flex;align-items:center;gap:7px\"><span class=\"sw\" style=\"width:11px;height:11px;border-radius:3px;background:${SEG[r.tag].color}\"><\/span>${r.name}<\/div><\/div><div class=\"lr-val\">${num(r.interactions)}<div class=\"lr-sub\" style=\"font-weight:600\">${money(r.impact)}<\/div><\/div><div class=\"lr-bar\"><i style=\"width:${(r.interactions\/max*100).toFixed(0)}%\"><\/i><\/div><\/div>`);\n    row.addEventListener('click',()=>go('#\/modules'));list.appendChild(row);});\n  c.appendChild(list);\n  const btns=h('<div style=\"display:flex;gap:8px;margin-top:12px\"><\/div>');\n  btns.appendChild(h(`<button class=\"chip\" style=\"cursor:pointer\" onclick=\"go('#\/modules')\">Modules \u203a<\/button>`));\n  btns.appendChild(h(`<button class=\"chip\" style=\"cursor:pointer\" onclick=\"go('#\/campaigns')\">Campaigns &amp; A\/B tests \u203a<\/button>`));\n  c.appendChild(btns);\n  return c;\n}\n\n\/* ================= OVERVIEW ================= *\/\nfunction pageOverview(){\n  const k=K(),m=rollup(k);\n  const wrap=h('<div class=\"fade\"><\/div>');\n  wrap.appendChild(h(`<div class=\"pagehead\"><div><div class=\"eyebrow\">${ACT().kind} \u00b7 Executive Dashboard<\/div><h1>${ACT().name} \u2014 ${ACT().scope} Impact<\/h1><\/div><div class=\"meta\">Reporting period<br><b style=\"color:var(--text);font-size:14px\">${periodLabel()}<\/b><br>${m.kiosks} kiosks \u00b7 ${LOCS().length} zones<\/div><\/div>`));\n  wrap.appendChild(h(`<div class=\"crumbs\"><span>${ACT().name}<\/span><span class=\"sep\">\u203a<\/span><a onclick=\"go('#\/overview')\">${ACT().region}<\/a><span class=\"sep\">\u203a<\/span><span>All zones<\/span><\/div>`));\n  wrap.appendChild(contextStrip()); wrap.lastChild.style.marginBottom='16px';\n  wrap.appendChild(h(aiBanner('TrueImpact AI \u00b7 Board-ready summary',aiOverview(k))));\n  wrap.appendChild(rampCard(k)); wrap.lastChild.style.marginBottom='16px';\n\n  \/\/ KPI band\n  const kpis=h('<div class=\"grid kpis\" style=\"margin-bottom:16px\"><\/div>');\n  kpis.appendChild(h(`<div class=\"card kpi hero\"><div class=\"glow\"><\/div><div class=\"k-label\">Total economic impact<\/div><div class=\"k-val\"><span class=\"cur\">${curSym()}<\/span>${money(m.total).replace(curSym(),'')}<\/div><div class=\"k-delta up\">\u25b2 18.4% vs prior period<\/div><div class=\"k-foot\">Direct ${money(m.direct)} + Influenced ${money(m.influenced)} \u00b7 dollars-first, ledger-level<\/div><\/div>`));\n  kpis.appendChild(kpiTile('Estimated tax revenue',money(m.tax),'\u25b2 16.1%',`County innkeeper's ${money(m.taxLocal)} \u00b7 Indiana state ${money(m.taxState)}`,()=>go('#\/tax')));\n  kpis.appendChild(kpiTile('Partner-captured spend',money(Object.values(m.partners).reduce((a,b)=>a+b,0)),'\u25b2 21.0%','Hotels \u00b7 dining \u00b7 retail &amp; attractions \u00b7 sports &amp; venues',()=>go('#\/partners')));\n  kpis.appendChild(kpiTile('Trackable visitor actions',num(m.interactions),'\u25b2 12.7%',`${num(m.conversions)} attributed conversions`));\n  wrap.appendChild(kpis);\n\n  \/\/ Map + location list\n  const mapRow=h('<div class=\"grid row-map\" style=\"margin-bottom:16px\"><\/div>');\n  mapRow.appendChild(card('Impact by kiosk location','click a market to drill in',[buildMap(k),legend([{name:'Bubble size = economic impact',color:'var(--azure)'}])],'pad0'+' '));\n  const mapCard=mapRow.lastChild;mapCard.style.padding='18px';\n  mapRow.appendChild(card('Zones ranked','by economic impact',[buildLocList(k)]));\n  wrap.appendChild(mapRow);\n\n  \/\/ Funnel + Direct\/influenced by location\n  const r2=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n  r2.appendChild(card('The visitor funnel',ACT().scope.toLowerCase(),[buildFunnel(m),h('<div class=\"note\">Exposure \u2192 interaction \u2192 high-intent action \u2192 attributed conversion. Rates are TrueOmni platform benchmarks; volumes are ledgered kiosk events.<\/div>')]));\n  const dcols=stackedCols(LOCS().map(L=>{const mm=deriveMetrics(L,k);return{label:shortName(L.name),direct:mm.direct,influenced:mm.influenced,onClick:()=>go('#\/location\/'+L.id)};}));\n  r2.appendChild(card('Direct vs influenced impact','by market \u00b7 click to drill',[dcols,legend([{name:'Direct (attributed spend)',color:'var(--s-direct)'},{name:'Influenced (supply-chain + wage tail)',color:'var(--s-influenced)'}])]));\n  wrap.appendChild(r2);\n\n  \/\/ Partner mix + tax preview\n  const r3=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n  r3.appendChild(buildPartnerCard(m,k));\n  r3.appendChild(buildTaxPreview(m,k));\n  wrap.appendChild(r3);\n\n  \/\/ Engagement entry\n  wrap.appendChild(engMiniCard(k));\n  wrap.lastChild.style.marginBottom='16px';\n\n  \/\/ Media Network entry\n  wrap.appendChild(mediaMiniCard(k));\n  wrap.lastChild.style.marginBottom='16px';\n\n  \/\/ Trend\n  const trend=card('Economic impact trend','monthly \u00b7 '+periodLabel(),[areaChart(rollupSeries(k),MONTHS,{h:220}),h(`<div class=\"note\">Set against a client-directed planning estimate of <b>3.0M annual visitors<\/b> (2.8\u20133.2M; Explore Evansville publishes no visitor total), this network is modeled to capture <b>${num(m.exposures\/K())}<\/b> kiosk encounters a year \u2014 <b>${pct(m.exposures\/K()\/3_000_000,0)}<\/b> of that base, within the 25\u201335% planning range for a network concentrated in the highest-traffic zones. Seasonality follows the youth-sports tournament calendar: a March championship bump (OVC\/MVC basketball, IHSAA wrestling), an April\u2013August tournament peak at Deaconess Sports Park and Goebel, a solid September\u2013October, and a winter trough. Shoulder-season automation is the largest untapped lever \u2014 and the shoulder months are exactly where a smaller destination loses share to larger ones.<\/div>`)]);\n  wrap.appendChild(trend);\n  return wrap;\n}\n\/* Destination context \u2014 the REAL, cited figures, surfaced above anything modeled.\n   The 3.0M visitor estimate is rendered separately and badged so it can never be\n   read as a published number. *\/\nfunction contextStrip(){\n  const c=card('Explore Evansville \u2014 destination context','published &amp; client-supplied figures \u00b7 cited on each tile \u00b7 <b>not modeled<\/b>','',' ');\n  const row=h('<div style=\"display:flex;gap:10px;flex-wrap:wrap;margin-top:2px\"><\/div>');\n  CONTEXT.cited.forEach(t=>row.appendChild(h(`<div style=\"flex:1 1 178px;min-width:168px;border:1px solid var(--line);border-radius:11px;padding:12px 13px;background:var(--surface-2)\"><div style=\"font-size:9.5px;font-weight:800;letter-spacing:1.2px;color:var(--s-attractions)\">\u25cf CITED<\/div><div style=\"font-size:21px;font-weight:800;letter-spacing:-.5px;margin-top:6px;line-height:1.15\">${t.val}<\/div><div style=\"font-size:11.5px;font-weight:700;margin-top:4px\">${t.label}<\/div><div style=\"font-size:10.5px;color:var(--text-2);margin-top:5px;line-height:1.42\">${t.sub}<\/div><div style=\"font-size:9.5px;color:var(--muted);margin-top:7px;line-height:1.35\">${t.src}<\/div><\/div>`)));\n  c.appendChild(row);\n  const md=CONTEXT.modeled;\n  c.appendChild(h(`<div style=\"margin-top:12px;border:1.5px dashed var(--warn);border-radius:11px;padding:13px 15px;background:rgba(194,100,31,.07)\"><div style=\"display:flex;align-items:baseline;gap:12px;flex-wrap:wrap\"><span style=\"font-size:9.5px;font-weight:800;letter-spacing:1.2px;color:var(--warn);border:1px solid var(--warn);border-radius:5px;padding:3px 7px\">MODELED ESTIMATE \u00b7 NOT PUBLISHED<\/span><span style=\"font-size:25px;font-weight:800;letter-spacing:-.6px\">${md.val}<\/span><span style=\"font-size:12px;font-weight:700;color:var(--text-2)\">${md.label} \u00b7 range ${md.range}<\/span><\/div><div style=\"font-size:11.5px;color:var(--text-2);margin-top:8px;line-height:1.55\">${md.note}<\/div><\/div>`));\n  c.appendChild(h(`<div class=\"note\" style=\"margin-top:12px\">${CONTEXT.visitorDef}<\/div>`));\n  return c;\n}\nfunction rampCard(k){\n  const NK=rollup(1).kiosks;\n  const c=card('Deployment ramp \u00b7 7 \u2192 20 kiosks \u00b7 3 \u2192 5 screens','projected run-rate as zones come online (modeled 24-week rollout)','',' ');\n  const list=h('<div class=\"loclist\"><\/div>');\n  let prevK=0, prevS=0;\n  PHASES.forEach(ph=>{\n    const locs=LOCS().filter(L=>ph.ids.includes(L.id));\n    const m=rollup(k,locs); const add=m.kiosks-prevK; prevK=m.kiosks;\n    const sg=signageMetrics(k,locs); const scr=sg?sg.screens:0; const addS=scr-prevS; prevS=scr;\n    const row=h(`<div class=\"locrow\"><div><div class=\"lr-name\">${ph.name}<\/div><div class=\"lr-sub\">${ph.window} \u00b7 ${m.kiosks} kiosks live${add?` (+${add})`:''}${sg?` \u00b7 ${scr} screens${addS?` (+${addS})`:''}`:''}<\/div><\/div><div class=\"lr-val\">${money(m.total)}<div class=\"lr-sub\" style=\"font-weight:600\">${money(m.tax)} tax \u00b7 ${money(m.taxLocal)} innkeeper's<\/div><\/div><div class=\"lr-bar\"><i style=\"width:${(m.kiosks\/NK*100).toFixed(0)}%\"><\/i><\/div><\/div>`);\n    list.appendChild(row);\n  });\n  c.appendChild(list);\n  c.appendChild(h('<div class=\"note\">Cumulative annualized run-rate at each phase. <b>Phase 1 is the fastest proof<\/b>: the official Explore Evansville visitor center downtown, The Pagoda on the riverfront, and the Ford Center \/ Old National Events Plaza cluster \u2014 all within walking distance, all already staffed. The sports complexes, Eastland Mall and EVV follow in Phase 2. Figures scale with units online, not with new demand. Phasing is MODELED; no rollout plan has been agreed.<\/div>'));\n  return c;\n}\nfunction kpiTile(label,val,delta,foot,onClick){\n  const c=h(`<div class=\"card kpi\"${onClick?' style=\"cursor:pointer\"':''}><div class=\"k-label\">${label}<\/div><div class=\"k-val\">${val}<\/div><div class=\"k-delta up\">\u25b2 ${delta.replace('\u25b2','').trim()}<\/div><div class=\"k-foot\">${foot}<\/div><\/div>`);\n  if(onClick)c.addEventListener('click',onClick);\n  return c;\n}\n\n\/* ---- Destination map (pixel-scale viewBox so marks\/labels stay true size).\n   Reads the active destination's outline + each location's x,y. Works for any tenant. ---- *\/\nfunction buildMap(k){\n  const D=ACT(), locs=LOCS();\n  const svg=el('svg',{viewBox:'0 0 480 620',role:'img','aria-label':D.region+' kiosk map'});\n  if(D.lake) svg.appendChild(el('path',{d:D.lake,fill:'var(--s-hotels)','fill-opacity':.12,stroke:'none'}));\n  svg.appendChild(el('path',{d:D.outline,class:'ca-outline'}));\n  if(D.lakeLabel) svg.appendChild(el('text',{x:D.lakeLabel.x,y:D.lakeLabel.y,'text-anchor':'middle','font-size':12,'font-style':'italic',fill:'var(--muted)',stroke:'none'},D.lakeLabel.t));\n  const max=Math.max(...locs.map(L=>deriveMetrics(L,k).total));\n  locs.forEach(L=>{\n    const mm=deriveMetrics(L,k);const rr=9+18*Math.sqrt(mm.total\/max);\n    const px=L.x,py=L.y;\n    const g=el('g',{class:'mk'+(state.loc===L.id?' active':''),transform:`translate(${px},${py})`});\n    g.appendChild(el('circle',{class:'ring',r:rr+5}));\n    g.appendChild(el('circle',{class:'pin',r:rr,fill:'var(--azure)','fill-opacity':.85}));\n    g.appendChild(el('circle',{class:'hit',r:Math.max(rr+7,16)}));\n    if(rr>16)g.appendChild(el('text',{y:4,'text-anchor':'middle','font-size':11,fill:'#fff',stroke:'none'},money(mm.total)));\n    g.appendChild(el('text',{y:rr+15,'text-anchor':'middle','font-size':11.5,'font-weight':700},L.name));\n    g.addEventListener('mousemove',ev=>showTT(`<div class=\"tt-t\">${L.name}<\/div><div class=\"tt-r\">Impact <b>${money(mm.total)}<\/b><\/div><div class=\"tt-r\">Tax <b>${money(mm.tax)}<\/b><\/div><div class=\"tt-r\">Interaction <b>${pct(L.interactionRate)}<\/b><\/div>`,ev));\n    g.addEventListener('mouseleave',hideTT);\n    g.addEventListener('click',()=>go('#\/location\/'+L.id));\n    svg.appendChild(g);\n  });\n  const box=h('<div class=\"mapwrap\"><\/div>');box.appendChild(svg);return box;\n}\nfunction buildLocList(k){\n  const rows=[...LOCS()].map(L=>({L,m:deriveMetrics(L,k)})).sort((a,b)=>b.m.total-a.m.total);\n  const max=rows[0].m.total;\n  const box=h('<div class=\"loclist\"><\/div>');\n  rows.forEach(({L,m})=>{\n    const row=h(`<div class=\"locrow\"><div><div class=\"lr-name\">${L.name} ${L.badge?`<span class=\"pill tag-hi\">${L.badge}<\/span>`:''}<\/div><div class=\"lr-sub\">${L.sites} \u00b7 ${L.kiosks} kiosks${L.screens?` \u00b7 ${L.screens} screens`:''}<\/div><\/div><div class=\"lr-val\">${money(m.total)}<div class=\"lr-sub\" style=\"font-weight:600\">${money(m.tax)} tax<\/div><\/div><span class=\"chev\">\u203a<\/span><div class=\"lr-bar\"><i style=\"width:${(m.total\/max*100).toFixed(0)}%\"><\/i><\/div><\/div>`);\n    row.addEventListener('click',()=>go('#\/location\/'+L.id));\n    box.appendChild(row);\n  });\n  return box;\n}\nfunction buildFunnel(m){\n  const stages=[\n    {n:'Kiosk exposures',v:m.exposures,rate:''},\n    {n:'Interactions',v:m.interactions,rate:'of exposed'},\n    {n:'High-intent actions',v:m.highIntent,rate:pct(FUNNEL.highIntent)+' of interactions'},\n    {n:'Attributed conversions',v:m.conversions,rate:pct(FUNNEL.conversion)+' of high-intent'},\n  ];\n  const max=stages[0].v;const cols=['#0E2240','#14508C','#1C9CD8','#33abe0'];\n  const box=h('<div class=\"funnel\"><\/div>');\n  stages.forEach((s,i)=>{\n    const w=26+40*(s.v\/max);\n    const st=h(`<div class=\"fstage\"><div class=\"fbar\" style=\"width:${w}%;background:${cols[i]}\">${s.n}<\/div><div class=\"fmeta\"><b>${num(s.v)}<\/b> <span class=\"frate\">${s.rate}<\/span><\/div><\/div>`);\n    box.appendChild(st);\n  });\n  return box;\n}\nfunction buildPartnerCard(m,k){\n  const parts=Object.entries(m.partners).map(([id,v])=>({v,name:SEG[id].name,color:SEG[id].color,onClick:()=>go('#\/partners')}));\n  const c=card('Partner economic impact','hotels \u00b7 dining \u00b7 retail &amp; attractions \u00b7 sports &amp; venues','',' ');\n  const inner=h('<div style=\"display:flex;gap:20px;align-items:center;flex-wrap:wrap\"><\/div>');\n  inner.appendChild(donut(parts));\n  const list=h('<div style=\"flex:1;min-width:200px\"><\/div>');\n  parts.sort((a,b)=>b.v-a.v).forEach(p=>{\n    const row=h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div><div class=\"lr-name\" style=\"display:flex;align-items:center;gap:7px\"><span class=\"sw\" style=\"width:11px;height:11px;border-radius:3px;background:${p.color}\"><\/span>${p.name}<\/div><\/div><div class=\"lr-val\">${money(p.v)}<\/div><\/div>`);\n    row.addEventListener('click',()=>go('#\/partners'));list.appendChild(row);\n  });\n  inner.appendChild(list);\n  c.appendChild(inner);\n  c.appendChild(h('<div class=\"note\">This is the figure a partner sees in their own portal \u2014 every dollar tied to a kiosk referral, QR scan, pass pull, or partner-POS event. <span class=\"toggle-tbl\" onclick=\"go(\\'#\/partners\\')\">Open partner detail \u203a<\/span><\/div>'));\n  return c;\n}\nfunction buildTaxPreview(m,k){\n  const b=m.taxBreak;\n  const parts=[\n    {v:b.hotelTOT,name:'Innkeeper&rsquo;s tax \u00b7 county (8%)',color:'var(--s-local)'},\n    {v:b.salesTax,name:'Sales &amp; use \u00b7 lodging, dining &amp; retail',color:'#33abe0'},\n    {v:b.rentalTax,name:'Auto rental excise (11%)',color:'#7cc9e8'},\n    {v:b.stateTax,name:'Sales &amp; use \u00b7 attractions',color:'var(--s-state)'},\n  ];\n  const c=card('Estimated tax revenue','real Indiana \/ Vanderburgh County rates \u00b7 click to drill','',' ');\n  const rows=parts.map(p=>({label:p.name,parts:[{v:p.v,color:p.color,name:p.name}],total:p.v,onClick:()=>go('#\/tax')}));\n  c.appendChild(rankedStacked(rows,{pl:130,w:560}));\n  c.appendChild(h(`<div class=\"gauge-track\"><i style=\"width:${(m.recirc\/(m.recirc+m.tax)*100).toFixed(0)}%\"><\/i><\/div>`));\n  c.appendChild(h(`<div class=\"note\">Only the <b>8% county innkeeper&rsquo;s tax<\/b> (${money(m.taxLocal)}) comes back to Evansville \u2014 Indiana levies no local sales-tax add-on \u2014 and it is earmarked for tourism capital projects, marketing and Old National Events Plaza operations. <b style=\"color:var(--text)\">${money(m.recirc)}<\/b> soft benefit \u2014 estimated local re-circulation of these public dollars. <span class=\"toggle-tbl\" onclick=\"go('#\/tax')\">Full tax breakdown \u203a<\/span><\/div>`));\n  return c;\n}\n\n\/* ================= LOCATION DETAIL ================= *\/\nfunction pageLocation(id){\n  const L=findLoc(id);if(!L)return pageOverview();\n  const k=K(),m=deriveMetrics(L,k),r=L.tax;\n  const wrap=h('<div class=\"fade\"><\/div>');\n  wrap.appendChild(h(`<a class=\"backbtn\" onclick=\"go('#\/overview')\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M15 18l-6-6 6-6\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg> All ${ACT().region} markets<\/a>`));\n  wrap.appendChild(h(`<div class=\"crumbs\"><span>${ACT().name}<\/span><span class=\"sep\">\u203a<\/span><a onclick=\"go('#\/overview')\">${ACT().region}<\/a><span class=\"sep\">\u203a<\/span><span>${L.name}<\/span><\/div>`));\n  wrap.appendChild(h(`<div class=\"pagehead\"><div><div class=\"eyebrow\">Kiosk market${L.badge?` \u00b7 <span style=\"color:var(--good)\">${L.badge}<\/span>`:''}<\/div><h1>${L.name}<\/h1><div class=\"ch-sub\" style=\"margin-top:4px;color:var(--text-2)\">${L.sites} \u00b7 ${L.kiosks} kiosks${L.screens?` \u00b7 ${L.screens} screens`:''} \u00b7 ${periodLabel()}<\/div><\/div><div class=\"meta\">Tax rates (real)<br><b style=\"color:var(--text);font-size:13px\">Innkeeper&rsquo;s ${r.tot}% \u00b7 IN sales ${r.sales}% \u00b7 rental ${r.rental}%<\/b><\/div><\/div>`));\n  wrap.appendChild(h(aiBanner('TrueImpact AI \u00b7 Market read',aiLocation(L,k))));\n\n  const kpis=h('<div class=\"grid kpis\" style=\"margin-bottom:16px\"><\/div>');\n  kpis.appendChild(h(`<div class=\"card kpi hero\"><div class=\"glow\"><\/div><div class=\"k-label\">Economic impact<\/div><div class=\"k-val\"><span class=\"cur\">${curSym()}<\/span>${money(m.total).replace(curSym(),'')}<\/div><div class=\"k-foot\">Direct ${money(m.direct)} + Influenced ${money(m.influenced)}<\/div><\/div>`));\n  kpis.appendChild(kpiTile('Estimated tax revenue',money(m.tax),'',`County innkeeper's ${money(m.taxLocal)} \u00b7 Indiana state ${money(m.taxState)}`,()=>go('#\/tax')));\n  kpis.appendChild(kpiTile('Partner-captured spend',money(Object.values(m.partners).reduce((a,b)=>a+b,0)),'','across 4 segments',()=>go('#\/partners')));\n  kpis.appendChild(kpiTile('Interaction rate',pct(L.interactionRate),'',`${num(m.interactions)} interactions`));\n  wrap.appendChild(kpis);\n\n  const r2=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n  r2.appendChild(card('Visitor funnel','this market',[buildFunnel(m)]));\n  r2.appendChild(buildLocTaxCard(m,L));\n  wrap.appendChild(r2);\n\n  const r3=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n  const parts=Object.entries(m.partners).map(([pid,v])=>({v,name:SEG[pid].name,color:SEG[pid].color}));\n  const pc=card('Partner impact \u2014 '+L.name,'who captured the visitor dollar','',' ');\n  const pin=h('<div style=\"display:flex;gap:20px;align-items:center;flex-wrap:wrap\"><\/div>');\n  pin.appendChild(donut(parts));\n  const pl=h('<div style=\"flex:1;min-width:200px\"><\/div>');\n  parts.sort((a,b)=>b.v-a.v).forEach(p=>pl.appendChild(h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div class=\"lr-name\" style=\"display:flex;align-items:center;gap:7px\"><span class=\"sw\" style=\"width:11px;height:11px;border-radius:3px;background:${p.color}\"><\/span>${p.name}<\/div><div class=\"lr-val\">${money(p.v)}<\/div><\/div>`)));\n  pin.appendChild(pl);pc.appendChild(pin);r3.appendChild(pc);\n  r3.appendChild(card('Monthly impact','seasonality',[areaChart(seriesFor(L,k),MONTHS,{h:210})]));\n  wrap.appendChild(r3);\n\n  \/\/ sample named partners\n  wrap.appendChild(buildSamplePartners(L,m));\n  return wrap;\n}\nfunction buildLocTaxCard(m,L){\n  const b=m.taxBreak,r=L.tax;\n  const rows=[\n    {label:`Innkeeper&rsquo;s tax \u2014 lodging (${r.tot}%)`,parts:[{v:b.hotelTOT,color:'var(--s-local)',name:'Vanderburgh County innkeeper&rsquo;s tax'}],total:b.hotelTOT},\n    {label:`Sales &amp; use \u2014 lodging + dining\/retail (${r.sales}%)`,parts:[{v:b.salesTax,color:'#33abe0',name:'Indiana sales &amp; use tax'}],total:b.salesTax},\n    {label:`Auto rental excise (${r.rental}%)`,parts:[{v:b.rentalTax,color:'#7cc9e8',name:'Indiana sales 7% + auto rental excise 4%'}],total:b.rentalTax},\n    {label:`Sales &amp; use \u2014 attractions (${r.sales}%)`,parts:[{v:b.stateTax,color:'var(--s-state)',name:'Indiana sales &amp; use tax on admissions'}],total:b.stateTax},\n  ];\n  const c=card('Estimated tax revenue','real Indiana \/ Vanderburgh County rates','',' ');\n  c.appendChild(rankedStacked(rows,{pl:150,w:560}));\n  c.appendChild(h(`<div class=\"note\">Unlike most figures on this dashboard, these three rates are <b>real and citable<\/b>: the 8% Vanderburgh County innkeeper&rsquo;s tax, Indiana&rsquo;s 7% state sales tax (no local add-on), and 11% on auto rental (7% sales + 4% Indiana auto rental excise). <b style=\"color:var(--text)\">${money(m.recirc)}<\/b> estimated re-circulation (soft benefit).<\/div>`));\n  return c;\n}\nfunction buildSamplePartners(L,m){\n  const SAMPLES={\n    visitorctr:['DoubleTree by Hilton Downtown','Bru Burger Bar','Downtown Entertainment District retail','Victory Theatre'],\n    riverfront:['Le Merigot Hotel','Riverwalk dining','Dress for Less Riverwalk','The Pagoda events'],\n    fordctr:['Hyatt Place Downtown','Sportsman&rsquo;s Grille','Ford Center concessions &amp; merch','Ford Center events'],\n    eventsplaza:['DoubleTree (connected)','Plaza catering','Exhibit-hall retail','Old National Events Plaza'],\n    eastland:['Hampton Inn East','Texas Roadhouse','Eastland Mall retail','Green River Rd promotions'],\n    deaconess:['TownePlace Suites East','Tournament concessions','Deaconess Sports Park retail','Deaconess Sports Park tournaments'],\n    goebel:['Fairfield Inn North','Complex concessions','Team merchandise','Goebel Soccer Complex tournaments'],\n    zoo:['Local lodging referrals','Zoo cafe','Mesker Park Zoo admissions','Wild Summer Lights'],\n    airport:['Airport-area hotels','Terminal dining','Rental-car counters','Charter &amp; team arrivals'],\n    museums:['Downtown lodging referrals','Museum cafe','Evansville Museum &amp; cMoe admissions','Planetarium programs'],\n    ballys:['Bally&rsquo;s hotel tower','Bally&rsquo;s dining','Casino retail','Sportsbook &amp; entertainment'],\n    haynies:['Nearby B&amp;B \/ short-term rentals','Haynie&rsquo;s Corner restaurants','Galleries &amp; studios','First Friday'],\n    campus:['Campus-area hotels','Lincoln Ave dining','Campus bookstores','UE Aces &amp; USI Screaming Eagles'],\n    heritage:['Regional lodging referrals','Nearby dining','Angel Mounds &amp; Wesselman admissions','Nature &amp; heritage programs'],\n    la:['JW Marriott L.A. LIVE','Grand Central Market','Griffith Observatory','Crypto.com Arena'],\n    sf:['Hotel Nikko','Ferry Building Marketplace','Alcatraz Cruises','Moscone Center'],\n    sd:['Hotel del Coronado','Little Italy Food Hall','San Diego Zoo','Petco Park'],\n    ana:['Anaheim Marriott','Downtown Disney Dining','Disneyland Resort','Angel Stadium'],\n    bb:['The Lodge at Big Bear','Peppercorn Grille','Big Bear Mountain Resort','Village Events'],\n    napa:['Carneros Resort','The French Laundry','Castello di Amorosa','Oxbow Public Market'],\n    ps:['Parker Palm Springs','Workshop Kitchen','Palm Springs Tram','Coachella \/ Stagecoach'],\n    sac:['Citizen Hotel','Old Sacramento Waterfront','California State Railroad Museum','Golden 1 Center'],\n    ord:['Hilton O\u2019Hare','Tortas Frontera','Terminal 5 Retail','United Club'],\n    mag:['The Peninsula Chicago','Purple Pig','360 CHICAGO','Water Tower Place'],\n    navy:['Sable at Navy Pier','Giordano\u2019s','Centennial Wheel','Navy Pier Events'],\n    mcc:['Marriott Marquis Chicago','Wintrust Cafe','Field Museum','McCormick Expo Halls'],\n    loop:['JW Marriott Chicago','The Berghoff','Skydeck Willis Tower','Chicago Theatre'],\n    mus:['Hilton Museum Campus','Shedd Cafe','Shedd Aquarium','Adler After Dark'],\n    wrig:['Hotel Zachary','Gallagher Way Dining','Wrigley Field Tours','Cubs Home Games'],\n    orl:['Hilton Bonnet Creek','Disney Springs Dining','Universal Orlando','OCCC Events'],\n    mia:['Fontainebleau Miami','Joe\u2019s Stone Crab','Vizcaya Museum','Ultra \/ Art Basel'],\n    tpa:['Tampa Marriott Water St','Columbia Restaurant','Busch Gardens','Amalie Arena'],\n    ftl:['W Fort Lauderdale','Casa Sensei','Riverwalk Cruises','Broward Convention'],\n    jax:['Marriott Downtown JAX','Cowford Chophouse','MOSH Museum','VyStar Arena'],\n    nap:['Ritz-Carlton Naples','Campiello','Naples Botanical Garden','5th Ave Events'],\n    key:['Casa Marina Resort','Blue Heaven','Mallory Square Sunset','Fantasy Fest'],\n  };\n  const names=SAMPLES[L.id]||['Hotel','Restaurant','Attraction','Venue'];\n  const segIds=['hotels','dining','attractions','events'];\n  const c=card('Sample attributed partners','illustrative \u2014 top referral recipients','',' ');\n  const tbl=h('<table><thead><tr><th>Partner<\/th><th>Segment<\/th><th>Attributed spend<\/th><th>Referrals<\/th><th>Trend<\/th><\/tr><\/thead><tbody><\/tbody><\/table>');\n  const tb=tbl.querySelector('tbody');\n  segIds.forEach((sid,i)=>{\n    const v=m.partners[sid]*(0.34-i*0.03);\n    const refs=Math.round(m.highIntent*L.mix[sid]*0.4);\n    tb.appendChild(h(`<tr><td><b>${names[i]}<\/b><\/td><td><span class=\"pill tag-mid\">${SEG[sid].name}<\/span><\/td><td class=\"tnum\">${money2(v)}<\/td><td class=\"tnum\">${refs.toLocaleString()}<\/td><td><span class=\"pill tag-hi\">\u25b2 ${(8+i*3)}%<\/span><\/td><\/tr>`));\n  });\n  c.appendChild(tbl);\n  return c;\n}\n\n\/* ================= PARTNER DETAIL ================= *\/\nfunction pagePartners(){\n  const k=K(),m=rollup(k);const tot=Object.values(m.partners).reduce((a,b)=>a+b,0);\n  const wrap=h('<div class=\"fade\"><\/div>');\n  wrap.appendChild(h(`<a class=\"backbtn\" onclick=\"go('#\/overview')\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M15 18l-6-6 6-6\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg> ${ACT().region} overview<\/a>`));\n  wrap.appendChild(h(`<div class=\"crumbs\"><a onclick=\"go('#\/overview')\">${ACT().region}<\/a><span class=\"sep\">\u203a<\/span><span>Partner economic impact<\/span><\/div>`));\n  wrap.appendChild(h(`<div class=\"pagehead\"><div><div class=\"eyebrow\">${ACT().region} \u00b7 Partner economic impact<\/div><h1>What the visitor dollar did for partners<\/h1><\/div><div class=\"meta\">${periodLabel()}<br><b style=\"color:var(--text)\">${money(tot)}<\/b> attributed<\/div><\/div>`));\n  wrap.appendChild(h(aiBanner('TrueImpact AI \u00b7 Partner read',aiPartner(k))));\n\n  \/\/ segment cards\n  const icons={hotels:'M3 21V9l9-6 9 6v12M9 21v-6h6v6',dining:'M6 3v7m0 0a3 3 0 006 0V3M6 10v11M18 3c-2 0-3 2-3 5s1 4 3 4v9',attractions:'M3 21l9-18 9 18M8 21v-5h8v5',events:'M3 8h18M3 8l2-4h14l2 4M5 8v12h14V8'};\n  const cards=h('<div class=\"seg-cards\" style=\"margin-bottom:16px\"><\/div>');\n  Object.entries(m.partners).sort((a,b)=>b[1]-a[1]).forEach(([id,v])=>{\n    const c=h(`<div class=\"seg-card\"><div class=\"sc-top\"><span class=\"sc-ic\" style=\"background:${SEG[id].color}\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"${icons[id]}\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><\/span>${SEG[id].name}<\/div><div class=\"sc-val\">${money(v)}<\/div><div class=\"sc-sub\">${pct(v\/tot,0)} of partner impact<\/div><div class=\"sc-count\"><span>Est. partners<\/span><span>${Math.round(400*SEG_SHARE(id))}<\/span><\/div><\/div>`);\n    cards.appendChild(c);\n  });\n  wrap.appendChild(cards);\n\n  \/\/ impact by segment across locations (stacked ranked)\n  const rows=[...LOCS()].map(L=>{const mm=deriveMetrics(L,k);const p=mm.partners;const t=Object.values(p).reduce((a,b)=>a+b,0);\n    return {label:L.name,total:t,onClick:()=>go('#\/location\/'+L.id),parts:['hotels','dining','attractions','events'].map(s=>({v:p[s],color:SEG[s].color,name:SEG[s].name}))};\n  }).sort((a,b)=>b.total-a.total);\n  const c1=card('Partner impact by market','stacked by segment \u00b7 click a bar to open the market','',' ');\n  c1.appendChild(rankedStacked(rows,{pl:120,w:660}));\n  c1.appendChild(legend(Object.keys(SEG).map(id=>({name:SEG[id].name,color:SEG[id].color}))));\n  wrap.appendChild(c1);\n\n  \/\/ why it matters\n  wrap.appendChild(card('Why partners engage','the portal effect',[h(`<div class=\"stat-inline\" style=\"margin-top:6px\"><div class=\"si\"><b>+15\u201330%<\/b><span>itinerary inclusion lift<\/span><\/div><div class=\"si\"><b>+20\u201340%<\/b><span>listing exposure<\/span><\/div><div class=\"si\"><b>+10\u201325%<\/b><span>pass participation<\/span><\/div><div class=\"si\"><b>48%<\/b><span>retail share of visitor spend (client, 2025)<\/span><\/div><\/div>`),h('<div class=\"note\">Benchmark lifts are TrueOmni platform ranges, not Evansville measurements. The retail figure is the client&rsquo;s 2025 number; published 2023 reporting put retail nearer <b>24%<\/b> with food ~40% \u2014 different periods and likely different methodologies (all-visitor survey vs tracked card spend). Both are carried in the provenance ledger; confirm with Explore Evansville before quoting either externally. When a restaurant, hotel or East Side retailer sees its own attributed dollars, flat-dues membership becomes performance-aligned membership.<\/div>')]));\n  return wrap;\n}\nfunction SEG_SHARE(id){return {hotels:.34,dining:.30,attractions:.22,events:.14}[id];}\n\n\/* ================= TAX DETAIL ================= *\/\nfunction pageTax(){\n  const k=K(),m=rollup(k),b=m.taxBreak;\n  const wrap=h('<div class=\"fade\"><\/div>');\n  wrap.appendChild(h(`<a class=\"backbtn\" onclick=\"go('#\/overview')\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M15 18l-6-6 6-6\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg> ${ACT().region} overview<\/a>`));\n  wrap.appendChild(h(`<div class=\"crumbs\"><a onclick=\"go('#\/overview')\">${ACT().region}<\/a><span class=\"sep\">\u203a<\/span><span>Estimated tax revenue<\/span><\/div>`));\n  wrap.appendChild(h(`<div class=\"pagehead\"><div><div class=\"eyebrow\">${ACT().region} \u00b7 Public revenue impact<\/div><h1>Estimated tax revenue by zone<\/h1><\/div><div class=\"meta\">${periodLabel()}<br><b style=\"color:var(--text)\">${money(m.tax)}<\/b> total est.<\/div><\/div>`));\n  wrap.appendChild(h(aiBanner('TrueImpact AI \u00b7 Tax read',aiTax(k))));\n\n  \/\/ KPI tiles by tax type\n  const kpis=h('<div class=\"grid kpis\" style=\"margin-bottom:16px\"><\/div>');\n  kpis.appendChild(h(`<div class=\"card kpi hero\"><div class=\"glow\"><\/div><div class=\"k-label\">Total estimated tax revenue<\/div><div class=\"k-val\"><span class=\"cur\">${curSym()}<\/span>${money(m.tax).replace(curSym(),'')}<\/div><div class=\"k-foot\">County innkeeper&rsquo;s ${money(m.taxLocal)} + Indiana state ${money(m.taxState)}<\/div><\/div>`));\n  kpis.appendChild(kpiTile('Innkeeper&rsquo;s tax \u00b7 county',money(b.hotelTOT),'','8% on hotel rooms \u2014 earmarked for tourism capital, marketing &amp; Old National Events Plaza'));\n  kpis.appendChild(kpiTile('Sales &amp; use \u00b7 lodging + dining\/retail',money(b.salesTax),'','7% Indiana state sales tax \u2014 no local add-on'));\n  kpis.appendChild(kpiTile('Sales &amp; use \u00b7 attractions',money(b.stateTax),'','7% on admissions &amp; attraction spend'));\n  wrap.appendChild(kpis);\n\n  \/\/ stacked tax by location (local components + state)\n  const rows=[...LOCS()].map(L=>{const mm=deriveMetrics(L,k),bb=mm.taxBreak;\n    return {label:L.name,total:mm.tax,onClick:()=>go('#\/location\/'+L.id),parts:[\n      {v:bb.hotelTOT,color:'var(--s-local)',name:'Innkeeper&rsquo;s tax (county)'},\n      {v:bb.salesTax,color:'#33abe0',name:'Sales &amp; use \u00b7 lodging + dining\/retail'},\n      {v:bb.rentalTax,color:'#7cc9e8',name:'Auto rental excise'},\n      {v:bb.stateTax,color:'var(--s-state)',name:'Sales &amp; use \u00b7 attractions'},\n    ]};}).sort((a,b)=>b.total-a.total);\n  const c1=card('Estimated tax revenue by zone','county innkeeper&rsquo;s tax \u00b7 Indiana sales &amp; use \u00b7 auto rental excise \u00b7 click a bar to drill','',' ');\n  c1.appendChild(rankedStacked(rows,{pl:120,w:680}));\n  c1.appendChild(legend([{name:'Innkeeper&rsquo;s tax (county)',color:'var(--s-local)'},{name:'Sales &amp; use \u00b7 lodging + dining\/retail',color:'#33abe0'},{name:'Auto rental excise',color:'#7cc9e8'},{name:'Sales &amp; use \u00b7 attractions',color:'var(--s-state)'}]));\n  wrap.appendChild(c1);\n\n  \/\/ recirculation soft benefit\n  const recircCard=card('Recirculation \u2014 the soft benefit','induced community activity from public tax dollars','',' ');\n  recircCard.appendChild(h(`<div class=\"stat-inline\" style=\"margin-top:4px\"><div class=\"si\"><b>${money(m.tax)}<\/b><span>hard tax captured<\/span><\/div><div class=\"si\"><b style=\"color:var(--good)\">${money(m.recirc)}<\/b><span>est. local re-circulation<\/span><\/div><div class=\"si\"><b>${money(m.tax+m.recirc)}<\/b><span>combined public benefit<\/span><\/div><\/div>`));\n  recircCard.appendChild(h(`<div class=\"gauge-track\" style=\"margin-top:14px\"><i style=\"width:${(m.recirc\/(m.tax+m.recirc)*100).toFixed(0)}%\"><\/i><\/div>`));\n  recircCard.appendChild(h('<div class=\"note\">Public revenue does not leave the community \u2014 it funds payroll, services and local procurement that are re-spent through the regional economy. Modeled conservatively at 0.9\u00d7 of captured tax (induced\/soft). The real-world anchor for this line in Evansville: without tourism, each Vanderburgh County household would pay <b>$1,149\/yr<\/b> more in taxes (Explore Evansville; the client cites ~$1,200 as the current figure). This is what turns \"we captured tax\" into \"we grew the local economy.\"<\/div>'));\n  wrap.appendChild(recircCard);\n\n  \/\/ full data table\n  const c2=card('Full tax detail','auditable line items \u00b7 '+periodLabel(),'',' ');\n  const tbl=h('<table><thead><tr><th>Zone<\/th><th>Innk. %<\/th><th>Innkeeper&rsquo;s tax<\/th><th>Sales \u00b7 lodging+dining\/retail<\/th><th>Auto rental<\/th><th>Sales \u00b7 attractions<\/th><th>Total tax<\/th><th>Recirc (soft)<\/th><\/tr><\/thead><tbody><\/tbody><\/table>');\n  const tb=tbl.querySelector('tbody');\n  rows.forEach(r=>{const L=LOCS().find(x=>x.name===r.label);const mm=deriveMetrics(L,k),bb=mm.taxBreak,rt=L.tax;\n    const tr=h(`<tr><td><b>${L.name}<\/b><\/td><td class=\"tnum\">${rt.tot}%<\/td><td class=\"tnum\">${money2(bb.hotelTOT)}<\/td><td class=\"tnum\">${money2(bb.salesTax)}<\/td><td class=\"tnum\">${money2(bb.rentalTax)}<\/td><td class=\"tnum\">${money2(bb.stateTax)}<\/td><td class=\"tnum\"><b>${money2(mm.tax)}<\/b><\/td><td class=\"tnum\" style=\"color:var(--good)\">${money2(mm.recirc)}<\/td><\/tr>`);\n    tr.addEventListener('click',()=>go('#\/location\/'+L.id));tb.appendChild(tr);\n  });\n  c2.appendChild(tbl);\n  wrap.appendChild(c2);\n  return wrap;\n}\n\n\/* ================= NETWORK ROLL-UP (all destinations) ================= *\/\nfunction pageNetwork(){\n  const k=K(),{net,parts}=networkAgg(k);\n  const wrap=h('<div class=\"fade\"><\/div>');\n  wrap.appendChild(h(`<div class=\"pagehead\"><div><div class=\"eyebrow\">TrueOmni Network \u00b7 All destinations<\/div><h1>Total economic impact \u2014 every kiosk, every destination<\/h1><\/div><div class=\"meta\">${periodLabel()}<br><b style=\"color:var(--text);font-size:14px\">${net.destinations} destinations \u00b7 ${num(net.kiosks)} kiosks<\/b><\/div><\/div>`));\n  wrap.appendChild(h(`<div class=\"crumbs\"><span>TrueOmni Network<\/span><span class=\"sep\">\u203a<\/span><span>All destinations<\/span><\/div>`));\n  wrap.appendChild(h(aiBanner('TrueImpact AI \u00b7 Network roll-up',aiNetwork(k))));\n\n  const kpis=h('<div class=\"grid kpis\" style=\"margin-bottom:16px\"><\/div>');\n  kpis.appendChild(h(`<div class=\"card kpi hero\"><div class=\"glow\"><\/div><div class=\"k-label\">Network economic impact<\/div><div class=\"k-val\"><span class=\"cur\">${curSym()}<\/span>${money(net.total).replace(curSym(),'')}<\/div><div class=\"k-delta up\">\u25b2 22.6% YoY<\/div><div class=\"k-foot\">Direct ${money(net.direct)} + Influenced ${money(net.influenced)} \u00b7 ${net.destinations} destinations, ledger-level<\/div><\/div>`));\n  kpis.appendChild(kpiTile('Public tax revenue',money(net.tax),'\u25b2 19.4%',`County innkeeper's ${money(net.taxLocal)} \u00b7 Indiana state ${money(net.taxState)}`));\n  kpis.appendChild(kpiTile('Partner-captured spend',money(Object.values(net.partners).reduce((a,b)=>a+b,0)),'\u25b2 24.1%','across all destinations'));\n  kpis.appendChild(kpiTile('Trackable visitor actions',num(net.interactions),'\u25b2 15.2%',`${num(net.conversions)} attributed conversions`));\n  wrap.appendChild(kpis);\n\n  \/\/ destinations ranked (real 3 + modeled long-tail)\n  const destRows=NET_IDS.map((id,i)=>({id,name:DESTINATIONS[id].name,region:DESTINATIONS[id].region,kind:DESTINATIONS[id].kind,m:parts[i]}))\n    .sort((a,b)=>b.m.total-a.m.total);\n  const maxD=destRows[0].m.total;\n  const dl=h('<div class=\"loclist\"><\/div>');\n  destRows.forEach(d=>{\n    const row=h(`<div class=\"locrow\"><div><div class=\"lr-name\">${d.name}<\/div><div class=\"lr-sub\">${d.kind} \u00b7 ${d.m.kiosks} kiosks \u00b7 ${d.region}<\/div><\/div><div class=\"lr-val\">${money(d.m.total)}<div class=\"lr-sub\" style=\"font-weight:600\">${money(d.m.tax)} tax<\/div><\/div><span class=\"chev\">\u203a<\/span><div class=\"lr-bar\"><i style=\"width:${(d.m.total\/maxD*100).toFixed(0)}%\"><\/i><\/div><\/div>`);\n    row.addEventListener('click',()=>setDest(d.id));dl.appendChild(row);\n  });\n  const realTot=parts.reduce((a,b)=>a+b.total,0), othersTot=net.total-realTot, othersTax=net.tax-parts.reduce((a,b)=>a+b.tax,0), othersK=net.kiosks-parts.reduce((a,b)=>a+b.kiosks,0);\n  dl.appendChild(h(`<div class=\"locrow\" style=\"opacity:.85;cursor:default\"><div><div class=\"lr-name\">Other ${net.destinations-3} destinations<\/div><div class=\"lr-sub\">North America + Japan \u00b7 ~${num(othersK)} kiosks \u00b7 modeled long-tail<\/div><\/div><div class=\"lr-val\">${money(othersTot)}<div class=\"lr-sub\" style=\"font-weight:600\">${money(othersTax)} tax<\/div><\/div><span class=\"chev\" style=\"opacity:0\">\u203a<\/span><div class=\"lr-bar\"><i style=\"width:${(othersTot\/maxD*100).toFixed(0)}%;background:linear-gradient(90deg,#8b96a5,#5B6675)\"><\/i><\/div><\/div>`));\n\n  const r1=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n  r1.appendChild(card('Destinations ranked','click a live destination to drill into its kiosks',[dl,h('<div class=\"note\">California, Chicago and Florida are live TrueImpact tenants shown from their own kiosk data. The long-tail bucket models the remaining network to the published footprint.<\/div>')]));\n  \/\/ network partner mix\n  const parts2=Object.entries(net.partners).map(([id,v])=>({v,name:SEG[id].name,color:SEG[id].color}));\n  const pc=card('Network partner impact','hotels \u00b7 dining \u00b7 retail &amp; attractions \u00b7 sports &amp; venues','',' ');\n  const pin=h('<div style=\"display:flex;gap:20px;align-items:center;flex-wrap:wrap\"><\/div>');\n  pin.appendChild(donut(parts2));\n  const plist=h('<div style=\"flex:1;min-width:190px\"><\/div>');\n  parts2.sort((a,b)=>b.v-a.v).forEach(p=>plist.appendChild(h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div class=\"lr-name\" style=\"display:flex;align-items:center;gap:7px\"><span class=\"sw\" style=\"width:11px;height:11px;border-radius:3px;background:${p.color}\"><\/span>${p.name}<\/div><div class=\"lr-val\">${money(p.v)}<\/div><\/div>`)));\n  pin.appendChild(plist);pc.appendChild(pin);\n  r1.appendChild(pc);\n  wrap.appendChild(r1);\n\n  \/\/ engagement entry (network scope)\n  wrap.appendChild(engMiniCard(k));\n  wrap.lastChild.style.marginBottom='16px';\n\n  \/\/ network trend\n  wrap.appendChild(card('Network economic impact trend','monthly \u00b7 all destinations',[areaChart(networkSeries(k),MONTHS,{h:220}),h('<div class=\"note\">The category\\'s first aggregate impact curve built from first-party behavioral data across the network. Each destination re-circulates public tax dollars into its own community \u2014 an estimated '+money(net.recirc)+' network-wide (soft benefit).<\/div>')]));\n  return wrap;\n}\n\n\/* ================= ENGAGEMENT DRILL-THROUGH ================= *\/\nfunction engScope(k){\n  if(activeDest==='network'){const m=networkAgg(k).net;return {m,name:'the TrueOmni Network',seg:segSharesOf(m),locs:[]};}\n  if(engLoc!=='all'){const L=findLoc(engLoc);if(L){const m=deriveMetrics(L,k);return {m,name:L.name,seg:segSharesOf(m),locs:LOCS()};}}\n  const m=rollup(k);return {m,name:ACT().region,seg:segSharesOf(m),locs:LOCS()};\n}\nfunction engMetrics(mode){\n  const base={\n    interactions:{label:'Attention',   get:r=>r.interactions, fmt:num,   tfmt:v=>num(v)+' sessions'},\n    highIntent:  {label:'High-intent',  get:r=>r.highIntent,   fmt:num,   tfmt:v=>num(v)+' actions'},\n    conversions: {label:'Conversions',  get:r=>r.conversions,  fmt:num,   tfmt:v=>num(v)+' conv.'},\n    impact:      {label:'Attributed $', get:r=>r.impact,       fmt:money, tfmt:money2},\n  };\n  if(mode==='modules') base.time={label:'Time spent',get:r=>r.timeHrs,fmt:v=>num(v)+' h',tfmt:v=>num(v)+' hours'};\n  else base.roas={label:'ROI (ROAS)',get:r=>r.roas,fmt:v=>v.toFixed(1)+'\u00d7',tfmt:v=>v.toFixed(2)+'\u00d7 return'};\n  return base;\n}\nfunction setEng(key,val){ if(key==='mode'){engMode=val;engMetric='interactions';} else if(key==='loc'){engLoc=val;} else {engMetric=val;}\n  location.hash = '#\/'+(engMode==='modules'?'modules':'campaigns'); render(); }\nfunction pageEngagement(){\n  const k=K(), sc=engScope(k);\n  const items = engMode==='modules'?MODULES:CAMPAIGNS;\n  const rows = splitFunnel(sc.m, items, sc.seg);\n  const M = engMetrics(engMode);\n  if(!M[engMetric]) engMetric='interactions';\n  const met=M[engMetric];\n  rows.sort((a,b)=>(met.get(b)||0)-(met.get(a)||0));\n  const colorOf=r=> engMode==='modules'?SEG[r.tag].color:CAMP_TYPE[r.type];\n\n  const wrap=h('<div class=\"fade\"><\/div>');\n  wrap.appendChild(h(`<a class=\"backbtn\" onclick=\"go('#\/overview')\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M15 18l-6-6 6-6\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg> ${activeDest==='network'?'Network':ACT().region} overview<\/a>`));\n  wrap.appendChild(h(`<div class=\"crumbs\"><a onclick=\"go('#\/overview')\">${activeDest==='network'?'TrueOmni Network':ACT().region}<\/a><span class=\"sep\">\u203a<\/span><span>Engagement drill-through<\/span><\/div>`));\n  wrap.appendChild(h(`<div class=\"pagehead\"><div><div class=\"eyebrow\">Marketing \u00b7 Engagement drill-through<\/div><h1>What draws attention \u2014 and what to invest in<\/h1><\/div><div class=\"meta\">${periodLabel()}<br><b style=\"color:var(--text)\">${sc.name}<\/b><\/div><\/div>`));\n  wrap.appendChild(h(aiBanner('TrueImpact AI \u00b7 Investment read',aiEngagement(rows,engMode,sc.name))));\n\n  \/\/ filters\n  const f=h('<div class=\"filters\"><\/div>');\n  f.appendChild(h(`<div class=\"fgroup\"><span class=\"flab\">Dimension<\/span><div class=\"fseg\">\n    <button class=\"${engMode==='modules'?'on':''}\" onclick=\"setEng('mode','modules')\">Modules<\/button>\n    <button class=\"${engMode==='campaigns'?'on':''}\" onclick=\"setEng('mode','campaigns')\">Campaigns<\/button><\/div><\/div>`));\n  if(sc.locs.length){\n    const opts=['<option value=\"all\"'+(engLoc==='all'?' selected':'')+'>All markets<\/option>']\n      .concat(sc.locs.map(L=>`<option value=\"${L.id}\"${engLoc===L.id?' selected':''}>${L.name}<\/option>`)).join('');\n    f.appendChild(h(`<div class=\"fgroup\"><span class=\"flab\">Location<\/span><select class=\"fsel\" onchange=\"setEng('loc',this.value)\">${opts}<\/select><\/div>`));\n  }\n  const mkeys=Object.keys(M);\n  f.appendChild(h(`<div class=\"fgroup\"><span class=\"flab\">Rank by<\/span><div class=\"fseg\">${mkeys.map(mk=>`<button class=\"${mk===engMetric?'on':''}\" onclick=\"setEng('metric','${mk}')\">${M[mk].label}<\/button>`).join('')}<\/div><\/div>`));\n  wrap.appendChild(f);\n\n  \/\/ ranked bar + top funnel\n  const r1=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n  const barRows=rows.map(r=>({label:engShort(r.name),parts:[{v:met.get(r)||0,color:colorOf(r),name:met.label}],total:met.get(r)||0}));\n  const rk=card(`${engMode==='modules'?'Modules':'Campaigns'} ranked by ${met.label.toLowerCase()}`,'stack ranking','',' ');\n  rk.appendChild(rankedStacked(barRows,{pl:150,w:640,pr:74,fmt:met.fmt,tfmt:met.tfmt}));\n  r1.appendChild(rk);\n  \/\/ top item funnel drill-through\n  const top=rows[0];\n  const fc=card('Funnel drill-through','top '+(engMode==='modules'?'module':'campaign')+': '+top.name,[buildEngFunnel(top),h(`<div class=\"note\">Exposures \u2192 interactions \u2192 high-intent \u2192 attributed conversions for <b>${top.name}<\/b>. Conversion rate <b>${pct(top.convRate,1)}<\/b>${top.roas?` \u00b7 ROAS <b>${top.roas.toFixed(1)}\u00d7<\/b>`:''}${top.timeHrs?` \u00b7 <b>${num(top.timeHrs)}<\/b> engaged hours`:''}.<\/div>`)]);\n  r1.appendChild(fc);\n  wrap.appendChild(r1);\n\n  \/\/ full table\n  const tc=card(`${engMode==='modules'?'Module':'Campaign'} funnel \u2014 full breakdown`,'every stage \u00b7 '+periodLabel(),'',' ');\n  tc.appendChild(buildEngTable(rows,engMode,colorOf));\n  wrap.appendChild(tc);\n\n  \/\/ A\/B tests (campaigns only)\n  if(engMode==='campaigns'){\n    const tests=AB_TESTS.map(t=>({t,row:rows.find(r=>r.id===t.camp)})).filter(x=>x.row);\n    const abWrap=card('A\/B campaign tests','conversion rate by variant \u2014 compare & contrast',[h('<div class=\"grid row-2\" id=\"abgrid\" style=\"margin-top:2px\"><\/div>')]);\n    const grid=abWrap.querySelector('#abgrid');\n    tests.forEach(({t,row})=>grid.appendChild(buildABcard(t,row)));\n    wrap.appendChild(abWrap);\n  }\n  return wrap;\n}\nfunction buildEngFunnel(r){\n  const stages=[['Exposures',r.exposures,''],['Interactions',r.interactions,pct(r.interactions\/r.exposures,0)+' of exposed'],\n    ['High-intent',r.highIntent,pct(r.highIntent\/r.interactions,0)+' of interactions'],['Conversions',r.conversions,pct(r.conversions\/r.highIntent,0)+' of high-intent']];\n  const max=stages[0][1],cols=['#0E2240','#14508C','#1C9CD8','#33abe0'];\n  const box=h('<div class=\"funnel\"><\/div>');\n  stages.forEach(([n,v,rate],i)=>box.appendChild(h(`<div class=\"fstage\"><div class=\"fbar\" style=\"width:${26+40*(v\/max)}%;background:${cols[i]}\">${n}<\/div><div class=\"fmeta\"><b>${num(v)}<\/b> <span class=\"frate\">${rate}<\/span><\/div><\/div>`)));\n  return box;\n}\nfunction buildEngTable(rows,mode,colorOf){\n  const head = mode==='modules'\n    ? '<tr><th>Module<\/th><th>Exposures<\/th><th>Interactions<\/th><th>High-intent<\/th><th>Conversions<\/th><th>Conv %<\/th><th>Time<\/th><th>Attributed $<\/th><th>$\/1K int<\/th><\/tr>'\n    : '<tr><th>Campaign<\/th><th>Interactions<\/th><th>High-intent<\/th><th>Conversions<\/th><th>Conv %<\/th><th>Spend<\/th><th>Attributed $<\/th><th>ROAS<\/th><\/tr>';\n  const tbl=h(`<table><thead>${head}<\/thead><tbody><\/tbody><\/table>`);\n  const tb=tbl.querySelector('tbody');\n  rows.forEach(r=>{\n    const dot=`<span class=\"sw\" style=\"display:inline-block;width:10px;height:10px;border-radius:3px;background:${colorOf(r)};margin-right:7px;vertical-align:-1px\"><\/span>`;\n    const conv=`<span class=\"conv-pill\">${pct(r.convRate,1)}<\/span>`;\n    if(mode==='modules'){\n      tb.appendChild(h(`<tr><td>${dot}<b>${r.name}<\/b><\/td><td class=\"tnum\">${num(r.exposures)}<\/td><td class=\"tnum\">${num(r.interactions)}<\/td><td class=\"tnum\">${num(r.highIntent)}<\/td><td class=\"tnum\">${num(r.conversions)}<\/td><td>${conv}<\/td><td class=\"tnum\">${num(r.timeHrs)} h<\/td><td class=\"tnum\"><b>${money(r.impact)}<\/b><\/td><td class=\"tnum\">${money(r.valPerK)}<\/td><\/tr>`));\n    } else {\n      tb.appendChild(h(`<tr><td>${dot}<b>${r.name}<\/b><div class=\"ab-sub\" style=\"margin-left:17px\">${r.type}<\/div><\/td><td class=\"tnum\">${num(r.interactions)}<\/td><td class=\"tnum\">${num(r.highIntent)}<\/td><td class=\"tnum\">${num(r.conversions)}<\/td><td>${conv}<\/td><td class=\"tnum\">${money(r.spend)}<\/td><td class=\"tnum\"><b>${money(r.impact)}<\/b><\/td><td class=\"tnum\"><span class=\"pill ${r.roas>=4?'tag-hi':'tag-mid'}\">${r.roas.toFixed(1)}\u00d7<\/span><\/td><\/tr>`));\n    }\n  });\n  return tbl;\n}\nfunction buildABcard(t,row){\n  \/\/ split the campaign row's traffic; blended conv rate must equal row.convRate\n  const base=row.convRate, rA=base\/(t.split + (1-t.split)*t.bLift), rB=rA*t.bLift;\n  const intA=row.interactions*t.split, intB=row.interactions*(1-t.split);\n  const cvA=intA*rA, cvB=intB*rB;\n  const impA=row.impact*(cvA\/(cvA+cvB)), impB=row.impact*(cvB\/(cvA+cvB));\n  const winnerB=t.bLift>1, decisive=t.conf>=0.9;\n  const maxR=Math.max(rA,rB);\n  const badge = t.status==='No winner yet' ? `<span class=\"ab-badge ab-none\">Running \u00b7 ${pct(t.conf,0)} conf.<\/span>`\n    : `<span class=\"ab-badge ab-win\">${t.status} \u00b7 ${pct(t.conf,0)} conf.<\/span>`;\n  const lift=(rB\/rA-1);\n  const c=h(`<div class=\"ab-card\"><\/div>`);\n  c.appendChild(h(`<div class=\"ab-head\"><div><div class=\"abt\">${t.name}<\/div><div class=\"abs\">${row.name} \u00b7 ${num(row.interactions)} sessions split ${Math.round(t.split*100)}\/${Math.round((1-t.split)*100)}<\/div><\/div>${badge}<\/div>`));\n  const variant=(tag,label,r,cv,imp,isWin)=>`\n    <div class=\"ab-var\">\n      <div class=\"ab-tag\" style=\"background:${isWin?'var(--good)':'var(--slate)'}\">${tag}<\/div>\n      <div><div class=\"ab-nm\">${label} ${isWin?'<span class=\"conv-pill\" style=\"background:rgba(12,163,12,.14);color:var(--good)\">winner<\/span>':''}<\/div><div class=\"ab-sub\">${num(cv)} conversions \u00b7 ${money(imp)} attributed<\/div><\/div>\n      <div class=\"ab-conv\"><b>${pct(r,2)}<\/b><span>conv. rate<\/span><\/div>\n      <div class=\"ab-bar\"><i style=\"width:${(r\/maxR*100).toFixed(0)}%;background:${isWin?'var(--good)':'var(--slate)'}\"><\/i><\/div>\n    <\/div>`;\n  c.appendChild(h(variant('A',t.a,rA,cvA,impA,!winnerB)));\n  c.appendChild(h(variant('B',t.b,rB,cvB,impB,winnerB)));\n  c.appendChild(h(`<div class=\"ab-foot\"><span>Variant B vs A<\/span><span><b style=\"color:${lift>=0?'var(--good)':'var(--warn)'}\">${lift>=0?'+':''}${pct(lift,1)}<\/b> conversion-rate lift<\/span><\/div>`));\n  return c;\n}\n\n\/* ================= MEDIA NETWORK ================= *\/\nfunction aiMedia(k){const m=mediaMetrics(k);\n  const t=adTotals(k), sg=t.sg;\n  return `At the modeled <b>${m.kiosks}-kiosk<\/b>${sg?` + <b>${sg.screens}-screen<\/b>`:''} network, TrueImpact projects <span class=\"em\">${money(t.total)}<\/span> a year in <b>Total Advertising Revenue<\/b> \u2014 <b>${money(m.rev)}<\/b> from interactive kiosks (range ${money(m.band.floor)}\u2013${money(m.band.strong)})${sg?` and <b>${money(sg.rev)}<\/b> from digital signage (range ${money(sg.band.floor)}\u2013${money(sg.band.strong)})`:''}. Kiosks deliver an estimated <b>${num(m.impressions)}<\/b> ad impressions at an effective CPM near <b>${money(m.cpm)}<\/b> \u2014 interactive, high-dwell, QR-convertible inventory prices above broadcast display${sg?`, while the signage network delivers <b>${num(sg.impressions)}<\/b> screen impressions at <b>${money(sg.cpm)}<\/b> CPM, inside the defensible DOOH range`:''}. About <b>${pct(MEDIA.streamSplit.direct)}<\/b> of kiosk revenue is direct local sales; the rest fills programmatically through Google Ad Manager. Together that covers the combined annual software fee <b>${(t.total\/t.softwareYr).toFixed(0)}\u00d7<\/b> over and repays all hardware in roughly <b>${t.payback.toFixed(1)} years<\/b> \u2014 the self-funding loop that lets a mid-market DMO run this without a new line in the budget.`;}\nfunction mediaMiniCard(k){const t=adTotals(k), m=t.km, sg=t.sg;\n  const c=card('Media Network \u00b7 Total Advertising Revenue','the self-funding layer \u2014 kiosks + digital signage','',' ');\n  c.appendChild(h(`<div class=\"stat-inline\" style=\"margin-top:2px\"><div class=\"si\"><b>${money(t.total)}<\/b><span>Total Advertising Revenue \/ yr<\/span><\/div><div class=\"si\"><b>${money(m.rev)}<\/b><span>kiosk ad revenue<\/span><\/div>${sg?`<div class=\"si\"><b>${money(sg.rev)}<\/b><span>signage ad revenue (${sg.screens} screens)<\/span><\/div>`:''}<div class=\"si\"><b style=\"color:var(--good)\">${t.payback.toFixed(1)} yr<\/b><span>combined capital payback<\/span><\/div><\/div>`));\n  c.appendChild(h(`<div style=\"display:flex;gap:8px;margin-top:12px\"><button class=\"chip\" style=\"cursor:pointer\" onclick=\"go('#\/media')\">Open Media Network \u203a<\/button><\/div>`));\n  return c;\n}\nfunction pageMedia(){\n  const k=K(); const t=adTotals(k), m=t.km, sg=t.sg;\n  const wrap=h('<div class=\"fade\"><\/div>');\n  wrap.appendChild(h(`<a class=\"backbtn\" onclick=\"go('#\/overview')\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M15 18l-6-6 6-6\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg> ${ACT().region} overview<\/a>`));\n  wrap.appendChild(h(`<div class=\"crumbs\"><span>${ACT().name}<\/span><span class=\"sep\">\u203a<\/span><a onclick=\"go('#\/overview')\">${ACT().region}<\/a><span class=\"sep\">\u203a<\/span><span>Media Network<\/span><\/div>`));\n  wrap.appendChild(h(`<div class=\"pagehead\"><div><div class=\"eyebrow\">Advertising \u00b7 Media Network<\/div><h1>Media Network \u2014 advertising revenue potential<\/h1><div class=\"ch-sub\" style=\"margin-top:4px;color:var(--text-2)\">Native direct-sold + Google Ad Manager programmatic \u00b7 ${periodLabel()}<\/div><\/div><div class=\"meta\">Sell-through at maturity<br><b style=\"color:var(--text);font-size:14px\">${pct(MEDIA.fillMature)} fill \u00b7 ${m.kiosks} kiosks${sg?` \u00b7 ${sg.screens} screens`:''}<\/b><\/div><\/div>`));\n  wrap.appendChild(h(aiBanner('TrueImpact AI \u00b7 Media read', aiMedia(k))));\n\n  const kpis=h('<div class=\"grid kpis\" style=\"margin-bottom:16px\"><\/div>');\n  kpis.appendChild(h(`<div class=\"card kpi hero\"><div class=\"glow\"><\/div><div class=\"k-label\">Total Advertising Revenue<\/div><div class=\"k-val\"><span class=\"cur\">${curSym()}<\/span>${money(t.total).replace(curSym(),'')}<\/div><div class=\"k-delta up\">\u25b2 kiosks + digital signage<\/div><div class=\"k-foot\">Kiosks ${money(m.rev)} + signage ${money(sg?sg.rev:0)} \u00b7 scales with fill, kiosks &amp; screens<\/div><\/div>`));\n  kpis.appendChild(kpiTile('Kiosk ad revenue \/ yr',money(m.rev),'',`Range ${money(m.band.floor)}\u2013${money(m.band.strong)} \u00b7 ${curSym()}325\u20131,000 \/ kiosk \/ mo (modeled, mid-market)`));\n  kpis.appendChild(kpiTile('Kiosk ad impressions \/ yr',num(m.impressions),'',`effective CPM ${money(m.cpm)} \u2014 interactive, high-dwell inventory`));\n  kpis.appendChild(kpiTile('Covers annual software',(t.total\/t.softwareYr).toFixed(0)+'\u00d7','',`vs ${money(t.softwareYr)}\/yr combined platform fee`));\n  wrap.appendChild(kpis);\n\n  const r2=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n  const invCard=card('Revenue by inventory type','container-level potential (Omni Media Network)','',' ');\n  const list=h('<div class=\"loclist\"><\/div>'); const maxv=Math.max(...m.byInv.map(x=>x.v));\n  m.byInv.slice().sort((a,b)=>b.v-a.v).forEach(x=>{list.appendChild(h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div class=\"lr-name\">${x.name}<\/div><div class=\"lr-val\">${money(x.v)}<div class=\"lr-sub\" style=\"font-weight:600\">${pct(x.share)}<\/div><\/div><div class=\"lr-bar\"><i style=\"width:${(x.v\/maxv*100).toFixed(0)}%\"><\/i><\/div><\/div>`));});\n  invCard.appendChild(list); r2.appendChild(invCard);\n  const streamCard=card('Direct vs programmatic','native sales + Google Ad Manager','',' ');\n  const parts=[{v:m.byStream.direct,name:'Direct \/ native sold',color:'var(--s-hotels)'},{v:m.byStream.programmatic,name:'Programmatic (GAM \/ DTN)',color:'var(--s-events)'}];\n  const pin=h('<div style=\"display:flex;gap:20px;align-items:center;flex-wrap:wrap\"><\/div>'); pin.appendChild(donut(parts));\n  const pl=h('<div style=\"flex:1;min-width:180px\"><\/div>'); parts.forEach(p=>pl.appendChild(h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div class=\"lr-name\" style=\"display:flex;align-items:center;gap:7px\"><span class=\"sw\" style=\"width:11px;height:11px;border-radius:3px;background:${p.color}\"><\/span>${p.name}<\/div><div class=\"lr-val\">${money(p.v)}<\/div><\/div>`))); pin.appendChild(pl);\n  streamCard.appendChild(pin); r2.appendChild(streamCard);\n  wrap.appendChild(r2);\n\n  \/\/ ---------------- DIGITAL SIGNAGE ----------------\n  if(sg){\n    const sgHead=card('Digital Signage \u2014 the broadcast layer','OMNI Signage \u00b7 non-interactive screens \u00b7 reach, not transactions','',' ');\n    const sk=h('<div class=\"grid kpis\" style=\"margin-top:2px\"><\/div>');\n    sk.appendChild(h(`<div class=\"card kpi hero\"><div class=\"glow\"><\/div><div class=\"k-label\">Signage ad revenue \/ yr<\/div><div class=\"k-val\"><span class=\"cur\">${curSym()}<\/span>${money(sg.rev).replace(curSym(),'')}<\/div><div class=\"k-delta up\">\u25b2 ${sg.screens} screens at ${pct(SIGNAGE.fillMature)} fill<\/div><div class=\"k-foot\">Range ${money(sg.band.floor)}\u2013${money(sg.band.strong)} \u00b7 ${money(sg.revPerScreen)} revenue per screen \/ yr<\/div><\/div>`));\n    sk.appendChild(kpiTile('Screens deployed',String(sg.screens),'',`${(sg.screens\/m.kiosks).toFixed(1)} screens per kiosk \u00b7 modeled`));\n    sk.appendChild(kpiTile('Screen impressions \/ yr',num(sg.impressions),'',`${num(sg.reach)} reach \u00b7 effective CPM ${money(sg.cpm)}`));\n    sk.appendChild(kpiTile('Avg dwell \/ attention',SIGNAGE.dwellSec+'s','','the DOOH quality metric'));\n    sgHead.appendChild(sk);\n    const sk2=h('<div class=\"grid kpis\" style=\"margin-top:12px\"><\/div>');\n    sk2.appendChild(kpiTile('Spots per loop',String(sg.spotsPerLoop),'',`${SIGNAGE.loopSec}s loop \/ ${SIGNAGE.spotSec}s spot`));\n    sk2.appendChild(kpiTile('Share of voice',pct(sg.shareOfVoice),'','per advertiser, per loop'));\n    sk2.appendChild(kpiTile('Signage fill rate',pct(SIGNAGE.fillMature),'',`Phase 1 ${pct(SIGNAGE.fillByPhase[1])} \u2192 Phase 3 ${pct(SIGNAGE.fillByPhase[3])}`));\n    sk2.appendChild(kpiTile('Revenue per screen \/ yr',money(sg.revPerScreen),'',`${money(SIGNAGE.perScreenMo.mid)} \/ screen \/ mo at maturity`));\n    sgHead.appendChild(sk2);\n    sgHead.appendChild(h(`<div class=\"note\"><b>Screens broadcast; kiosks transact.<\/b> None of these impressions feed interactions, attributed visitors, economic impact or tax \u2014 those stay kiosk-derived. Signage contributes reach and ad inventory only. The audience base is deliberately larger than the kiosk exposure base: Explore Evansville counts a visitor as someone travelling >30 miles, but a screen in the Ford Center concourse or Eastland Mall is seen mostly by residents and by repeat passes, so the base is grown by ${SIGNAGE.residentMult}\u00d7 to venue footfall (MODELED). Per-screen revenue is scaled to a mid-market DMO, which is what puts the implied CPM at <b>${money(sg.cpm)}<\/b> \u2014 inside the defensible digital-out-of-home range.<\/div>`));\n    wrap.appendChild(sgHead); wrap.lastChild.style.marginBottom='16px';\n\n    const r3=h('<div class=\"grid row-2\" style=\"margin-bottom:16px\"><\/div>');\n    const fmtCard=card('Signage revenue by format','weighted to arena, sports complexes and mall','',' ');\n    const fl=h('<div class=\"loclist\"><\/div>'); const fmax=Math.max(...sg.byFormat.map(x=>x.v));\n    sg.byFormat.slice().sort((a,b)=>b.v-a.v).forEach(x=>fl.appendChild(h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div class=\"lr-name\">${x.name}<\/div><div class=\"lr-val\">${money(x.v)}<div class=\"lr-sub\" style=\"font-weight:600\">${pct(x.share)}<\/div><\/div><div class=\"lr-bar\"><i style=\"width:${(x.v\/fmax*100).toFixed(0)}%\"><\/i><\/div><\/div>`)));\n    fmtCard.appendChild(fl); r3.appendChild(fmtCard);\n    const znCard=card('Screens by zone','where the broadcast inventory sits','',' ');\n    const zl=h('<div class=\"loclist\"><\/div>'); const zmax=Math.max(...sg.byZone.map(x=>x.screens));\n    sg.byZone.slice().sort((a,b)=>b.screens-a.screens).forEach(x=>{const row=h(`<div class=\"locrow\"><div><div class=\"lr-name\">${x.name}<\/div><div class=\"lr-sub\">${x.screens} screens<\/div><\/div><div class=\"lr-val\">${money(x.v)}<div class=\"lr-sub\" style=\"font-weight:600\">\/yr<\/div><\/div><span class=\"chev\">\u203a<\/span><div class=\"lr-bar\"><i style=\"width:${(x.screens\/zmax*100).toFixed(0)}%\"><\/i><\/div><\/div>`);row.addEventListener('click',()=>go('#\/location\/'+x.id));zl.appendChild(row);});\n    znCard.appendChild(zl); r3.appendChild(znCard);\n    wrap.appendChild(r3);\n\n    const mixCard=card('Revenue mix \u2014 kiosk vs signage','the two surfaces, side by side','',' ');\n    const mixParts=[{v:m.rev,name:'Interactive kiosks',color:'var(--s-hotels)'},{v:sg.rev,name:'Digital signage',color:'var(--s-attractions)'}];\n    const mpin=h('<div style=\"display:flex;gap:20px;align-items:center;flex-wrap:wrap\"><\/div>'); mpin.appendChild(donut(mixParts));\n    const mpl=h('<div style=\"flex:1;min-width:200px\"><\/div>');\n    mixParts.forEach(p=>mpl.appendChild(h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div class=\"lr-name\" style=\"display:flex;align-items:center;gap:7px\"><span class=\"sw\" style=\"width:11px;height:11px;border-radius:3px;background:${p.color}\"><\/span>${p.name}<\/div><div class=\"lr-val\">${money(p.v)}<div class=\"lr-sub\" style=\"font-weight:600\">${pct(p.v\/t.total)}<\/div><\/div><\/div>`)));\n    mpl.appendChild(h(`<div class=\"locrow\" style=\"grid-template-columns:1fr auto\"><div class=\"lr-name\"><b>Total Advertising Revenue<\/b><\/div><div class=\"lr-val\"><b>${money(t.total)}<\/b><\/div><\/div>`));\n    mpin.appendChild(mpl); mixCard.appendChild(mpin);\n    mixCard.appendChild(h('<div class=\"note\">Signage is the larger screen count and the cheaper per-unit sell; kiosks are the smaller count and the premium, interactive, QR-convertible sell. Reporting them separately and then combining is what keeps the headline honest.<\/div>'));\n    wrap.appendChild(mixCard); wrap.lastChild.style.marginBottom='16px';\n  }\n\n  const rampC=card('Advertising ramp \u00b7 kiosks + digital signage','builds with units online and sell-through','',' ');\n  const rl=h('<div class=\"loclist\"><\/div>');\n  const NKtot=rollup(1).kiosks;\n  PHASES.forEach(ph=>{const locs=LOCS().filter(L=>ph.ids.includes(L.id));const mm=mediaMetrics(k,locs);const sgm=signageMetrics(k,locs);\n    const fill=MEDIA.fillByPhase[ph.n];const rev=mm.rev*(fill\/MEDIA.fillMature);\n    const sfill=SIGNAGE.fillByPhase[ph.n];const srev=sgm?sgm.rev*(sfill\/SIGNAGE.fillMature):0;\n    rl.appendChild(h(`<div class=\"locrow\"><div><div class=\"lr-name\">${ph.name}<\/div><div class=\"lr-sub\">${ph.window} \u00b7 ${mm.kiosks} kiosks${sgm?` \u00b7 ${sgm.screens} screens`:''} \u00b7 ${pct(fill)} fill<\/div><\/div><div class=\"lr-val\">${money(rev+srev)}<div class=\"lr-sub\" style=\"font-weight:600\">kiosk ${money(rev)} \u00b7 signage ${money(srev)}<\/div><\/div><div class=\"lr-bar\"><i style=\"width:${(mm.kiosks\/NKtot*100).toFixed(0)}%\"><\/i><\/div><\/div>`));});\n  rampC.appendChild(rl);\n  rampC.appendChild(h('<div class=\"note\">Revenue scales with units online and with sell-through as impressions grow. In a mid-market like Evansville the direct-sold base is regional \u2014 hospitals, the universities, auto, restaurant groups, banks, and the tournament sponsors already buying around the sports complexes; programmatic (Google Ad Manager) fills remnant inventory once volume attracts national demand.<\/div>'));\n  wrap.appendChild(rampC);\n\n  const sf=card('The self-funding math','advertising vs. program cost \u00b7 kiosks + signage','',' ');\n  sf.appendChild(h(`<div class=\"stat-inline\" style=\"margin-top:4px\"><div class=\"si\"><b>${money(t.total)}<\/b><span>Total Advertising Revenue \/ yr<\/span><\/div><div class=\"si\"><b>${money(t.softwareYr)}<\/b><span>annual software (kiosk ${money(MEDIA.softwareYr)} + signage ${money(sg?sg.softwareYr:0)})<\/span><\/div><div class=\"si\"><b>${money(t.capital)}<\/b><span>one-time capital (kiosk ${money(MEDIA.capital)} + signage ${money(sg?sg.capital:0)})<\/span><\/div><div class=\"si\"><b style=\"color:var(--good)\">${t.payback.toFixed(1)} yr<\/b><span>combined capital payback (mid)<\/span><\/div><\/div>`));\n  sf.appendChild(h('<div class=\"note\">At the mid scenario, advertising covers the combined annual software many times over and repays the full hardware investment inside a year. This matters more for a mid-market DMO than for a large one: Explore Evansville does not have to find new budget to instrument its destination \u2014 the network pays for itself out of inventory it already owns, in the same way the 8% innkeeper&rsquo;s tax already funds capital projects and marketing. All media and signage economics here are <b>MODELED<\/b> \u2014 no rate card, proposal or fill curve exists for Explore Evansville.<\/div>'));\n  wrap.appendChild(sf);\n  return wrap;\n}\n\n\/* ================= ROUTER ================= *\/\nconst state={loc:null};\nfunction go(hash){location.hash=hash;}\nfunction render(){\n  buildDestSel();\n  const hash=location.hash||'#\/overview';\n  const parts=hash.replace('#\/','').split('\/');\n  if(activeDest==='network'){\n    app.innerHTML='';\n    if(parts[0]==='modules'){engMode='modules';app.appendChild(pageEngagement());}\n    else if(parts[0]==='campaigns'){engMode='campaigns';app.appendChild(pageEngagement());}\n    else app.appendChild(pageNetwork());\n    window.scrollTo({top:0,behavior:'instant'});return;\n  }\n  state.loc = parts[0]==='location'?parts[1]:null;\n  app.innerHTML='';\n  let node;\n  if(parts[0]==='location') node=pageLocation(parts[1]);\n  else if(parts[0]==='partners') node=pagePartners();\n  else if(parts[0]==='tax') node=pageTax();\n  else if(parts[0]==='modules'){engMode='modules';node=pageEngagement();}\n  else if(parts[0]==='campaigns'){engMode='campaigns';node=pageEngagement();}\n  else if(parts[0]==='media') node=pageMedia();\n  else node=pageOverview();\n  app.appendChild(node);\n  window.scrollTo({top:0,behavior:'instant'});\n}\nwindow.addEventListener('hashchange',render);\n\n\/\/ destination selector (rebuilt each render to reflect active)\nfunction buildDestSel(){\n  const host=$('#destSel');if(!host)return;\n  const opts=[...Object.keys(DESTINATIONS).map(id=>[id,DESTINATIONS[id].name])];\n  host.innerHTML=opts.map(([id,label])=>`<option value=\"${id}\"${id===activeDest?' selected':''}>${label}<\/option>`).join('');\n}\n\n\/\/ period selector\n$('#periodSel').addEventListener('click',e=>{const b=e.target.closest('button');if(!b)return;\n  [...$('#periodSel').children].forEach(x=>x.classList.remove('on'));b.classList.add('on');PERIOD=b.dataset.p;render();});\n\/\/ destination selector\n$('#destSel').addEventListener('change',e=>setDest(e.target.value));\n\/\/ theme\n$('#themeBtn').addEventListener('click',()=>{const cur=document.documentElement.getAttribute('data-theme');document.documentElement.setAttribute('data-theme',cur==='dark'?'light':'dark');render();});\nwindow.addEventListener('mousemove',e=>{if(TT.style.opacity==1)moveTT(e);});\n\nrender();\n<\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>TrueImpact \u2014 Tableau de bord ex\u00e9cutif \u00b7 Explorez Evansville<\/p>","protected":false},"author":11,"featured_media":57099,"comment_status":"open","ping_status":"open","sticky":false,"template":"elementor_canvas","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"postBodyCss":"","postBodyMargin":[],"postBodyPadding":[],"postBodyBackground":{"backgroundType":"classic","gradient":""},"_thinkrank_schema_form_data":"","_thinkrank_selected_schema_type":"","_thinkrank_additional_schemas":"","_thinkrank_canonical_url":"","_thinkrank_og_title":"","_thinkrank_og_description":"","_thinkrank_og_image":"","_thinkrank_twitter_title":"","_thinkrank_twitter_description":"","_thinkrank_twitter_image":"","_thinkrank_imported_from":"","_thinkrank_focus_keywords":[],"_thinkrank_focus_keyword":"","_thinkrank_robots_meta_enabled":0,"_thinkrank_robots_meta":"","_thinkrank_advanced_robots_meta":"","_thinkrank_primary_category":0,"footnotes":""},"categories":[1171],"tags":[1176,1172],"class_list":["post-58031","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-true-impact","tag-explore-evansville","tag-trueimpact"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.9 (Yoast SEO v28.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>ExploreEvansville - TrueOmni<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trueomni.com\/french\/true-impact\/exploreevansville\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ExploreEvansville\" \/>\n<meta property=\"og:description\" content=\"TrueImpact \u2014 Executive Dashboard \u00b7 Explore Evansville\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trueomni.com\/french\/true-impact\/exploreevansville\/\" \/>\n<meta property=\"og:site_name\" content=\"TrueOmni\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/trueomni\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-31T21:40:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-31T21:42:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/trueomni.com\/wp-content\/uploads\/2026\/05\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-1024x753.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"753\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Ruben Ramirez\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ruben Ramirez\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/\"},\"author\":{\"name\":\"Ruben Ramirez\",\"@id\":\"http:\\\/\\\/trueomni.com\\\/#\\\/schema\\\/person\\\/063bf88aea0a02d03a0115375148bf2b\"},\"headline\":\"ExploreEvansville\",\"datePublished\":\"2026-07-31T21:40:09+00:00\",\"dateModified\":\"2026-07-31T21:42:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/\"},\"wordCount\":6,\"commentCount\":0,\"publisher\":{\"@id\":\"http:\\\/\\\/trueomni.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/trueomni.com\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png\",\"keywords\":[\"Explore Evansville\",\"TrueImpact\"],\"articleSection\":[\"True Impact\"],\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/\",\"url\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/\",\"name\":\"ExploreEvansville - TrueOmni\",\"isPartOf\":{\"@id\":\"http:\\\/\\\/trueomni.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/trueomni.com\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png\",\"datePublished\":\"2026-07-31T21:40:09+00:00\",\"dateModified\":\"2026-07-31T21:42:51+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#primaryimage\",\"url\":\"https:\\\/\\\/trueomni.com\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png\",\"contentUrl\":\"https:\\\/\\\/trueomni.com\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png\",\"width\":2560,\"height\":1883,\"caption\":\"TrueOmni interactive kiosks in a hotel lobby\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/trueomni.com\\\/true-impact\\\/exploreevansville\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"http:\\\/\\\/trueomni.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"ExploreEvansville\"}]},{\"@type\":\"WebSite\",\"@id\":\"http:\\\/\\\/trueomni.com\\\/#website\",\"url\":\"http:\\\/\\\/trueomni.com\\\/\",\"name\":\"TrueOmni\",\"description\":\"TrueOmni Self-Service Digital Customer Experience Company\",\"publisher\":{\"@id\":\"http:\\\/\\\/trueomni.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\\\/\\\/trueomni.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"http:\\\/\\\/trueomni.com\\\/#organization\",\"name\":\"TRUE OMNI LLC\",\"alternateName\":\"TRUE OMNI LLC\",\"url\":\"http:\\\/\\\/trueomni.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"http:\\\/\\\/trueomni.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"http:\\\/\\\/trueomni.com\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/TrueOmni-Logo-2.png\",\"contentUrl\":\"http:\\\/\\\/trueomni.com\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/TrueOmni-Logo-2.png\",\"width\":1000,\"height\":230,\"caption\":\"TRUE OMNI LLC\"},\"image\":{\"@id\":\"http:\\\/\\\/trueomni.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/trueomni\\\/\"],\"description\":\"TrueOmni is the leader in digital self-service solutions, offering innovative kiosks, digital signage, and mobile marketing platforms. Enhance customer engagement and streamline operations with our cutting-edge technology tailored for the hospitality, retail, and tourism industries.\",\"email\":\"info@trueomni.com\",\"telephone\":\"8333006664\",\"legalName\":\"True Omni LLC\"},{\"@type\":\"Person\",\"@id\":\"http:\\\/\\\/trueomni.com\\\/#\\\/schema\\\/person\\\/063bf88aea0a02d03a0115375148bf2b\",\"name\":\"Ruben Ramirez\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e5f68af99ae89c8a9e4ccd0d7e8d00309bb80f5b0cd9c21768a7dd9f6daea70f?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e5f68af99ae89c8a9e4ccd0d7e8d00309bb80f5b0cd9c21768a7dd9f6daea70f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e5f68af99ae89c8a9e4ccd0d7e8d00309bb80f5b0cd9c21768a7dd9f6daea70f?s=96&d=mm&r=g\",\"caption\":\"Ruben Ramirez\"},\"url\":\"https:\\\/\\\/trueomni.com\\\/french\\\/author\\\/ruben\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"ExploreEvansville - TrueOmni","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trueomni.com\/french\/true-impact\/exploreevansville\/","og_locale":"fr_FR","og_type":"article","og_title":"ExploreEvansville","og_description":"TrueImpact \u2014 Executive Dashboard \u00b7 Explore Evansville","og_url":"https:\/\/trueomni.com\/french\/true-impact\/exploreevansville\/","og_site_name":"TrueOmni","article_publisher":"https:\/\/www.facebook.com\/trueomni\/","article_published_time":"2026-07-31T21:40:09+00:00","article_modified_time":"2026-07-31T21:42:51+00:00","og_image":[{"width":1024,"height":753,"url":"https:\/\/trueomni.com\/wp-content\/uploads\/2026\/05\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-1024x753.png","type":"image\/png"}],"author":"Ruben Ramirez","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"Ruben Ramirez","Dur\u00e9e de lecture estim\u00e9e":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/#article","isPartOf":{"@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/"},"author":{"name":"Ruben Ramirez","@id":"http:\/\/trueomni.com\/#\/schema\/person\/063bf88aea0a02d03a0115375148bf2b"},"headline":"ExploreEvansville","datePublished":"2026-07-31T21:40:09+00:00","dateModified":"2026-07-31T21:42:51+00:00","mainEntityOfPage":{"@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/"},"wordCount":6,"commentCount":0,"publisher":{"@id":"http:\/\/trueomni.com\/#organization"},"image":{"@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/#primaryimage"},"thumbnailUrl":"https:\/\/trueomni.com\/wp-content\/uploads\/2026\/05\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png","keywords":["Explore Evansville","TrueImpact"],"articleSection":["True Impact"],"inLanguage":"fr-FR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/trueomni.com\/true-impact\/exploreevansville\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/","url":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/","name":"ExploreEvansville - TrueOmni","isPartOf":{"@id":"http:\/\/trueomni.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/#primaryimage"},"image":{"@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/#primaryimage"},"thumbnailUrl":"https:\/\/trueomni.com\/wp-content\/uploads\/2026\/05\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png","datePublished":"2026-07-31T21:40:09+00:00","dateModified":"2026-07-31T21:42:51+00:00","breadcrumb":{"@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trueomni.com\/true-impact\/exploreevansville\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/#primaryimage","url":"https:\/\/trueomni.com\/wp-content\/uploads\/2026\/05\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png","contentUrl":"https:\/\/trueomni.com\/wp-content\/uploads\/2026\/05\/Travel-TrueOmni-TNT-IVE-Kiosks-2026-Website-scaled.png","width":2560,"height":1883,"caption":"TrueOmni interactive kiosks in a hotel lobby"},{"@type":"BreadcrumbList","@id":"https:\/\/trueomni.com\/true-impact\/exploreevansville\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/trueomni.com\/"},{"@type":"ListItem","position":2,"name":"ExploreEvansville"}]},{"@type":"WebSite","@id":"http:\/\/trueomni.com\/#website","url":"http:\/\/trueomni.com\/","name":"TrueOmni","description":"TrueOmni Self-Service Digital Customer Experience Company","publisher":{"@id":"http:\/\/trueomni.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/trueomni.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"http:\/\/trueomni.com\/#organization","name":"TRUE OMNI LLC","alternateName":"TRUE OMNI LLC","url":"http:\/\/trueomni.com\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"http:\/\/trueomni.com\/#\/schema\/logo\/image\/","url":"http:\/\/trueomni.com\/wp-content\/uploads\/2024\/06\/TrueOmni-Logo-2.png","contentUrl":"http:\/\/trueomni.com\/wp-content\/uploads\/2024\/06\/TrueOmni-Logo-2.png","width":1000,"height":230,"caption":"TRUE OMNI LLC"},"image":{"@id":"http:\/\/trueomni.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/trueomni\/"],"description":"TrueOmni is the leader in digital self-service solutions, offering innovative kiosks, digital signage, and mobile marketing platforms. Enhance customer engagement and streamline operations with our cutting-edge technology tailored for the hospitality, retail, and tourism industries.","email":"info@trueomni.com","telephone":"8333006664","legalName":"True Omni LLC"},{"@type":"Person","@id":"http:\/\/trueomni.com\/#\/schema\/person\/063bf88aea0a02d03a0115375148bf2b","name":"Ruben Ramirez","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/secure.gravatar.com\/avatar\/e5f68af99ae89c8a9e4ccd0d7e8d00309bb80f5b0cd9c21768a7dd9f6daea70f?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/e5f68af99ae89c8a9e4ccd0d7e8d00309bb80f5b0cd9c21768a7dd9f6daea70f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e5f68af99ae89c8a9e4ccd0d7e8d00309bb80f5b0cd9c21768a7dd9f6daea70f?s=96&d=mm&r=g","caption":"Ruben Ramirez"},"url":"https:\/\/trueomni.com\/french\/author\/ruben\/"}]}},"_links":{"self":[{"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/posts\/58031","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/comments?post=58031"}],"version-history":[{"count":5,"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/posts\/58031\/revisions"}],"predecessor-version":[{"id":58058,"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/posts\/58031\/revisions\/58058"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/media\/57099"}],"wp:attachment":[{"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/media?parent=58031"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/categories?post=58031"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trueomni.com\/french\/wp-json\/wp\/v2\/tags?post=58031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}