1<!DOCTYPE html> 2<html lang="en" data-theme="dark"> 3 4<head> 5<style id="pollsmax-home-ad-wells-first-paint"> 6@media (min-width:768px){ 7body.pollsmax-home-page .pm-tx-ad-band.pm-tx-ad-band--desktop{display:flex!important;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;width:100%;background:#0b0e13;border-top:none;border-bottom:1px solid rgb(30 41 55 / 0.8);padding:16px 1.5rem!important;min-height:calc(250px + 32px)!important;height:calc(250px + 32px)!important;max-height:calc(250px + 32px)!important;overflow:hidden;flex-shrink:0} 8body.pollsmax-home-page .pm-tx-ad-band.pm-tx-ad-band--desktop .pm-ad-slot{display:flex!important;align-items:center;justify-content:center;box-sizing:border-box;width:100%;min-height:250px!important;height:250px!important;max-height:250px!important;margin:0;padding:0;overflow:hidden} 9body.pollsmax-home-page .pm-tx-ad-band--mobile{display:none!important;height:0!important;min-height:0!important;margin:0!important;padding:0!important;overflow:hidden!important;pointer-events:none!important} 10} 11@media (max-width:767px){ 12body.pollsmax-home-page .pm-tx-ad-band--mobile{display:flex!important;flex-direction:column;align-items:center;justify-content:center;width:100%;text-align:center;box-sizing:border-box} 13body.pollsmax-home-page .pm-tx-ad-band--mobile .pm-ad-slot,body.pollsmax-home-page .pm-tx-ad-band--mobile .pollsmax-ad-single__inner{display:flex!important;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center;width:100%;text-align:center;box-sizing:border-box} 14body.pollsmax-home-page .pm-tx-ad-band--mobile .pm-ad-slot>*,body.pollsmax-home-page .pm-tx-ad-band--mobile .pollsmax-ad-single__inner>*{display:flex!important;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center;width:100%;max-width:100%;margin-left:auto!important;margin-right:auto!important;float:none!important;box-sizing:border-box} 15body.pollsmax-home-page .pm-tx-ad-band--mobile iframe,body.pollsmax-home-page .pm-tx-ad-band--mobile img{display:block!important;margin-left:auto!important;margin-right:auto!important;float:none!important;max-width:100%;flex-shrink:0} 16} 17</style> 18
19<script> 20 (function () { 21 try { 22 document.documentElement.setAttribute("data-theme", "dark"); 23 document.documentElement.style.colorScheme = "dark"; 24 document.documentElement.removeAttribute("data-pollsmax-theme"); 25 try { 26 localStorage.setItem("pollsmax-theme", "dark"); 27 localStorage.setItem("pollsmax-home-theme", "dark"); 28 } catch (eStore) { /* ignore */ } 29 } catch (error) { 30 document.documentElement.setAttribute("data-theme", "dark"); 31 document.documentElement.style.colorScheme = "dark"; 32 } 33 /* First-paint mobile layout (Search All Polls + panels): don't wait for deferred shared.js */ 34 try { 35 if (window.matchMedia && window.matchMedia("(max-width: 767px)").matches) { 36 document.documentElement.classList.add("et-mobile-active"); 37 } 38 } catch (eMob) { /* ignore */ } 39 })(); 40 </script>
40 41 <style id="pollsmax-mobile-header-first-paint"> 42 @media (max-width:767px) { 43 html { --et-mobile-header-h: calc(57px + env(safe-area-inset-top, 0px)); } 44 #mainHeader { 45 position: fixed !important; top: 0 !important; left: 0 !important; right: 0 !important; 46 width: 100% !important; z-index: 60 !important; 47 padding-top: env(safe-area-inset-top, 0px) !important; box-sizing: border-box !important; 48 background: var(--color-header-bg, rgba(5, 6, 8, 0.97)) !important; 49 border-bottom: 1px solid var(--color-border-default, rgba(51, 65, 85, 0.45)) !important; 50 transition: none !important; 51 } 52 body { padding-top: var(--et-mobile-header-h) !important; } 53 body:has(#et-mobile-page-shell) { padding-top: 0 !important; } 54 #et-mobile-page-shell { padding-top: var(--et-mobile-header-h) !important; } 55 #mainHeader nav, #mainHeader nav.flex { display: none !important; } 56 #site-primary-nav, nav.sleek-sitelinks-strip, .sleek-sitelinks-strip.flex { display: none !important; } 57 #mainHeader .sleek-home-header-meta, 58 #mainHeader .flex.items-center.justify-between > div:not(:first-child) { display: none !important; } 59 #mainHeader a[href*="x.com/Pollsmax"], 60 #mainHeader a[href*="twitter.com/Pollsmax"], 61 #mainHeader img[alt="Pollsmax on X"], 62 #mainHeader img[alt="Twitter"] { display: none !important; } 63 #mainHeader .et-mobile-nav-btn { display: inline-flex !important; } 64 } 65 </style> 66 67 <!-- Correct chrome on first paint (don't wait for shared.js) --> 68 <link rel="stylesheet" href="/assets/pollsmax-responsive-unified.css?v=drawer-x-white" data-pollsmax-responsive-unified="1" /> 69 <style id="pollsmax-home-forecast-ready-gate"> 70 /* Hub-style prerendered maps: visible on first paint (same as senate/gov/house hubs). */ 71 /* Legacy empty-shell maps: wait so senate & gov reveal together after JS build. */ 72 html:not(.et-home-forecast-ready) body.pollsmax-home-page .sleek-maps .home-forecast-map-stage:not(:has(svg[data-chamber-map-prerendered="1"])):not(:has(svg[data-house-map-prerendered="1"])) { 73 opacity: 0 !important; 74 visibility: hidden !important; 75 pointer-events: none !important; 76 } 77 html.et-home-forecast-ready body.pollsmax-home-page .sleek-maps .home-forecast-map-stage { 78 opacity: 1; 79 visibility: visible; 80 pointer-events: auto; 81 } 82 /* House CD map (client-built only): keep hidden until bake + flip paint settles. */ 83 html.et-home-forecast-ready:not(.et-home-house-map-ready) body.pollsmax-home-page .home-forecast-map-stage--house:not(:has(svg[data-house-map-prerendered="1"])) { 84 opacity: 0 !important; 85 visibility: hidden !important; 86 pointer-events: none !important; 87 } 88 html.et-home-house-map-ready body.pollsmax-home-page .home-forecast-map-stage--house, 89 body.pollsmax-home-page .home-forecast-map-stage--house:has(svg[data-house-map-prerendered="1"]) { 90 opacity: 1; 91 visibility: visible; 92 pointer-events: auto; 93 } 94 body.pollsmax-home-page g.et-house-flip-outline-layer, 95 body.pollsmax-home-page g.et-house-flip-outline-layer path { 96 pointer-events: none !important; 97 } 98 /* Reserve map stage height so layout doesn't jump when maps paint */ 99 body.pollsmax-home-page .home-forecast-map-stage { 100 min-height: 0; 101 aspect-ratio: 1000 / 600; 102 } 103 body.pollsmax-home-page .home-forecast-map-stage svg { 104 width: 100%; 105 height: auto; 106 display: block; 107 } 108 </style> 109 <!-- gtag deferred until after load (see home-lazy-boot.js) for faster first paint --> 110
110<script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);}</script>
110 111 112
112<script src="/assets/pm-theme-boot-20260903e.js"></script>
112 113
113<script> 114 /* FDT Phase 1: warm cache for externalized home map SVGs (cacheable; not inlined in HTML). */ 115 (function () { 116 var VER = '20260926chamberhub0945'; 117 var maps = [ 118 ['/fragments/home-us-map.svg?v=' + VER, '__pmHomeUsMapFrag'], 119 ['/fragments/home-house-cd-map.svg?v=' + VER, '__pmHomeHouseMapFrag'], 120 ['/fragments/home-gov-map.svg?v=' + VER, '__pmHomeGovMapFrag'] 121 ]; 122 var head = document.head || document.documentElement; 123 maps.forEach(function (pair) { 124 try { 125 var l = document.createElement('link'); 126 l.rel = 'preload'; 127 l.as = 'fetch'; 128 l.href = pair[0]; 129 l.crossOrigin = 'anonymous'; 130 head.appendChild(l); 131 } catch (eL) { /* ignore */ } 132 try { 133 fetch(pair[0], { credentials: 'same-origin' }).then(function (r) { 134 return r.ok ? r.text() : ''; 135 }).then(function (t) { 136 if (t) window[pair[1]] = t; 137 }).catch(function () {}); 138 } catch (eF) { /* ignore */ } 139 }); 140 })(); 141 </script>
vendor: 1 bytes, line 141
141
142<script>window.POLLSMAX_HUB_UI_REV = '107';</script>
142 143
143<script> 144 window.ET = window.ET || {}; 145 /* Keep home 50/50 seat bars until senate+gov maps reveal together (client-built only). */ 146 window.ET.homeForecastDeferSeatBars = true; 147 </script>
147 148
148<script> 149 /* Hub-style prerendered maps: show immediately; don't blank fills over baked colors. */ 150 (function () { 151 function hasPrerender(id, attr) { 152 var el = document.getElementById(id); 153 return !!(el && el.getAttribute(attr) === '1'); 154 } 155 /* Runs after body parses â also re-check on DOMContentLoaded. */ 156 function markReadyIfPrerendered() { 157 var senate = hasPrerender('usMap', 'data-chamber-map-prerendered'); 158 var gov = hasPrerender('govMap', 'data-chamber-map-prerendered'); 159 var house = hasPrerender('houseCdMap', 'data-house-map-prerendered'); 160 if (senate && gov) { 161 document.documentElement.classList.add('et-home-forecast-ready'); 162 if (window.ET) { 163 window.ET.homeForecastShellBlank = false; 164 window.ET.homeForecastDeferSeatBars = true; /* bars still fill after model */ 165 } 166 } 167 if (house) document.documentElement.classList.add('et-home-house-map-ready'); 168 } 169 if (document.readyState === 'loading') { 170 document.addEventListener('DOMContentLoaded', markReadyIfPrerendered); 171 } else { 172 markReadyIfPrerendered(); 173 } 174 })(); 175 </script>
175 176 177 <meta charset="utf-8" /> 178 <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" /> 179 <link rel="preload" href="/assets/forecast-hub-map-ui.css?v=chevron-align-1" as="style" /> 180 <link rel="preload" href="/assets/donate-page.css?v=donate-card-cqi-1" as="style" /> 181 <link rel="preload" href="/assets/pm-shared-20260714s.js?v=hub-polls-20260926" as="script" /> 182 <!-- home-mob-chart-0w-1: do not pin mobile canvases at 0px width --> 183 <title>2026 Senate, House & Governor Forecasts | Pollsmax</title> 184 <meta name="description" 185 content="See the latest forecasts for the 2026 Senate, House, and governor elections, with polling averages, race ratings, and interactive maps."> 186 <link rel="canonical" href="https://www.pollsmax.com/" /> 187 <!-- Browser tabs: 16/32/ico at full-size X. Google Search: 48/96 at 80% X (both transparent). --> 188 <link rel="icon" href="/favicon.ico" sizes="any"> 189 <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> 190 <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"> 191 <link rel="icon" type="image/png" sizes="48x48" href="/favicon-48x48.png"> 192 <link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"> 193 <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
194<script type="application/ld+json"> 195 { 196 "@context": "https://schema.org", 197 "@graph": [ 198 { 199 "@type": "WebSite", 200 "@id": "https://www.pollsmax.com/#website", 201 "name": "Pollsmax", 202 "url": "https://www.pollsmax.com/", 203 "hasPart": [ 204 { "@type": "WebPage", "name": "Latest Polls", "url": "https://www.pollsmax.com/latest-polls/" }, 205 { "@type": "WebPage", "name": "2026 Senate Forecast", "url": "https://www.pollsmax.com/senate/" }, 206 { "@type": "WebPage", "name": "2026 House Forecast", "url": "https://www.pollsmax.com/2026-us-house/" }, 207 { "@type": "WebPage", "name": "2026 Governor Forecast", "url": "https://www.pollsmax.com/governor/" }, 208 { "@type": "WebPage", "name": "Trump Approval", "url": "https://www.pollsmax.com/approval/trump/" }, 209 { "@type": "WebPage", "name": "Generic Ballot", "url": "https://www.pollsmax.com/approval/generic-ballot/" }, 210 { "@type": "WebPage", "name": "2028 Democratic Primary", "url": "https://www.pollsmax.com/2028-democratic-primary/" }, 211 { "@type": "WebPage", "name": "2028 Republican Primary", "url": "https://www.pollsmax.com/2028-republican-primary/" }, 212 { "@type": "WebPage", "name": "Electoral History", "url": "https://www.pollsmax.com/electoral-history/" } 213 ] 214 }, 215 { 216 "@type": "SiteNavigationElement", 217 "@id": "https://www.pollsmax.com/#site-primary-nav", 218 "name": "Pollsmax primary sections", 219 "url": "https://www.pollsmax.com/", 220 "hasPart": [ 221 { "@type": "WebPage", "name": "Latest Polls", "url": "https://www.pollsmax.com/latest-polls/" }, 222 { "@type": "WebPage", "name": "2026 Senate Forecast", "url": "https://www.pollsmax.com/senate/" }, 223 { "@type": "WebPage", "name": "2026 House Forecast", "url": "https://www.pollsmax.com/2026-us-house/" }, 224 { "@type": "WebPage", "name": "2026 Governor Forecast", "url": "https://www.pollsmax.com/governor/" }, 225 { "@type": "WebPage", "name": "Trump Approval", "url": "https://www.pollsmax.com/approval/trump/" }, 226 { "@type": "WebPage", "name": "Generic Ballot", "url": "https://www.pollsmax.com/approval/generic-ballot/" }, 227 { "@type": "WebPage", "name": "2028 Democratic Primary", "url": "https://www.pollsmax.com/2028-democratic-primary/" }, 228 { "@type": "WebPage", "name": "2028 Republican Primary", "url": "https://www.pollsmax.com/2028-republican-primary/" }, 229 { "@type": "WebPage", "name": "Electoral History", "url": "https://www.pollsmax.com/electoral-history/" } 230 ] 231 }, 232 { 233 "@type": "ItemList", 234 "@id": "https://www.pollsmax.com/#primary-sitelinks", 235 "name": "Pollsmax primary sections", 236 "itemListElement": [ 237 { "@type": "ListItem", "position": 1, "name": "Latest Polls", "url": "https://www.pollsmax.com/latest-polls/" }, 238 { "@type": "ListItem", "position": 2, "name": "2026 Senate Forecast", "url": "https://www.pollsmax.com/senate/" }, 239 { "@type": "ListItem", "position": 3, "name": "2026 House Forecast", "url": "https://www.pollsmax.com/2026-us-house/" }, 240 { "@type": "ListItem", "position": 4, "name": "2026 Governor Forecast", "url": "https://www.pollsmax.com/governor/" }, 241 { "@type": "ListItem", "position": 5, "name": "Trump Approval", "url": "https://www.pollsmax.com/approval/trump/" }, 242 { "@type": "ListItem", "position": 6, "name": "Generic Ballot", "url": "https://www.pollsmax.com/approval/generic-ballot/" }, 243 { "@type": "ListItem", "position": 7, "name": "2028 Democratic Primary", "url": "https://www.pollsmax.com/2028-democratic-primary/" }, 244 { "@type": "ListItem", "position": 8, "name": "2028 Republican Primary", "url": "https://www.pollsmax.com/2028-republican-primary/" }, 245 { "@type": "ListItem", "position": 9, "name": "Electoral History", "url": "https://www.pollsmax.com/electoral-history/" } 246 ] 247 } 248 ] 249 } 250 </script>
250 251 <link rel="preconnect" href="https://fonts.googleapis.com" /> 252 253 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 254 255 <link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700&family=Plus+Jakarta+Sans:wght@500;600;700&display=swap" rel="stylesheet" /> 256<link rel="stylesheet" href="/assets/pm-site-chrome-20260714i.css" /> 257 <link rel="stylesheet" href="/assets/sleek-map-tip.css?v=home-house-tip-1" /> 258 <link rel="stylesheet" href="/assets/forecast-hub-map-ui.css?v=chevron-align-1" /> 259<link rel="stylesheet" href="/assets/tailwind-compiled.css?v=1" /> 260 <link rel="stylesheet" href="/assets/home-ads-20260901c.css" /> 261 <link rel="stylesheet" href="/assets/donate-page.css?v=donate-card-cqi-1" /> 262 <!-- Map-critical only on first paint. Chart.js + national chart packs load via home-lazy-boot.js --> 263 <!-- POLLSMAX_HOME_FAST_BOOT: set false + restore scripts listed in assets/home-fast-boot.js to revert. --> 264
264<script>window.POLLSMAX_HOME_FAST_BOOT = true;</script>
264 265
265<script defer src="/assets/d3.min.js?v=1"></script>
265 266
266<script defer src="/assets/topojson-client.min.js?v=1"></script>
266 267
267<script defer src="/assets/pollster-canonical.js?v=1"></script>
267 268
268<script defer src="/assets/cook-pvi-data.js?v=1"></script>
268 269
269<script defer src="/assets/cook-race-ratings.js?v=4"></script>
269 270
270<script defer src="/assets/editorial-ratings.js?v=gov-no-gray-tie-1"></script>
270 271
271<script defer src="/assets/forecast-senate-electoral.js?v=1"></script>
271 272
272<script defer src="/assets/forecast-governor-electoral.js?v=1"></script>
272 273
273<script defer src="/assets/race-ge-page-manifest.js?v=gov-ge-keys-2"></script>
273 274
274<script defer src="/assets/chamber-hub-data.js?v=20260926chamberhub0945"></script>
274 275
275<script defer src="/assets/senate-hub-baked-forecast.js?v=20260926chamberhub0945"></script>
275 276
276<script defer src="/assets/gov-hub-baked-forecast.js?v=20260926chamberhub0945"></script>
276 277
277<script defer src="/assets/senate-hub-interactive-data.js?v=20260926chamberhub0945"></script>
277 278
278<script defer src="/assets/gov-hub-interactive-data.js?v=20260926chamberhub0945"></script>
278 279
279<script defer src="/assets/senate-hub-baked-map-tooltips.js?v=20260926chamberhub0945"></script>
279 280
280<script defer src="/assets/gov-hub-baked-map-tooltips.js?v=20260926chamberhub0945"></script>
280 281
281<script defer src="/assets/chamber-hub-enhance.js?v=20260926chamberhub0945"></script>
281 282 <!-- shared.js early: Senate/Gov hover binds as soon as this finishes (House stack is lazy). --> 283
283<script defer src="/assets/pm-shared-20260714s.js?v=hub-polls-20260926"></script>
283 284
284<script defer src="/assets/forecast-hub-map-ui.js?v=cd-sec-sync-1"></script>
284 285
285<script defer src="/assets/home-fast-boot.js?v=20260926chamberhub0945"></script>
285 286
286<script defer src="/assets/home-forecast-chance.js?v=home-chance-gov-map-1"></script>
286 287
287<script defer src="/assets/home-panel-blurbs.js?v=gb-home-comma-20260902"></script>
287 288
288<script defer src="/assets/home-lazy-boot.js?v=honest-20260925"></script>
288 289
289<script src="/assets/house-cd-map-rev.js"></script>
289 290 <!-- POLLSMAX_HOME_FAST_BOOT lazy (see assets/home-fast-boot.js): forecast-model, house-* --> 291
291<script> 292 window.__pollsmaxHomePollDotAlpha = 0.10; 293 window.__pollsmaxHomeGenericBluePollDotAlpha = 0.12; 294 window.__pollsmaxHomeTrumpGreenPollDotAlpha = 0.08; 295 /* Home mobile only: Approve poll dots slightly less transparent than desktop. */ 296 window.__pollsmaxHomeTrumpGreenPollDotAlphaMobile = 0.11; 297 /* Search All Polls + home 2028 primary charts: extra peak opacity on under-line glow. */ 298 window.__pollsmaxHomeLineGlowOpacityBoost = 0.03; 299 window.__pollsmaxHomeChartAxisPadPct = 2; 300 </script>
300 301 <style> 302 :root { 303 color-scheme: dark; 304 } 305 306 body { 307 background: #050608; 308 color: #e5e7eb; 309 } 310 311 .card { 312 background: #111827; 313 border: 1px solid #1f2937; 314 } 315 316 .pill { 317 background: #0f172a; 318 border: 1px solid #1e293b; 319 } 320 321 #usMap { 322 display: block; 323 margin: 0 auto; 324 width: 100%; 325 max-width: 1000px; 326 height: auto; 327 } 328 329 .et-chip { 330 display: inline-block; 331 color: #fff; 332 padding: var(--et-chip-py, .42rem) var(--et-chip-px, .6rem); 333 border-radius: var(--et-chip-radius, .55rem); 334 font-weight: var(--et-chip-fw, 700); 335 font-size: var(--et-chip-fs, .9rem); 336 line-height: 1; 337 white-space: nowrap; 338 } 339 340 .section-head { 341 background: #0b1220; 342 } 343 344 .quick-link { 345 transition: all 0.2s ease; 346 } 347 348 .quick-link:hover { 349 box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3); 350 } 351 352 .race-link { 353 transition: all 0.2s ease; 354 } 355 356 .race-link:hover { 357 opacity: 0.8; 358 } 359 360 /* Remove vertical line next to numbers in Latest Polls lists */ 361 #searchTable li>div:last-child, 362 #senateTable li>div:last-child, 363 #govTable li>div:last-child { 364 border: none !important; 365 border-left: none !important; 366 border-right: none !important; 367 } 368 369 /* ââ Sleek home: flat full-width layout, no card âbubblesâ ââ */ 370 body.sleek-home { 371 font-family: "DM Sans", ui-sans-serif, system-ui, sans-serif; 372 background: #050608; 373 color: #e2e8f0; 374 min-height: 100vh; 375 --color-chart-bg: #050608; 376 --color-section-band: #050608; 377 } 378 379 html:has(body.sleek-home.pollsmax-home-page) { 380 background: #050608; 381 } 382 383 /* Desktop home intro (logo + about) between top ad and Senate/House maps */ 384 .home-intro { 385 display: none; 386 } 387 388 @media (min-width: 1024px) { 389 .home-intro { 390 display: flex; 391 align-items: center; 392 gap: clamp(1.75rem, 3.2vw, 2.75rem); 393 padding: clamp(1.5rem, 2.6vw, 2.25rem) clamp(1.75rem, 4.5vw, 3.75rem); 394 background: #050608; 395 /* Single rule under intro; maps must not also paint a top rule. */ 396 border-top: none; 397 border-bottom: 1px solid rgba(51, 65, 85, 0.45); 398 } 399 400 .home-intro__logo-wrap { 401 --home-about-logo-h: clamp(4.75rem, 7.25vw, 6.25rem); 402 flex-shrink: 0; 403 height: var(--home-about-logo-h); 404 overflow: hidden; 405 line-height: 0; 406 } 407 408 .home-intro__logo { 409 display: block; 410 height: calc(var(--home-about-logo-h) / 0.6); 411 width: auto; 412 max-width: none; 413 margin-top: calc(var(--home-about-logo-h) / -0.6 * 0.2); 414 } 415 416 .home-intro__copy { 417 margin: 0; 418 flex: 1 1 auto; 419 min-width: 0; 420 max-width: none; 421 font-family: "Plus Jakarta Sans", "DM Sans", ui-sans-serif, system-ui, sans-serif; 422 font-size: clamp(0.92rem, 1.05vw, 1.02rem); 423 font-weight: 500; 424 line-height: 1.55; 425 letter-spacing: 0.01em; 426 color: #b6c2d1; 427 } 428 429 /* Match header hairline under the sitelinks strip (one line only). */ 430 body.sleek-home #site-primary-nav.sleek-sitelinks-strip, 431 body.sleek-home nav.sleek-sitelinks-strip { 432 border-bottom: 1px solid rgba(51, 65, 85, 0.45) !important; 433 } 434 435 /* 436 * Top-of-page hairlines (PC home), one 1px rule per junction: 437 * header border-b â nav 438 * nav border-b â ad 439 * ad ::after bottom hairline â intro 440 * (ad JS forces border-bottom:0 â cannot use a real border) 441 * intro border-b â maps 442 * maps: no border-t / ::before (would double with intro) 443 */ 444 body.pollsmax-home-page #pollsmaxPageTopAdDesktop:is([data-ad-state="filled"], [data-ad-state="live"]):not([data-pollsmax-ad-empty="1"]), 445 body.pollsmax-home-page #pollsmaxPageTopAdDesktop[data-ad-state="filled"] { 446 position: relative !important; 447 } 448 449 body.pollsmax-home-page #pollsmaxPageTopAdDesktop:is([data-ad-state="filled"], [data-ad-state="live"]):not([data-pollsmax-ad-empty="1"])::after, 450 body.pollsmax-home-page #pollsmaxPageTopAdDesktop[data-ad-state="filled"]::after { 451 content: "" !important; 452 display: block !important; 453 position: absolute !important; 454 left: 50% !important; 455 transform: translateX(-50%) !important; 456 bottom: 0 !important; 457 width: 100vw !important; 458 max-width: 100vw !important; 459 height: 1px !important; 460 margin: 0 !important; 461 padding: 0 !important; 462 border: 0 !important; 463 background: rgba(51, 65, 85, 0.45) !important; 464 pointer-events: none !important; 465 z-index: 5 !important; 466 } 467 468 /* Intro already has border-b â don't stack maps border-t or ads ::before. */ 469 body.pollsmax-home-page main .home-intro + .sleek-maps--home-senate-house { 470 border-top: none !important; 471 border-top-width: 0 !important; 472 border-top-color: transparent !important; 473 } 474 475 body.pollsmax-home-page main .home-intro + .sleek-maps--home-senate-house::before, 476 body.pollsmax-home-page:has(#pollsmaxPageTopAdDesktop[data-ad-state="filled"]) 477 main .home-intro + .sleek-maps--home-senate-house::before, 478 body.pollsmax-home-page:has(#pollsmaxPageTopAdDesktop:is([data-ad-state="filled"], [data-ad-state="live"]):not([data-pollsmax-ad-empty="1"])) 479 main .home-intro + .sleek-maps--home-senate-house::before { 480 content: none !important; 481 display: none !important; 482 background: none !important; 483 height: 0 !important; 484 } 485 486 html[data-pollsmax-theme="light"] body.pollsmax-home-page #pollsmaxPageTopAdDesktop:is([data-ad-state="filled"], [data-ad-state="live"]):not([data-pollsmax-ad-empty="1"])::after, 487 html[data-pollsmax-theme="light"] body.pollsmax-home-page #pollsmaxPageTopAdDesktop[data-ad-state="filled"]::after, 488 html[data-theme="light"] body.pollsmax-home-page #pollsmaxPageTopAdDesktop:is([data-ad-state="filled"], [data-ad-state="live"]):not([data-pollsmax-ad-empty="1"])::after, 489 html[data-theme="light"] body.pollsmax-home-page #pollsmaxPageTopAdDesktop[data-ad-state="filled"]::after { 490 background: #cbd5e1 !important; 491 } 492 493 html[data-pollsmax-theme="light"] body.pollsmax-home-page .home-intro, 494 html[data-theme="light"] body.pollsmax-home-page .home-intro { 495 border-bottom-color: #cbd5e1; 496 } 497 } 498 499 /* PC: one hairline between stacked home blocks (previous border-b wins). */ 500 @media (min-width: 768px) { 501 body.pollsmax-home-page main .sleek-maps--home-senate-house + .sleek-maps--home-gov-donate { 502 border-top: none !important; 503 border-top-width: 0 !important; 504 } 505 body.pollsmax-home-page main .sleek-maps--home-gov-donate + #homeUpcomingElectionsSection, 506 body.pollsmax-home-page #homeUpcomingElectionsSection { 507 border-top: none !important; 508 border-top-width: 0 !important; 509 } 510 body.pollsmax-home-page #homeKeyRacesSection + .sleek-maps--home-primaries, 511 body.pollsmax-home-page main .sleek-maps--home-primaries { 512 border-top: none !important; 513 border-top-width: 0 !important; 514 } 515 } 516
517 body.sleek-home h1, 518 body.sleek-home h2, 519 body.sleek-home h3, 520 body.sleek-home h4 { 521 font-family: "Plus Jakarta Sans", "DM Sans", ui-sans-serif, system-ui, sans-serif; 522 } 523 524 body.sleek-home #mainHeader { 525 position: relative; 526 z-index: 50; 527 background: rgba(5, 6, 8, 0.92); 528 backdrop-filter: blur(16px); 529 -webkit-backdrop-filter: blur(16px); 530 border-bottom: 1px solid rgba(51, 65, 85, 0.45); 531 overflow: visible; 532 /* Match shared.js chrome vars so first paint doesn't snap later */ 533 --et-hdr-logo-h: 48px; 534 --et-hdr-logo-scale: 1.08; 535 --et-hdr-nav-fs: 15px; 536 --et-hdr-link-py: 4px; 537 --et-hdr-row-py: 2px; 538 --et-hdr-gap: 1rem; 539 --et-hdr-nav-gap: 1rem; 540 --et-hdr-chev: 15px; 541 --et-hdr-x: 15px; 542 } 543 544 @media (min-width: 1024px) { 545 body.sleek-home #mainHeader { 546 --et-hdr-logo-h: 56px; 547 --et-hdr-logo-scale: 1.12; 548 --et-hdr-nav-fs: 16px; 549 --et-hdr-gap: 1.25rem; 550 --et-hdr-nav-gap: 1.15rem; 551 --et-hdr-chev: 16px; 552 --et-hdr-x: 16px; 553 } 554 } 555 556 @media (min-width: 768px) { 557 html body.pollsmax-home-page.sleek-home #mainHeader { 558 background: rgba(5, 6, 8, 0.92) !important; 559 backdrop-filter: blur(16px) !important; 560 -webkit-backdrop-filter: blur(16px) !important; 561 border-bottom: 1px solid rgba(51, 65, 85, 0.45) !important; 562 } 563 html body.pollsmax-home-page.sleek-home #site-primary-nav.sleek-sitelinks-strip, 564 html body.pollsmax-home-page.sleek-home nav.sleek-sitelinks-strip { 565 background: transparent !important; 566 border-top: none !important; 567 border-bottom: 1px solid rgba(51, 65, 85, 0.45) !important; 568 } 569 html body.pollsmax-home-page.sleek-home footer[data-et-site-footer="1"] { 570 background: #0a0c10 !important; 571 border-top: none !important; 572 } 573 574 /* Content blocks match the header. Do not paint ads, header, or footer. */ 575 html:has(body.pollsmax-home-page.sleek-home), 576 html:has(body.pollsmax-home-page.sleek-home) body.pollsmax-home-page.sleek-home { 577 background-color: #050608 !important; 578 } 579 html body.pollsmax-home-page.sleek-home main.mv-content, 580 html body.pollsmax-home-page.sleek-home .home-intro, 581 html body.pollsmax-home-page.sleek-home .sleek-maps, 582 html body.pollsmax-home-page.sleek-home .sleek-map-pane, 583 html body.pollsmax-home-page.sleek-home .home-donate-pane, 584 html body.pollsmax-home-page.sleek-home #homeUpcomingElectionsSection, 585 html body.pollsmax-home-page.sleek-home #searchAllPollsSection, 586 html body.pollsmax-home-page.sleek-home #homeKeyRacesSection, 587 html body.pollsmax-home-page.sleek-home main > .border-b:has(> .home-key-races-grid), 588 html body.pollsmax-home-page.sleek-home .home-key-races-col, 589 html body.pollsmax-home-page.sleek-home .sleek-chart-stage { 590 background-color: #050608 !important; 591 } 592 html body.pollsmax-home-page.sleek-home .pm-tx-ad-band.pm-tx-ad-band--desktop, 593 html body.pollsmax-home-page.sleek-home .pm-tx-ad-band[data-pm-home-place] { 594 background: #0b0e13 !important; 595 } 596 } 597 598 @media (max-width: 767px) { 599 body.sleek-home #mainHeader { 600 --et-hdr-logo-h: 52px; 601 --et-hdr-logo-scale: 1.58; 602 --et-hdr-logo-crop-y: 1%; 603 --et-hdr-logo-visible-y: 0.98; 604 } 605 } 606 607 /* Same logo transform as pollsmax-responsive-unified.css / shared.js */ 608 body.sleek-home .sleek-home-header-logo { 609 height: var(--et-hdr-logo-h) !important; 610 max-height: var(--et-hdr-logo-h); 611 width: auto !important; 612 transform: scale(var(--et-hdr-logo-scale)) translateY(1px); 613 transform-origin: left center; 614 } 615 616 @media (max-width: 767px) {
617 body.sleek-home #mainHeader .sleek-home-header-logo { 618 -webkit-clip-path: inset(var(--et-hdr-logo-crop-y) 0 var(--et-hdr-logo-crop-y) 0); 619 clip-path: inset(var(--et-hdr-logo-crop-y) 0 var(--et-hdr-logo-crop-y) 0); 620 transform: scale(calc(1 / var(--et-hdr-logo-visible-y) * var(--et-hdr-logo-scale))) translateY(1px); 621 transform-origin: center center; 622 } 623 624 #site-primary-nav, 625 nav.sleek-sitelinks-strip, 626 .sleek-sitelinks-strip.flex { 627 display: none !important; 628 } 629 } 630 631 body.sleek-home .sleek-eyebrow { 632 font-size: 0.65rem; 633 font-weight: 600; 634 letter-spacing: 0.14em; 635 text-transform: uppercase; 636 color: #64748b; 637 margin-bottom: calc(0.375rem + 5px) !important; 638 } 639 640 /* No CSS grid behind canvas â Chart.js y-axis grid aligns with % ticks after ET.snapAxisToStep */ 641 body.sleek-home .sleek-chart-stage { 642 position: relative; 643 background-color: var(--color-chart-bg, #050608); 644 border: 1px solid var(--color-border-strong, rgba(51, 65, 85, 0.5)); 645 border-radius: 0; 646 padding: 0.5rem 0.65rem; 647 overflow: visible; 648 } 649 650 /* Trump / Generic ballot / 2028 primary: flush line charts â light mode uses pale chart stage */ 651 body.sleek-home .sleek-chart-stage:has(#trumpHomeApprovalChart), 652 body.sleek-home .sleek-chart-stage:has(#gbHomeBallotChart), 653 body.sleek-home .sleek-chart-stage:has(#demHomePrimaryChart), 654 body.sleek-home .sleek-chart-stage:has(#gopHomePrimaryChart) { 655 background-color: transparent; 656 border: none; 657 padding: 0.5rem 0; 658 } 659 660 html[data-theme="light"] body.sleek-home .sleek-chart-stage:has(#trumpHomeApprovalChart), 661 html[data-theme="light"] body.sleek-home .sleek-chart-stage:has(#gbHomeBallotChart), 662 html[data-theme="light"] body.sleek-home .sleek-chart-stage:has(#demHomePrimaryChart), 663 html[data-theme="light"] body.sleek-home .sleek-chart-stage:has(#gopHomePrimaryChart), 664 html[data-pollsmax-theme="light"] body.sleek-home .sleek-chart-stage:has(#trumpHomeApprovalChart), 665 html[data-pollsmax-theme="light"] body.sleek-home .sleek-chart-stage:has(#gbHomeBallotChart), 666 html[data-pollsmax-theme="light"] body.sleek-home .sleek-chart-stage:has(#demHomePrimaryChart), 667 html[data-pollsmax-theme="light"] body.sleek-home .sleek-chart-stage:has(#gopHomePrimaryChart) { 668 background-color: var(--color-surface-1, #ffffff) !important; 669 border: 1px solid var(--color-border-default, rgba(15, 23, 42, 0.15)) !important; 670 padding: 0.5rem 0.65rem !important; 671 box-shadow: var(--shadow-small); 672 } 673 674 /* Floating hover header: no panel â date + chip only (styles also set in JS). */ 675 body.sleek-home .sleek-chart-stage .sleek-hover-header { 676 background: transparent !important; 677 border: none !important; 678 box-shadow: none !important; 679 } 680 681 body.sleek-home .sleek-chart-stage canvas { 682 display: block; 683 } 684 685 body.sleek-home .sleek-poll-sidebar { 686 background: #050608; 687 border: 1px solid rgba(51, 65, 85, 0.5); 688 border-radius: 0; 689 } 690 691 body.sleek-home .sleek-poll-sidebar-head { 692 background: #050608; 693 border-bottom: none; 694 } 695 696 /* Search All Polls â All polls panel: header + rows #050608, lines #11161e */ 697 body.sleek-home #searchAllPollsSection .sleek-poll-sidebar { 698 background: #050608; 699 border: 1px solid #11161e; 700 } 701 702 body.sleek-home #searchAllPollsSection .sleek-poll-sidebar-head { 703 background: #050608; 704 border-bottom: 1px solid #11161e; 705 } 706 707 body.sleek-home #searchAllPollsSection .sleek-poll-list { 708 background: #050608; 709 } 710
711 body.sleek-home #searchAllPollsSection .sleek-poll-list > li, 712 body.sleek-home #searchAllPollsSection .sleek-poll-list > div { 713 border-bottom: 1px solid #11161e; 714 } 715 716 body.sleek-home #searchAllPollsSection .sleek-poll-list > li:last-child, 717 body.sleek-home #searchAllPollsSection .sleek-poll-list > div:last-child { 718 border-bottom: none; 719 } 720 721 body.sleek-home .sleek-poll-list>li, 722 body.sleek-home .sleek-poll-list>div { 723 border-bottom: 1px solid rgba(51, 65, 85, 0.35); 724 } 725 726 body.sleek-home .sleek-poll-list>li:last-child, 727 body.sleek-home .sleek-poll-list>div:last-child { 728 border-bottom: none; 729 } 730 731 body.sleek-home .sleek-poll-list>li { 732 padding: 0.76rem 0.75rem; 733 border-radius: 0 !important; 734 background: transparent !important; 735 margin-bottom: 0 !important; 736 transition: background 0.12s ease; 737 } 738 739 body.sleek-home #searchAllPollsSection .sleek-poll-list > li { 740 padding-top: calc(0.76rem - 0.5px); 741 padding-bottom: calc(0.76rem - 0.5px); 742 background: #050608 !important; 743 margin-bottom: 0 !important; 744 } 745 746 /* Desktop: the All Polls panel matches the Senate hub's â header band a step 747 lighter than the rows, slate separators â instead of the flat near-black 748 the surrounding home-page content blocks use. Mobile keeps the flat look. */ 749 @media (min-width: 768px) { 750 body.sleek-home #searchAllPollsSection .sleek-poll-sidebar { 751 background: #0a0c10; 752 border: 1px solid rgba(51, 65, 85, 0.5); 753 } 754 755 body.sleek-home #searchAllPollsSection .sleek-poll-sidebar-head { 756 background: #0f1218; 757 border-bottom: none; 758 } 759 760 body.sleek-home #searchAllPollsSection .sleek-poll-list { 761 background: transparent; 762 } 763 764 body.sleek-home #searchAllPollsSection .sleek-poll-list > li, 765 body.sleek-home #searchAllPollsSection .sleek-poll-list > div { 766 background: transparent !important; 767 border-bottom: 1px solid rgba(51, 65, 85, 0.35); 768 } 769 770 body.sleek-home #searchAllPollsSection .sleek-poll-list > li:last-child, 771 body.sleek-home #searchAllPollsSection .sleek-poll-list > div:last-child { 772 border-bottom: none; 773 } 774 } 775 776 body.sleek-home .sleek-poll-list>li:hover { 777 background: rgba(15, 23, 42, 0.35) !important; 778 } 779 780 body.sleek-home .sleek-poll-list .text-slate-400.text-center { 781 padding: 1.75rem 0.75rem; 782 } 783 784 body.sleek-home select.sleek-select { 785 border-radius: 0; 786 cursor: pointer; 787 border-bottom: 1px solid rgba(71, 85, 105, 0.9) !important; 788 border-top: none !important; 789 border-left: none !important; 790 border-right: none !important; 791 background: transparent !important; 792 box-shadow: none !important; 793 } 794 795 body.sleek-home .sleek-band-head { 796 border-bottom: 1px solid rgba(51, 65, 85, 0.45); 797 padding: 1rem 0 0.75rem; 798 } 799 800 body.sleek-home .sleek-race-row { 801 display: flex; 802 flex-wrap: wrap; 803 align-items: center; 804 justify-content: space-between; 805 gap: 0.5rem 1rem; 806 padding: 0.85rem 0; 807 border-bottom: 1px solid rgba(51, 65, 85, 0.35); 808 transition: background 0.12s ease; 809 } 810 811 body.sleek-home .sleek-race-row:last-child { 812 border-bottom: none; 813 } 814 815 body.sleek-home a.sleek-race-row:hover { 816 background: rgba(15, 23, 42, 0.35); 817 opacity: 1 !important; 818 } 819 820 body.sleek-home .sleek-lead { 821 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; 822 font-size: 0.8rem; 823 font-weight: 600; 824 font-variant-numeric: tabular-nums; 825 letter-spacing: -0.02em; 826 padding-left: 0.5rem; 827 border-left: 2px solid; 828 } 829
830 body.sleek-home .key-race-cands>div+div { 831 margin-top: -1px; 832 } 833 834 /* Key races: first candidate line slightly up, second slightly down (JS injects two divs per row). */ 835 body.sleek-home .key-race-cands>div:first-child { 836 position: relative; 837 top: -1px; 838 } 839 840 body.sleek-home .key-race-cands>div:last-child:not(:only-child) { 841 position: relative; 842 top: 1px; 843 } 844 845 /* Layout stays short (12px tall strip); scale draws flag ~same height as key-race chip (14px font + 6px pad) Ã 1.08 */ 846 body.sleek-home .key-race-flag-wrap { 847 display: inline-flex; 848 align-items: center; 849 justify-content: flex-start; 850 flex-shrink: 0; 851 width: 38px; 852 height: 12px; 853 margin-right: 10px; 854 overflow: visible; 855 } 856 857 body.sleek-home .key-race-flag { 858 width: 18px; 859 height: 12px; 860 object-fit: cover; 861 object-position: center; 862 flex-shrink: 0; 863 border-radius: 1px; 864 transform: scale(calc(25 / 12)); 865 transform-origin: left center; 866 } 867 868 body.sleek-home a.sleek-race-row>div:first-of-type span[aria-hidden="true"] { 869 position: relative; 870 left: -2px; 871 } 872 873 /* Search All Polls: tall flag spans eyebrow â state title only; rule + chart spacing stay outside */ 874 body.sleek-home .search-poll-head-wrap { 875 min-width: 0; 876 } 877 878 body.sleek-home .search-poll-head-wrap>.border-b { 879 padding-bottom: calc(1rem - 5px); 880 } 881 882 body.sleek-home .search-poll-head-text-row { 883 display: flex; 884 align-items: flex-start; 885 gap: 1.35rem; 886 min-width: 0; 887 } 888 889 body.sleek-home .search-poll-flag-rail { 890 display: none; 891 flex-shrink: 0; 892 line-height: 0; 893 align-self: flex-start; 894 } 895 896 body.sleek-home .search-poll-flag-rail.is-visible { 897 display: block; 898 } 899 900 /* Height set in JS = top(2026 SENATE) â bottom(state name); width follows image aspect ratio */ 901 body.sleek-home .search-poll-flag-img { 902 display: block; 903 width: auto; 904 height: auto; 905 max-width: none; 906 max-height: calc(var(--search-poll-flag-state-line-px, 28) * 1px + 2rem); 907 border-radius: 6px; 908 } 909 910 body.sleek-home .search-poll-flag-rail.is-party-logo .search-poll-flag-img { 911 width: auto; 912 height: auto; 913 max-width: none; 914 border-radius: 9999px; 915 object-fit: cover; 916 border: 1px solid rgba(51, 65, 85, 0.55); 917 background: #0c0f14; 918 } 919 920 body.sleek-home #searchAllPollsSection .search-poll-eyebrow-2028 { 921 color: #94a3b8 !important; 922 letter-spacing: 0.14em; 923 } 924 925 body.sleek-home .search-poll-2028-cand-grid { 926 display: flex; 927 flex-direction: column; 928 gap: 0.15rem; 929 width: 100%; 930 } 931 932 body.sleek-home .search-poll-2028-cand-row { 933 display: flex; 934 flex-direction: row; 935 flex-wrap: nowrap; 936 justify-content: flex-end; 937 align-items: baseline; 938 column-gap: 0.35rem; 939 width: 100%; 940 max-width: 100%; 941 } 942 943 body.sleek-home #searchAllPollsSection #searchTable > li[data-pm-primary-hub-nav] .search-poll-2028-cand-row { 944 align-items: baseline; 945 } 946 947 body.sleek-home #searchAllPollsSection #searchTable > li[data-pm-primary-hub-nav] .search-poll-2028-cand-grid { 948 font-size: 13px; 949 line-height: 1.15; 950 } 951 952 body.sleek-home .search-poll-2028-cand-name { 953 flex: 1 1 auto; 954 min-width: 0; 955 text-align: right; 956 padding-left: 0; 957 white-space: nowrap; 958 overflow: hidden; 959 text-overflow: ellipsis; 960 } 961
962 body.sleek-home .search-poll-2028-cand-pct { 963 flex: 0 0 2.75rem; 964 text-align: right; 965 font-variant-numeric: tabular-nums; 966 white-space: nowrap; 967 } 968 969 /* Flag height uses --search-poll-flag-state-line-px (base text-xl/2xl line), not scaled state name */ 970 body.sleek-home #searchAllPollsSection { 971 --search-poll-flag-state-line-px: 28; 972 } 973 974 @media (min-width: 640px) { 975 body.sleek-home #searchAllPollsSection { 976 --search-poll-flag-state-line-px: 32; 977 } 978 } 979 980 @media (min-width: 768px) { 981 body.sleek-home #searchAllPollsSection { 982 --search-poll-flag-state-line-px: 38; 983 } 984 } 985 986 /* Search All Polls mobile: 2Ã2 filter grid, compact dropdowns */ 987 @media (max-width: 767px) { 988 /* Stable flag slot (larger size: eyebrow â state line @ 28px, not the old 22/40 shrink). 989 Default HTML ships is-visible + mi.webp so first paint already reserves space. */ 990 body.sleek-home #searchAllPollsSection { 991 --search-poll-flag-state-line-px: 28; 992 } 993 body.sleek-home #searchAllPollsSection .search-poll-flag-rail.is-visible { 994 display: block; 995 /* ~0.9rem eyebrow + mb-1.5 + 28px state line â 2 */ 996 min-height: 52px;
997 margin-top: 1px; 998 } 999 body.sleek-home #searchAllPollsSection .search-poll-flag-img { 1000 height: 52px; 1001 width: auto; 1002 max-height: none; 1003 } 1004 1005 body.sleek-home #searchAllPollsSection .search-all-polls-filters { 1006 display: grid !important; 1007 grid-template-columns: repeat(2, minmax(0, 1fr)); 1008 column-gap: 0.65rem; 1009 row-gap: 0.7rem; 1010 width: 100%; 1011 max-width: 100%; 1012 margin-top: 0.85rem; 1013 } 1014 1015 body.sleek-home #searchAllPollsSection .search-all-polls-filters > div { 1016 display: flex !important; 1017 flex-direction: column !important; 1018 align-items: flex-start !important; 1019 gap: 0.22rem; 1020 min-width: 0; 1021 max-width: 100%; 1022 width: 100%; 1023 } 1024 1025 body.sleek-home #searchAllPollsSection .search-all-polls-filters label { 1026 font-size: 9px; 1027 letter-spacing: 0.07em; 1028 line-height: 1.2; 1029 text-align: left; 1030 align-self: flex-start; 1031 width: 100%; 1032 margin-top: 5px; 1033 } 1034 1035 body.sleek-home #searchAllPollsSection .search-all-polls-filters select.sleek-select { 1036 width: 100%; 1037 min-width: 0 !important; 1038 max-width: 100%; 1039 font-size: 0.875rem; 1040 line-height: 1.35; 1041 padding-top: 0.34rem; 1042 padding-bottom: 0.34rem; 1043 } 1044 1045 /* Last row (Type alone): same half-width cell as the fields above */ 1046 body.sleek-home #searchAllPollsSection .search-all-polls-filters #homeSearchTypeField { 1047 grid-column: 1; 1048 } 1049 1050 body.sleek-home #searchAllPollsSection { 1051 padding-bottom: 0 !important; 1052 } 1053 1054 body.sleek-home #searchAllPollsSection .search-all-polls-filters { 1055 margin-bottom: 0 !important; 1056 } 1057 1058 body.sleek-home #searchAllPollsSection .search-poll-head-wrap { 1059 margin-top: 1.95rem !important; 1060 margin-bottom: 0 !important; 1061 padding-top: 0 !important; 1062 } 1063 1064 body.sleek-home #searchAllPollsSection .search-poll-head-text-row { 1065 align-items: flex-start !important; 1066 } 1067 1068 body.sleek-home #searchAllPollsSection .search-poll-head-text-row > .min-w-0, 1069 body.sleek-home #searchAllPollsSection .search-poll-head-text-row > .search-poll-flag-rail { 1070 align-self: flex-start !important; 1071 } 1072 1073 body.sleek-home #searchAllPollsSection .grid { 1074 display: block !important; 1075 margin-top: 0 !important; 1076 margin-bottom: 0 !important; 1077 padding-top: 0 !important; 1078 padding-bottom: 0 !important; 1079 row-gap: 0 !important; 1080 gap: 0 !important; 1081 } 1082 1083 body.sleek-home #searchAllPollsSection .grid > div:last-child { 1084 display: none !important; 1085 } 1086 1087 body.sleek-home #searchAllPollsSection .sleek-chart-stage--home-search { 1088 height: 227px !important; 1089 min-height: 227px; 1090 /* Race-head rule â chart: 3px tighter than prior (was 3.75rem â 1px). */ 1091 margin-top: calc(3.75rem - 4px) !important; 1092 /* No extra chart margin â panel pad-y alone matches other home cards. */ 1093 margin-bottom: 0 !important; 1094 } 1095 1096 body.sleek-home #searchAllPollsSection .sleek-chart-stage--home-search canvas#searchChart { 1097 display: block; 1098 } 1099 1100 body.sleek-home #searchAllPollsSection .sleek-poll-sidebar { 1101 display: none !important; 1102 } 1103 1104 /* House: District replaces Type in row 2; Type moves below State */
1105 body.sleek-home #searchAllPollsSection .search-all-polls-filters--house #homeSearchTypeField { 1106 grid-column: 1; 1107 grid-row: 3; 1108 } 1109 1110 } 1111 1112 /* Home Search All Polls â House district title styling */ 1113 body.sleek-home #searchAllPollsSection .search-poll-state-heading #entityLink .house-search-district-state { 1114 transition: color 0.2s ease; 1115 } 1116 1117 body.sleek-home #searchAllPollsSection .search-poll-state-heading #entityLink .house-search-district-tail { 1118 color: #cbd5e1; 1119 font-weight: 300; 1120 letter-spacing: -0.02em; 1121 transition: color 0.2s ease; 1122 } 1123 1124 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityLink .house-search-district-state { 1125 color: #94a3b8; 1126 } 1127 1128 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityLink .house-search-district-tail { 1129 color: #475569; 1130 } 1131 1132 @media (min-width: 768px) { 1133 body.sleek-home #searchAllPollsSection .search-all-polls-filters--house #homeSearchTypeField { 1134 grid-column: auto; 1135 grid-row: auto; 1136 } 1137 } 1138 1139 /* Search All Polls desktop spacing tweaks */ 1140 @media (min-width: 768px) { 1141 body.sleek-home #searchAllPollsSection { 1142 padding-bottom: calc(2rem + 10px); 1143 } 1144 1145 /* 1146 * Title â dropdowns: pad the title block (margin-top on filters was a no-op / 1147 * collapsed). +20px from the current PC gap. 1148 */ 1149 body.sleek-home.pollsmax-home-page #searchAllPollsSection > .max-w-4xl { 1150 padding-bottom: 20px !important; 1151 box-sizing: border-box; 1152 } 1153 1154 body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-all-polls-filters { 1155 margin-top: 0.25rem !important; /* keep Tailwind mt-1; do not change above spacing */ 1156 margin-bottom: 40px !important; /* +20px under dropdowns */ 1157 } 1158 1159 body.sleek-home #searchAllPollsSection .search-poll-head-wrap { 1160 margin-top: 30px; 1161 } 1162 1163 body.sleek-home #searchAllPollsSection .grid > div:last-child { 1164 margin-top: 28px !important; 1165 } 1166 } 1167 1168 /* Search All Polls section title â latest polls */ 1169 body.sleek-home #searchAllPollsSection .search-all-polls-title-link { 1170 cursor: pointer; 1171 } 1172 1173 body.sleek-home #searchAllPollsSection .search-all-polls-title-arrow { 1174 /* Size/gap from pm-site-chrome --pm-trailing-arrow-* tokens. */ 1175 transform: none; 1176 transition: color 0.15s ease; 1177 } 1178 1179 body.sleek-home #searchAllPollsSection .search-all-polls-title-link:hover .search-all-polls-title-arrow { 1180 transform: none; 1181 color: #94a3b8; 1182 } 1183 1184 body.sleek-home #searchAllPollsSection .search-all-polls-title-link:hover h2 { 1185 color: #94a3b8; 1186 } 1187 1188 /* 1189 * Home PC: any title/link with a trailing â â label + arrow share one hover gray. 1190 * Beats Tailwind group-hover:text-slate-200 / text-slate-500 mismatches. 1191 */ 1192 @media (min-width: 768px) { 1193 body.sleek-home .sleek-home-forecast-head__link:hover h2, 1194 body.sleek-home .sleek-home-forecast-head__link:hover h2 span, 1195 body.sleek-home a.group:hover > h2, 1196 body.sleek-home a.group:hover > h2 span, 1197 body.sleek-home #searchAllPollsSection .search-all-polls-title-link:hover h2, 1198 body.sleek-home #searchAllPollsSection .search-all-polls-title-link:hover .search-all-polls-title-arrow, 1199 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityLink, 1200 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityArrow, 1201 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityLink .house-search-district-state,
1202 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityLink .house-search-district-tail, 1203 body.sleek-home .home-donate-pane__title-link:hover .home-donate-pane__title, 1204 body.sleek-home .home-donate-pane__title-link:hover .home-donate-pane__title-arrow, 1205 body.sleek-home .home-upcoming-elections__title-link:hover, 1206 body.sleek-home .home-upcoming-elections__title-link:hover .home-upcoming-elections__title-arrow { 1207 color: #94a3b8 !important; 1208 } 1209 } 1210 1211 /* Home: arrow-link rows â label text medium gray on hover (mobile / fallback) */ 1212 body.sleek-home .sleek-home-forecast-head__link:hover h2, 1213 body.sleek-home a.group:hover > h2.text-white, 1214 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityLink { 1215 color: #94a3b8; 1216 } 1217 1218 /* Search All Polls: state name + arrow (flag height uses --search-poll-flag-state-line-px) */ 1219 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.search-poll-state-heading, 1220 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.search-poll-state-heading #entityLink { 1221 position: relative; 1222 font-size: calc(1.25rem * 1.188) !important; 1223 line-height: calc(1.75rem * 1.188) !important; 1224 } 1225 1226 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.search-poll-state-heading { 1227 position: relative !important; 1228 top: -3px !important; /* was -5px; down 2px */ 1229 } 1230 1231 @media (min-width: 640px) { 1232 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.search-poll-state-heading, 1233 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.search-poll-state-heading #entityLink { 1234 font-size: calc(1.5rem * 1.188) !important; 1235 line-height: calc(2rem * 1.188) !important; 1236 } 1237 } 1238 1239 /* PC only: state name right of the flag (!important beats Tailwind sm:text-2xl) */ 1240 @media (min-width: 768px) { 1241 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.search-poll-state-heading, 1242 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.search-poll-state-heading #entityLink { 1243 font-size: 1.95rem !important; 1244 line-height: 2.35rem !important; 1245 } 1246 } 1247 1248 /* Search All Polls: race-type eyebrow (2026 SENATE / GOVERNOR / â¦) slightly larger + nudged */ 1249 body.sleek-home #searchAllPollsSection #trendLabel.sleek-eyebrow { 1250 font-size: 0.98rem !important; 1251 position: relative !important; 1252 top: 4px !important; /* was 5px; up 1px */ 1253 } 1254 1255 body.sleek-home #searchAllPollsSection .search-poll-head-wrap #entityArrow { 1256 transform: none; 1257 transition: color 0.15s ease; 1258 } 1259 1260 body.sleek-home #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityArrow { 1261 transform: none; 1262 color: #94a3b8; 1263 } 1264 1265 /* Search All Polls: match ME senate / national home charts (transparent stage, flush left). 1266 Canvas fills stage so end-dot flush can meet the pinned date/chip right edge. */ 1267 body.sleek-home #searchAllPollsSection .sleek-chart-stage--home-search { 1268 margin-top: calc(3.75rem - 1px); 1269 background-color: transparent; 1270 border: none; 1271 padding: 0.5rem 0; 1272 } 1273 1274 body.sleek-home #searchAllPollsSection .sleek-chart-stage--home-search canvas#searchChart { 1275 display: block; 1276 width: 100% !important; 1277 max-width: 100%; 1278 } 1279 1280 html[data-theme="light"] body.sleek-home #searchAllPollsSection .sleek-chart-stage--home-search, 1281 html[data-pollsmax-theme="light"] body.sleek-home #searchAllPollsSection .sleek-chart-stage--home-search { 1282 background-color: var(--color-chart-bg, #ffffff) !important; 1283 border: 1px solid var(--color-border-default, rgba(15, 23, 42, 0.15)) !important; 1284 padding: 0.5rem 0.65rem !important; 1285 } 1286 1287 /* Search All Polls: All polls list â equal row heights (no extra last-row margin) */
1288 body.sleek-home #searchAllPollsSection #searchTable>li:last-child { 1289 margin-bottom: 0 !important; 1290 } 1291 1292 body.sleek-home .card { 1293 background: transparent; 1294 border: none; 1295 box-shadow: none; 1296 } 1297 1298 body.sleek-home .section-head { 1299 background: transparent; 1300 border-bottom: none; 1301 } 1302 1303 body.sleek-home .border-t.border-slate-700 { 1304 border-color: rgba(51, 65, 85, 0.45) !important; 1305 } 1306 1307 body.sleek-home .pill { 1308 background: transparent; 1309 border: none; 1310 border-bottom: 1px solid rgba(71, 85, 105, 0.8); 1311 border-radius: 0; 1312 box-shadow: none; 1313 } 1314 1315 body.sleek-home a.race-link:hover { 1316 opacity: 1; 1317 } 1318 1319 body.sleek-home .sleek-race-row:hover { 1320 background: rgba(15, 23, 42, 0.38); 1321 } 1322 1323 body.sleek-home a.race-link:hover span.text-lg.font-medium.text-white { 1324 color: #94a3b8; 1325 } 1326 1327 body.sleek-home .quick-link:hover { 1328 box-shadow: none; 1329 } 1330 1331 body.sleek-home .sleek-maps { 1332 gap: 0; 1333 } 1334 1335 /* 1336 * Home mobile forecast maps: spacing must not wait on Tailwind CDN (cold first load on mobile). 1337 */ 1338 @media (max-width: 767px) { 1339 body.pollsmax-home-page { 1340 --et-mob-standard-vertical-gap: 2rem; 1341 --et-mob-channel-pl: max(1rem, env(safe-area-inset-left)); 1342 --et-mob-channel-pr: max(1rem, env(safe-area-inset-right)); 1343 } 1344 1345 body.pollsmax-home-page main { 1346 padding-bottom: 5rem !important; 1347 } 1348 1349 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"] { 1350 padding-left: var(--et-mob-channel-pl) !important; 1351 padding-right: var(--et-mob-channel-pr) !important; 1352 box-sizing: border-box; 1353 } 1354 1355 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"]:first-of-type { 1356 padding-top: var(--et-mob-standard-vertical-gap) !important; 1357 } 1358 1359 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"]:last-of-type { 1360 padding-bottom: 1.5rem !important; 1361 } 1362 1363 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"] > div.block.mb-3.mt-6 { 1364 display: block !important; 1365 margin-top: 1.5rem !important; 1366 margin-bottom: 0.75rem !important; 1367 } 1368 1369 body.pollsmax-home-page .home-forecast-map-stage { 1370 margin-top: 0.5rem !important; 1371 } 1372 1373 /* Match Senate hub Simulated Distribution title rule (mobile). */ 1374 body.pollsmax-home-page .sleek-home-forecast-head { 1375 display: block !important; 1376 position: relative !important;
1377 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 1378 padding-bottom: 0.65rem !important; 1379 margin-bottom: 0.65rem !important; 1380 } 1381 1382 body.pollsmax-home-page .sleek-home-forecast-head__countdown { 1383 display: none !important; 1384 } 1385 1386 body.pollsmax-home-page .home-upcoming-elections__title { 1387 padding-right: 0 !important; 1388 } 1389 1390 body.pollsmax-home-page .sleek-map-pane > div[class*="px-4"] > .sleek-eyebrow { 1391 margin-bottom: calc(0.375rem + 5px) !important; 1392 } 1393 1394 /* Search All Polls â channel padding + section top inset */ 1395 body.pollsmax-home-page #searchAllPollsSection { 1396 padding-left: var(--et-mob-channel-pl) !important; 1397 padding-right: var(--et-mob-channel-pr) !important; 1398 padding-top: calc(var(--et-mob-standard-vertical-gap) - 6px) !important; 1399 box-sizing: border-box; 1400 } 1401 1402 /* Mobile-only: hide Support Pollsmax + Key Races. */ 1403 body.pollsmax-home-page .sleek-map-pane--home-donate, 1404 body.pollsmax-home-page main > .border-b:has(> .home-key-races-grid), 1405 body.pollsmax-home-page #homeKeyRacesSection { 1406 display: none !important; 1407 } 1408 1409 /* PC ad band needs border-t on 2028; drop it on mobile (approval border-b is enough). */ 1410 body.pollsmax-home-page .sleek-maps--home-primaries { 1411 border-top: none !important; 1412 } 1413 1414 /* Mobile-only: channel padding for remaining home ads */ 1415 1416 body.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-link { 1417 display: inline-flex !important; 1418 align-items: center; 1419 } 1420 1421 body.pollsmax-home-page #searchAllPollsSection .search-poll-head-wrap > .border-b { 1422 /* Race-head rule â chart: 12px tighter than gov Democrats gap. */ 1423 margin-bottom: calc(0.65rem - 12px) !important; 1424 } 1425 1426 /* Trump / Generic ballot / 2028 primary chart sections */ 1427 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] { 1428 padding-left: var(--et-mob-channel-pl) !important; 1429 padding-right: var(--et-mob-channel-pr) !important; 1430 padding-top: var(--et-mob-standard-vertical-gap) !important; 1431 padding-bottom: 2.75rem !important; 1432 box-sizing: border-box; 1433 } 1434 1435 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head { 1436 display: block !important;
1437 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 1438 padding-bottom: 0.65rem !important; 1439 margin-bottom: 0.65rem !important; 1440 } 1441 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a { 1442 display: block !important; 1443 text-decoration: none; 1444 color: inherit; 1445 } 1446 1447 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .sleek-eyebrow { 1448 display: block !important; 1449 margin-bottom: calc(0.375rem + 5px) !important; 1450 } 1451 1452 body.pollsmax-home-page .sleek-chart-stage:has(#trumpHomeApprovalChart), 1453 body.pollsmax-home-page .sleek-chart-stage:has(#gbHomeBallotChart), 1454 body.pollsmax-home-page .sleek-chart-stage:has(#demHomePrimaryChart), 1455 body.pollsmax-home-page .sleek-chart-stage:has(#gopHomePrimaryChart) { 1456 margin-top: 3.75rem !important; 1457 margin-left: -6px !important; 1458 width: calc(100% + 5px) !important; 1459 position: relative; 1460 overflow: visible !important; 1461 } 1462 /* Keep chart canvas geometry; exclude hover-chrome overlay canvas. */ 1463 body.pollsmax-home-page .sleek-chart-stage:has(#trumpHomeApprovalChart) > canvas#trumpHomeApprovalChart, 1464 body.pollsmax-home-page .sleek-chart-stage:has(#gbHomeBallotChart) > canvas#gbHomeBallotChart, 1465 body.pollsmax-home-page .sleek-chart-stage:has(#demHomePrimaryChart) > canvas#demHomePrimaryChart, 1466 body.pollsmax-home-page .sleek-chart-stage:has(#gopHomePrimaryChart) > canvas#gopHomePrimaryChart { 1467 margin-left: 2px !important; 1468 width: calc(100% - 2px) !important; 1469 max-width: calc(100% - 2px) !important; 1470 } 1471 1472 /* Key Senate / House / Governor race lists */ 1473 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .home-key-races-grid, 1474 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid.home-key-races-grid { 1475 padding-left: var(--et-mob-channel-pl) !important; 1476 padding-right: var(--et-mob-channel-pr) !important; 1477 box-sizing: border-box; 1478 } 1479 1480 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section.home-key-races-col, 1481 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section[class*="px-4"] { 1482 padding-left: 0 !important; 1483 padding-right: 0 !important; 1484 padding-top: var(--et-mob-standard-vertical-gap) !important; 1485 padding-bottom: var(--et-mob-standard-vertical-gap) !important; 1486 box-sizing: border-box; 1487 } 1488 1489 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section.home-key-races-col > .border-b, 1490 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section[class*="px-4"] > .border-b {
1491 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 1492 padding-bottom: 1rem !important; 1493 margin-bottom: 0.75rem !important; 1494 } 1495 1496 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section.home-key-races-col > .sleek-eyebrow, 1497 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section.home-key-races-col > .border-b > .sleek-eyebrow, 1498 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section[class*="px-4"] > .border-b > .sleek-eyebrow { 1499 display: block !important; 1500 margin-bottom: calc(0.375rem + 5px) !important; 1501 } 1502 1503 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section.home-key-races-col > [class*="mt-6"], 1504 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section[class*="px-4"] > [class*="mt-6"] { 1505 margin-top: 1.5rem !important; 1506 } 1507 1508 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section.home-key-races-col .sleek-home-key-races-sort, 1509 body.pollsmax-home-page main > .border-b.border-slate-800\/80 > .grid > section[class*="px-4"] .sleek-home-key-races-sort { 1510 margin-bottom: 0.5rem !important; 1511 } 1512 1513 body.pollsmax-home-page a.sleek-race-row > div:first-of-type { 1514 display: flex !important; 1515 flex-wrap: wrap; 1516 align-items: center; 1517 min-width: 0; 1518 } 1519 1520 body.pollsmax-home-page a.sleek-race-row .key-race-metrics, 1521 body.pollsmax-home-page a.sleek-race-row .senate-race-metrics { 1522 display: flex !important; 1523 align-items: center; 1524 flex-shrink: 0; 1525 margin-left: auto; 1526 min-width: 0; 1527 } 1528 1529 body.pollsmax-home-page a.sleek-race-row .senate-race-rating-col { 1530 width: var(--hub-aside-margin-col-w, calc(5.5rem - 5px)); 1531 flex-shrink: 0; 1532 display: flex; 1533 justify-content: flex-end; 1534 align-items: center; 1535 } 1536 1537 /* Mobile: hide projected vote (candidate names + %) â keep state + rating chip only */ 1538 body.pollsmax-home-page .key-race-metrics .senate-race-cands-col, 1539 body.pollsmax-home-page .sleek-home-key-races-sort .senate-sort-cands-col { 1540 display: none !important; 1541 } 1542 1543 body.pollsmax-home-page .sleek-home-key-races-sort .senate-races-sort-metrics { 1544 gap: 0; 1545 justify-content: flex-end; 1546 } 1547 1548 body.pollsmax-home-page .key-race-metrics { 1549 justify-content: flex-end; 1550 } 1551 } 1552 1553 /* Seat-bar majority label + pointer (â¼) above Senate / Governor map bars */ 1554 body.sleek-home .sleek-map-pane .sleek-seat-threshold { 1555 top: calc(-1.5rem - 1px); 1556 color: #94a3b8; 1557 } 1558 1559 body.sleek-home .sleek-map-pane .sleek-seat-indicator { 1560 top: calc(-0.5rem - 2px); 1561 width: 0; 1562 height: 0; 1563 border-left: 5px solid transparent; 1564 border-right: 5px solid transparent; 1565 border-top: 7px solid #94a3b8; 1566 } 1567 1568 body.sleek-home #usMap, 1569 body.sleek-home #govMap, 1570 body.sleek-home #houseCdMap { 1571 max-width: none; 1572 display: block; 1573 margin: 0 auto; 1574 width: 100%; 1575 height: auto; 1576 } 1577 1578 body.sleek-home footer { 1579 background: #0a0c10 !important; 1580 border-top: 1px solid rgba(51, 65, 85, 0.45) !important; 1581 backdrop-filter: none; 1582 -webkit-backdrop-filter: none; 1583 } 1584 1585 body.sleek-home .home-footer-states-grid { 1586 display: grid; 1587 grid-template-columns: repeat(4, max-content); 1588 column-gap: 2.75rem; 1589 row-gap: 0.5rem; 1590 justify-items: start; 1591 text-align: left; 1592 } 1593
1594 body.sleek-home .home-footer-states-grid a { 1595 justify-self: start; 1596 } 1597 1598 body.sleek-home .home-footer-cols { 1599 display: grid; 1600 grid-template-columns: 1fr; 1601 row-gap: 2rem; 1602 justify-content: start; 1603 align-items: start; 1604 } 1605 1606 @media (min-width: 640px) { 1607 body.sleek-home .home-footer-cols { 1608 grid-template-columns: max-content max-content; 1609 column-gap: 3.5rem; 1610 row-gap: 2rem; 1611 } 1612 } 1613 1614 @media (min-width: 1280px) { 1615 body.sleek-home .home-footer-cols { 1616 column-gap: 5rem; 1617 } 1618 } 1619 1620 .home-footer-pc-cols, 1621 .home-footer-pc-bottom { 1622 display: none; 1623 } 1624 1625 body.pollsmax-home-page footer[data-et-site-footer="1"] .home-footer-top { 1626 display: flex; 1627 flex-direction: column; 1628 gap: 1.5rem; 1629 } 1630 1631 /* Homepage footer: desktop Dorik-style columns; mobile keeps key races */ 1632 @media (min-width: 1024px) { 1633 body.sleek-home footer[data-et-site-footer="1"] .home-footer-cols, 1634 body.sleek-home footer[data-et-site-footer="1"] .home-footer-mobile-nav, 1635 body.sleek-home footer[data-et-site-footer="1"] .home-footer-brand .site-footer-copyright { 1636 display: none !important; 1637 } 1638 1639 body.sleek-home footer[data-et-site-footer="1"] .home-footer-legal-underline { 1640 display: none !important; 1641 } 1642 1643 body.pollsmax-home-page footer[data-et-site-footer="1"] { 1644 margin-top: 0; 1645 background: #0a0c10 !important; 1646 } 1647 1648 body.pollsmax-home-page footer[data-et-site-footer="1"] .home-footer-inner { 1649 padding-top: 3.25rem; 1650 padding-bottom: 3.75rem !important; 1651 } 1652 1653 body.pollsmax-home-page footer[data-et-site-footer="1"] .home-footer-top { 1654 display: grid !important; 1655 grid-template-columns: max-content minmax(0, 1fr); 1656 grid-template-rows: auto; 1657 align-items: stretch; 1658 gap: 0 2.55rem !important; 1659 min-height: 15rem; 1660 } 1661 1662 body.pollsmax-home-page .home-footer-brand { 1663 grid-column: 1; 1664 grid-row: 1; 1665 display: flex !important; 1666 flex-direction: column !important; 1667 justify-content: space-between; 1668 align-items: flex-start; 1669 align-self: stretch; 1670 width: max-content; 1671 min-width: max-content; 1672 max-width: none; 1673 } 1674 1675 body.pollsmax-home-page .home-footer-brand > a:first-child { 1676 margin-bottom: 0 !important; 1677 display: block; 1678 overflow: hidden; 1679 height: 6.375rem; 1680 line-height: 0; 1681 } 1682 1683 body.pollsmax-home-page .home-footer-brand > a:first-child img { 1684 height: 7.5rem !important; 1685 width: auto; 1686 max-width: none; 1687 display: block; 1688 margin-top: -1.125rem; 1689 } 1690 1691 body.pollsmax-home-page .home-footer-brand-meta { 1692 margin-top: auto !important; 1693 padding-top: 0.85rem; 1694 max-width: none !important; 1695 } 1696 1697 body.pollsmax-home-page .home-footer-brand-meta > * + *, 1698 body.pollsmax-home-page .home-footer-brand-meta.space-y-2 > :not([hidden]) ~ * { 1699 margin-top: 0.18rem !important; 1700 } 1701 1702 body.pollsmax-home-page .home-footer-brand-meta > a { 1703 display: block; 1704 margin-bottom: 0 !important; 1705 } 1706 1707 body.pollsmax-home-page .home-footer-brand .site-footer-tagline { 1708 white-space: nowrap !important; 1709 max-width: none !important; 1710 width: max-content; 1711 margin: 0; 1712 line-height: 1.35; 1713 } 1714 1715 body.pollsmax-home-page .home-footer-brand .site-footer-tagline br { 1716 display: none !important; 1717 } 1718 1719 body.pollsmax-home-page .home-footer-pc-cols { 1720 --home-footer-col-gap: 2.4rem; 1721 grid-column: 2; 1722 grid-row: 1; 1723 display: flex !important; 1724 flex-direction: row !important; 1725 flex-wrap: nowrap; 1726 align-items: flex-start; 1727 align-self: stretch; 1728 justify-content: space-between; 1729 gap: var(--home-footer-col-gap) !important; 1730 width: 100%; 1731 max-width: 100%; 1732 min-width: 0; 1733 margin-left: auto; 1734 padding-top: 0.15rem; 1735 } 1736 1737 body.pollsmax-home-page .home-footer-col { 1738 flex: 0 0 auto; 1739 width: max-content; 1740 min-width: max-content; 1741 max-width: max-content; 1742 } 1743 1744 body.pollsmax-home-page .home-footer-col.home-footer-col--omit { 1745 display: none !important; 1746 } 1747 1748 body.pollsmax-home-page .home-footer-col__title { 1749 margin: 0 0 0.95rem; 1750 font-family: "Plus Jakarta Sans", "DM Sans", ui-sans-serif, system-ui, sans-serif; 1751 font-size: 0.78rem; 1752 font-weight: 700; 1753 letter-spacing: 0.08em; 1754 line-height: 1.25; 1755 color: #f1f5f9; 1756 text-transform: uppercase; 1757 text-decoration: none; 1758 display: block; 1759 white-space: nowrap; 1760 } 1761 1762 body.pollsmax-home-page .home-footer-col__title:hover { 1763 color: #ffffff; 1764 } 1765 1766 body.pollsmax-home-page .home-footer-col__list { 1767 margin: 0; 1768 padding: 0; 1769 list-style: none; 1770 } 1771 1772 body.pollsmax-home-page .home-footer-col__list a { 1773 display: block; 1774 margin: 0 0 0.55rem; 1775 font-size: 0.8125rem; 1776 line-height: 1.35; 1777 color: #94a3b8; 1778 text-decoration: none; 1779 white-space: nowrap; 1780 } 1781 1782 body.pollsmax-home-page .home-footer-col__list a:hover { 1783 color: #ffffff; 1784 } 1785 1786 body.pollsmax-home-page .home-footer-pc-rule { 1787 display: block; 1788 width: 100%; 1789 height: 0; 1790 margin: 1.2rem 0; 1791 border: 0;
1792 border-top: 1px solid rgba(148, 163, 184, 0.22); 1793 } 1794 1795 body.pollsmax-home-page .home-footer-pc-bottom { 1796 display: flex; 1797 align-items: baseline; 1798 justify-content: space-between; 1799 gap: 1.5rem; 1800 } 1801 1802 body.pollsmax-home-page .home-footer-pc-bottom .site-footer-copyright { 1803 margin: 0; 1804 color: #64748b; 1805 font-size: 0.8125rem; 1806 } 1807 1808 body.pollsmax-home-page .home-footer-pc-legal { 1809 display: flex; 1810 flex-wrap: wrap; 1811 justify-content: flex-end; 1812 align-items: baseline; 1813 gap: 0.45rem 1.35rem; 1814 margin: 0; 1815 } 1816 1817 body.pollsmax-home-page .home-footer-pc-legal a { 1818 color: #64748b; 1819 font-size: 0.8125rem; 1820 text-decoration: none; 1821 white-space: nowrap; 1822 } 1823 1824 body.pollsmax-home-page .home-footer-pc-legal a:hover { 1825 color: #ffffff; 1826 } 1827 } 1828 1829 @media (min-width: 1024px) and (max-width: 1279px) { 1830 body.pollsmax-home-page footer[data-et-site-footer="1"] .home-footer-top { 1831 gap: 0 2rem !important; 1832 } 1833 body.pollsmax-home-page .home-footer-pc-cols { 1834 --home-footer-col-gap: 2.35rem; 1835 } 1836 body.pollsmax-home-page .home-footer-col__title { 1837 font-size: 0.7rem; 1838 letter-spacing: 0.06em; 1839 } 1840 } 1841 1842 @media (min-width: 1280px) { 1843 body.pollsmax-home-page footer[data-et-site-footer="1"] .home-footer-top { 1844 gap: 0 2.75rem !important; 1845 } 1846 body.pollsmax-home-page .home-footer-pc-cols { 1847 --home-footer-col-gap: 2.5rem; 1848 } 1849 } 1850 1851 @media (max-width: 1023.98px) { 1852 body.sleek-home footer[data-et-site-footer="1"] .home-footer-legal-underline { 1853 display: none !important; 1854 } 1855 body.pollsmax-home-page .home-footer-pc-rule { 1856 display: none; 1857 } 1858 } 1859 1860 /* Header nav dropdowns â match sleek map/chart shell (flat, hairlines, no pills) */ 1861 body.sleek-home .sleek-nav-dropdown { 1862 list-style: none; 1863 margin: 0; 1864 padding: 0; 1865 box-sizing: border-box; 1866 width: 10rem; 1867 max-width: min(100vw - 1.5rem, 10rem); 1868 background: #0a0c10; 1869 border: 1px solid rgba(51, 65, 85, 0.5); 1870 border-radius: 0; 1871 box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5); 1872 font-size: 0.875rem; 1873 font-weight: 500; 1874 line-height: 1.32; 1875 } 1876 1877 body.sleek-home .sleek-nav-dropdown li { 1878 border-bottom: 1px solid rgba(51, 65, 85, 0.35); 1879 } 1880 1881 body.sleek-home .sleek-nav-dropdown li:last-child { 1882 border-bottom: none; 1883 } 1884 1885 body.sleek-home .sleek-nav-dropdown a { 1886 display: block; 1887 padding: 0.5rem 0.55rem; 1888 color: #e2e8f0; 1889 text-decoration: none; 1890 text-align: left; 1891 transition: background 0.12s ease, color 0.12s ease; 1892 } 1893 1894 body.sleek-home .sleek-nav-dropdown a:hover { 1895 background: rgba(15, 23, 42, 0.5); 1896 color: #f8fafc; 1897 } 1898 1899 body.sleek-home .sleek-nav-dropdown a.sleek-nav-dropdown-lead { 1900 background: var(--pm-nav-dropdown-lead-bg, #181d26); 1901 font-weight: 600; 1902 letter-spacing: 0.01em; 1903 color: #f1f5f9; 1904 } 1905 1906 body.sleek-home .sleek-nav-dropdown a.sleek-nav-dropdown-lead:hover { 1907 background: var(--pm-nav-dropdown-lead-bg-hover, #232c38); 1908 color: #fff; 1909 } 1910 1911 /* Senate + governor race lists: narrower column */ 1912 body.sleek-home .sleek-nav-dropdown--races { 1913 width: 9rem; 1914 max-width: min(100vw - 1.5rem, 9rem); 1915 } 1916 1917 /* 2028 President: fit âDemocratic/Republican Primaryâ without extra width */
1918 body.sleek-home .sleek-nav-dropdown--2028 { 1919 width: max-content; 1920 min-width: 8.5rem; 1921 max-width: min(100vw - 1.5rem, 10.25rem); 1922 } 1923 1924 body.sleek-home .sleek-nav-dropdown--2028 a { 1925 white-space: nowrap; 1926 } 1927 1928 @media (prefers-reduced-motion: reduce) { 1929 1930 body.sleek-home .sleek-race-row, 1931 body.sleek-home .sleek-poll-list>li { 1932 transition: none; 1933 } 1934 1935 body.sleek-home .sleek-nav-dropdown { 1936 transition: opacity 0.12s ease, visibility 0.12s !important; 1937 transform: none !important; 1938 } 1939 } 1940 1941 body.sleek-home .sleek-sitelinks-strip .sleek-sitelinks-item { 1942 font-size: 0.75rem; 1943 line-height: 1.28; 1944 font-weight: 500; 1945 letter-spacing: normal; 1946 white-space: nowrap; 1947 padding-top: 0.125rem; 1948 padding-bottom: 0.125rem; 1949 } 1950 1951 @media (min-width: 640px) { 1952 body.sleek-home .sleek-sitelinks-strip .sleek-sitelinks-item { 1953 font-size: 0.8125rem; 1954 } 1955 } 1956 1957 body.sleek-home .sleek-sitelinks-strip .sleek-sitelinks-item--muted { 1958 color: #64748b; 1959 cursor: default; 1960 user-select: none; 1961 } 1962 1963 body.sleek-home .sleek-sitelinks-strip a.sleek-sitelinks-item { 1964 color: #94a3b8; 1965 transition: color 0.12s ease; 1966 } 1967 1968 body.sleek-home .sleek-sitelinks-strip a.sleek-sitelinks-item:hover { 1969 color: #fff; 1970 } 1971 1972 body.sleek-home .sleek-home-header-updated { 1973 color: #22c55e; 1974 font-size: 0.6875rem; 1975 line-height: 1.28; 1976 margin: 0; 1977 white-space: nowrap; 1978 font-weight: 500; 1979 } 1980 1981 body.sleek-home .sleek-home-header-meta { 1982 align-items: flex-end; 1983 } 1984 1985 @media (min-width: 768px) { 1986 body.sleek-home .sleek-home-header-meta, 1987 body.sleek-home #mainHeader .flex.items-center.justify-between>div:not(:first-child) { 1988 align-items: center; 1989 } 1990 1991 body.sleek-home #mainHeader #homeHeaderLastUpdated { 1992 display: none !important; 1993 } 1994 1995 body.sleek-home .sleek-sitelinks-strip .sleek-home-header-updated, 1996 body.sleek-home .sleek-sitelinks-strip__updated { 1997 margin-left: auto; 1998 text-align: right; 1999 transform: none; 2000 } 2001 } 2002 2003 @media (min-width: 1280px) { 2004 body.sleek-home .sleek-home-header-updated { 2005 font-size: 0.75rem; 2006 } 2007 } 2008 2009 @media (max-width: 767px) { 2010 body.sleek-home .sleek-home-header-updated { 2011 display: none !important; 2012 } 2013 } 2014 </style> 2015 2016 <!-- ===== HOME MOBILE PANEL REDESIGN (mobile â¤767px only; PC unchanged) ===== --> 2017 <style id="pollsmax-home-mobile-panels"> 2018 /* Year prefix ("2026" / "2028") only appears on mobile, where the caps eyebrow is hidden. 2019 One word-gap via padding only (no â that doubled the space). */ 2020 .home-mob-title-year { display: none; } 2021 2022 /* Mobile-only panel blurbs under titles (forecast chance + other home panels) */ 2023 .home-forecast-chance, 2024 .home-panel-blurb { display: none; } 2025 .home-forecast-chance__em, 2026 .home-panel-blurb__em { 2027 font-style: italic; 2028 font-weight: 800; 2029 } 2030 .home-forecast-chance__em--d, 2031 .home-panel-blurb__em--d { color: #0c6df6; } 2032 .home-forecast-chance__em--r, 2033 .home-panel-blurb__em--r { color: #ff4142; } 2034 .home-panel-blurb__em--approve { color: #00e070; } 2035 2036 @media (max-width: 767px) { 2037 body.pollsmax-home-page .home-forecast-chance, 2038 body.pollsmax-home-page .home-panel-blurb, 2039 html.et-mobile-active body.sleek-home.pollsmax-home-page .home-forecast-chance,
2040 html.et-mobile-active body.sleek-home.pollsmax-home-page .home-panel-blurb { 2041 display: block; 2042 /* Match hub Simulated Distribution subtitle (mt-2). */ 2043 margin: 0.5rem 0 0; 2044 padding: 0; 2045 /* Match Senate hub chart panel blurbs under titles (0.8125rem). */ 2046 font-size: 0.8125rem; 2047 line-height: 1.45; 2048 color: #94a3b8; 2049 max-width: 36rem; 2050 } 2051 html[data-theme="light"] body.pollsmax-home-page .home-forecast-chance, 2052 html[data-theme="light"] body.pollsmax-home-page .home-panel-blurb, 2053 html[data-pollsmax-theme="light"] body.pollsmax-home-page .home-forecast-chance, 2054 html[data-pollsmax-theme="light"] body.pollsmax-home-page .home-panel-blurb { 2055 color: #64748b; 2056 } 2057 } 2058 2059 @media (max-width: 767px) { 2060 body.pollsmax-home-page .home-mob-title-year, 2061 html.et-mobile-active body.sleek-home.pollsmax-home-page .home-mob-title-year { 2062 padding-right: 0.25em; /* normal word space */ 2063 } 2064 } 2065 2066 @media (max-width: 767px) { 2067 html[data-theme="light"] body.pollsmax-home-page { 2068 --et-home-panel-bg: #ffffff; 2069 --et-home-panel-border: #b0bbc9; 2070 --color-chart-bg: #ffffff; 2071 --color-section-band: #ffffff; 2072 } 2073 body.pollsmax-home-page { 2074 --et-home-panel-bg: #0d0f14; 2075 --color-chart-bg: #0d0f14; 2076 --color-section-band: #0d0f14; 2077 --et-home-panel-border: rgba(32, 40, 55, 0.95); 2078 --et-home-panel-radius: 14px; 2079 /* Match the hub panels: 0.95rem inner content padding, 30px inner top/bottom, 2080 and the 20px-above + 10px-below vertical rhythm between panels. */ 2081 --et-home-panel-pad-x: 0.95rem; 2082 --et-home-panel-pad-y: 30px; 2083 --et-home-panel-gap-above: 20px; 2084 --et-home-panel-gap-below: 10px; 2085 /* Full panelâpanel gap (ad owns this above and below when filled). */ 2086 --et-home-panel-gap: calc(var(--et-home-panel-gap-above) + var(--et-home-panel-gap-below)); 2087 /* Constant card inset (the standard channel width). Do NOT use --et-mob-channel-pl/pr 2088 here: those chain to --et-mobile-poll-box-left/right, set dynamically by the 2089 poll-box-sync JS, and feed back into a layout loop that collapses the cards in 2090 light mode. */ 2091 --et-home-card-inset-l: max(1rem, env(safe-area-inset-left)); 2092 --et-home-card-inset-r: max(1rem, env(safe-area-inset-right)); 2093 } 2094 2095 /* Show the in-heading year prefix; hide the light-gray caps eyebrow on the 2096 forecast/chart panels (kept on PC). The ONE exception is the Search-All-Polls 2097 preview race eyebrow (#trendLabel "2026 SENATE/GOVERNOR/HOUSE"), which the user 2098 wants to stay as the only light-gray text on mobile â re-shown just below. */ 2099 body.pollsmax-home-page .home-mob-title-year { display: inline; padding-right: 0.25em; } 2100 body.pollsmax-home-page .sleek-eyebrow, 2101 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"] > .sleek-eyebrow, 2102 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .sleek-eyebrow, 2103 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a .sleek-eyebrow { 2104 display: none !important; 2105 } 2106 body.pollsmax-home-page #searchAllPollsSection #trendLabel.sleek-eyebrow { 2107 display: block !important; 2108 } 2109 2110 /* ---- Panel grid + card box-model ---- 2111 The map/search-preview panes hold content with ~0 intrinsic width (SVG at 2112 width:100%, seat bar), so the single-column grid's default `auto` track 2113 shrinks to near-zero as soon as a pane gains a card margin â collapsing the 2114 map to 0px. Force the track to fill the row with minmax(0,1fr) so the pane 2115 always spans the full width and the margin simply insets the card. */ 2116 body.pollsmax-home-page main .sleek-maps { 2117 grid-template-columns: minmax(0, 1fr) !important; 2118 border: 0 !important; 2119 overflow: visible !important; 2120 margin: 0 !important; 2121 } 2122 /* Card: standard channel width (L/R = card inset), hub border/bg/radius, and the 2123 hub 20px-above + 10px-below rhythm (= 30px between consecutive panels). */ 2124 body.pollsmax-home-page main .sleek-maps .sleek-map-pane { 2125 border: 1px solid var(--et-home-panel-border) !important; 2126 border-radius: var(--et-home-panel-radius) !important; 2127 background: var(--et-home-panel-bg) !important; 2128 margin: var(--et-home-panel-gap-above) var(--et-home-card-inset-r) var(--et-home-panel-gap-below) var(--et-home-card-inset-l) !important; 2129 overflow: visible !important; 2130 box-sizing: border-box; 2131 } 2132 /* In-panel horizontal padding for ALL inner content (headers, bars, maps, charts). */ 2133 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"], 2134 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] { 2135 padding-left: var(--et-home-panel-pad-x) !important; 2136 padding-right: var(--et-home-panel-pad-x) !important; 2137 box-sizing: border-box; 2138 } 2139 /* Consistent 30px inner top/bottom padding per panel (hub pad-y). */ 2140 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"]:first-of-type { 2141 padding-top: var(--et-home-panel-pad-y) !important; 2142 } 2143 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"]:last-of-type { 2144 padding-bottom: var(--et-home-panel-pad-y) !important; 2145 } 2146 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] { 2147 padding-top: var(--et-home-panel-pad-y) !important; 2148 padding-bottom: var(--et-home-panel-pad-y) !important; 2149 } 2150 2151 /* Search All Polls + Upcoming Elections: same card + rhythm + inner padding. */ 2152 body.pollsmax-home-page #searchAllPollsSection, 2153 body.pollsmax-home-page #homeUpcomingElectionsSection { 2154 border: 1px solid var(--et-home-panel-border) !important; 2155 border-radius: var(--et-home-panel-radius) !important; 2156 background: var(--et-home-panel-bg) !important; 2157 margin: var(--et-home-panel-gap-above) var(--et-home-card-inset-r) var(--et-home-panel-gap-below) var(--et-home-card-inset-l) !important; 2158 padding: var(--et-home-panel-pad-y) var(--et-home-panel-pad-x) !important; 2159 box-sizing: border-box; 2160 overflow: visible !important; 2161 } 2162 body.pollsmax-home-page main .sleek-maps .sleek-map-pane .
2162sleek-chart-stage, 2163 body.pollsmax-home-page #searchAllPollsSection .sleek-chart-stage--home-search, 2164 body.pollsmax-home-page .sleek-poll-sidebar, 2165 body.pollsmax-home-page .sleek-poll-sidebar-head, 2166 body.pollsmax-home-page #searchAllPollsSection .sleek-poll-sidebar, 2167 body.pollsmax-home-page #searchAllPollsSection .sleek-poll-sidebar-head, 2168 body.pollsmax-home-page #searchAllPollsSection .sleek-poll-list, 2169 body.pollsmax-home-page #searchAllPollsSection .sleek-poll-list > li { 2170 background: var(--et-home-panel-bg, #0d0f14) !important; 2171 background-color: var(--et-home-panel-bg, #0d0f14) !important; 2172 } 2173 body.pollsmax-home-page #searchAllPollsSection .sleek-poll-list > li:hover { 2174 background: rgba(15, 23, 42, 0.35) !important; 2175 } 2176 2177 /* Top panel: match the full between-panel gap (above + below), not just gap-above. */ 2178 body.pollsmax-home-page main .sleek-maps--home-senate-house .sleek-map-pane:first-child { 2179 margin-top: calc(var(--et-home-panel-gap-above) + var(--et-home-panel-gap-below)) !important; 2180 } 2181 body.pollsmax-home-page main .sleek-maps--home-primaries .sleek-map-pane:last-of-type { 2182 margin-bottom: calc(var(--et-home-panel-gap-above) + var(--et-home-panel-gap-below)) !important; 2183 } 2184 2185 /* Mobile mid-ads: panel OUTER width + equal padding gaps (collapse-proof). */ 2186 body.pollsmax-home-page #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]), 2187 body.pollsmax-home-page #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]) { 2188 margin-top: 0 !important; 2189 margin-bottom: 0 !important; 2190 margin-left: var(--et-home-card-inset-l, max(1rem, env(safe-area-inset-left))) !important; 2191 margin-right: var(--et-home-card-inset-r, max(1rem, env(safe-area-inset-right))) !important; 2192 padding-top: var(--pm-mobile-ad-gap, var(--et-home-panel-gap)) !important; 2193 padding-bottom: var(--pm-mobile-ad-gap, var(--et-home-panel-gap)) !important; 2194 display: block !important; 2195 opacity: 1 !important; 2196 visibility: visible !important; 2197 height: auto !important; 2198 max-height: none !important; 2199 overflow: hidden !important; 2200 pointer-events: auto !important; 2201 background: transparent !important; 2202 } 2203 /* Zero facing panel margins so the ad padding alone owns the gap. 2204 * GbâDem uses ~ (not +): #homeKeyRacesSection sits between them (display:none 2205 * still breaks adjacent-sibling + and left Demâs margin-top under the ad). */ 2206 body.pollsmax-home-page #homeUpcomingElectionsSection:has(+ #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])), 2207 body.pollsmax-home-page .sleek-maps--home-gov-donate:has(+ #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-map-pane, 2208 /* Only the last approval pane (GB) faces the ad â not Trump above GB. */ 2209 body.pollsmax-home-page .sleek-maps--home-approval:has(+ #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-map-pane:last-child, 2210 body.pollsmax-home-page .sleek-maps--home-approval:has(~ #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-map-pane:last-child { 2211 margin-bottom: 0 !important; 2212 } 2213 body.pollsmax-home-page #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]) + #searchAllPollsSection, 2214 body.pollsmax-home-page #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]) ~ .sleek-maps--home-primaries > .sleek-map-pane:first-child, 2215 body.pollsmax-home-page:has(#homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-maps--home-primaries > .sleek-map-pane:first-child { 2216 margin-top: 0 !important; 2217 } 2218 2219 /* Uniform header size across all 8 sections (Search All Polls no longer oversized). */ 2220 body.pollsmax-home-page .sleek-home-forecast-head__link h2, 2221 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a h2, 2222 body.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-link h2 { 2223 font-size: 1.25rem !important; 2224 line-height: 1.3 !important; 2225 } 2226 /* Trailing header arrows: shared chrome tokens (proportional em size + gap). */ 2227 body.pollsmax-home-page .sleek-home-forecast-head__link h2 > span:last-child, 2228 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a h2 > span:last-child, 2229 body.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-arrow, 2230 body.pollsmax-home-page #searchAllPollsSection .search-poll-state-heading #entityArrow { 2231 vertical-align: middle !important; 2232 display: inline-flex !important; 2233 align-items: center !important; 2234 transform: none !important; 2235 top: var(--pm-trailing-arrow-nudge-y, 0) !important; 2236 left: 0 !important; 2237 position: relative !important; 2238 } 2239 body.pollsmax-home-page .sleek-home-forecast-head__link:hover h2 > span:last-child, 2240 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a.group:hover h2 > span:last-child, 2241 body.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-link:hover .search-all-polls-title-arrow, 2242 body.pollsmax-home-page #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityArrow { 2243 transform: none !important; 2244 color: #94a3b8 !important; 2245 } 2246 body.pollsmax-home-page .sleek-home-forecast-head__link h2, 2247 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a h2, 2248 body.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-link h2 { 2249 top: 0 !important; 2250 } 2251 2252 /* All home panel title rules: match Senate hub Simulated Distribution (0.65rem). */ 2253 body.pollsmax-home-page .sleek-home-forecast-head, 2254 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head { 2255 display: block !important; 2256 position: relative !important;
2257 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 2258 padding-bottom: 0.65rem !important; 2259 margin-bottom: 0.65rem !important; 2260 } 2261 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#trumpHomeApprovalChart) > .home-panel-head, 2262 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#gbHomeBallotChart) > .home-panel-head, 2263 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#demHomePrimaryChart) > .home-panel-head, 2264 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#gopHomePrimaryChart) > .home-panel-head { 2265 margin-bottom: calc(0.65rem - 19px) !important; 2266 } 2267 body.pollsmax-home-page #homeUpcomingElectionsSection .sleek-home-forecast-head { 2268 margin-bottom: calc(0.65rem + 15px) !important; 2269 } 2270 body.pollsmax-home-page #searchAllPollsSection .max-w-4xl { 2271 display: block !important; 2272 position: relative !important;
2273 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 2274 /* Space above title rule: +3px vs other panel heads. */ 2275 padding-bottom: calc(0.65rem + 3px) !important; 2276 /* Title rule â filters: +8px vs gov Democrats gap. */ 2277 margin-bottom: calc(0.65rem + 8px) !important; 2278 } 2279 body.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a { 2280 display: block !important; 2281 text-decoration: none; 2282 color: inherit; 2283 } 2284 2285 /* Search All Polls: nudge the whole dropdown row up 4px (visual only, no reflow). */ 2286 body.pollsmax-home-page #searchAllPollsSection .search-all-polls-filters { 2287 transform: translateY(-4px); 2288 } 2289 /* Preview flag: keep full eyebrowâstate size (28), not the prior mobile shrink. */ 2290 body.pollsmax-home-page #searchAllPollsSection { 2291 --search-poll-flag-state-line-px: 28; 2292 } 2293 } 2294 </style> 2295 2296 <!-- ===== HOME MOBILE PANEL REDESIGN â AUTHORITATIVE OVERRIDE (mobile â¤767px) ===== 2297 The block above (and forecast-hub-map-ui.css?v=chevron-align-1 + the theme-boot injected 2298 `pollsmax-layout-boot-critical` style, which is inserted as head.firstChild) 2299 both drive the OLD channel/poll-box-sync full-bleed layout with 2300 `html.et-mobile-active body.pollsmax-home-page` (0,2,2) â and id-level rules for 2301 Search All Polls. That out-specifies the redesign and the poll-box-sync JS 2302 mis-measures the channel (e.g. 434px, wider than the viewport) which pushes each 2303 panel into a narrow, right-offset column. 2304 This block wins by using a strictly higher-specificity prefix 2305 (`html.et-mobile-active body.sleek-home.pollsmax-home-page`, 0,3,2) and NEVER 2306 reads the channel vars â panels use fixed insets and full-width content. --> 2307 <style id="pollsmax-home-mobile-panels-authoritative"> 2308 @media (max-width: 767px) { 2309 html.et-mobile-active body.sleek-home.pollsmax-home-page { 2310 --et-home-panel-bg: #0d0f14; 2311 --color-chart-bg: #0d0f14; 2312 --color-section-band: #0d0f14; 2313 --et-home-panel-border: rgba(32, 40, 55, 0.95); 2314 --et-home-panel-radius: 14px; 2315 /* Fixed standard channel inset (matches the Senate hub) â NOT the JS channel vars. */ 2316 --et-home-inset-l: max(1rem, env(safe-area-inset-left)); 2317 --et-home-inset-r: max(1rem, env(safe-area-inset-right)); 2318 --et-home-pad-x: 0.95rem; 2319 --et-home-pad-y: 30px; 2320 --et-home-gap-above: 20px; 2321 --et-home-gap-below: 10px; 2322 --et-home-panel-gap: calc(var(--et-home-gap-above) + var(--et-home-gap-below)); 2323 } 2324 html.et-mobile-active[data-theme="light"] body.sleek-home.pollsmax-home-page, 2325 html.et-mobile-active[data-pollsmax-theme="light"] body.sleek-home.pollsmax-home-page { 2326 --et-home-panel-bg: #ffffff; 2327 --et-home-panel-border: #b0bbc9; 2328 --color-chart-bg: #ffffff; 2329 --color-section-band: #ffffff; 2330 } 2331 2332 /* Single-column grid; drop the full-bleed container border/overflow. 2333 Zero the grid's own horizontal padding so the pane margin alone 2334 provides the standard 16px inset (matches the Senate hub â otherwise 2335 the grid's 16px + pane's 16px doubled it to 32px). */ 2336 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps { 2337 grid-template-columns: minmax(0, 1fr) !important; 2338 border: 0 !important; 2339 overflow: visible !important; 2340 margin: 0 !important; 2341 padding-left: 0 !important; 2342 padding-right: 0 !important; 2343 } 2344 2345 /* Header hamburger flush left; theme toggle is hidden on mobile. 2346 Login / avatar sit on the right (--et-mob-theme-btn-right). */
2347 html.et-mobile-active body.sleek-home.pollsmax-home-page #mainHeader .et-mobile-nav-btn { 2348 left: 0 !important; 2349 } 2350 html.et-mobile-active body.sleek-home.pollsmax-home-page #mainHeader .pollsmax-theme-toggle, 2351 html.et-mobile-active body.sleek-home.pollsmax-home-page #mainHeader #pollsmax-theme-toggle { 2352 display: none !important; 2353 visibility: hidden !important; 2354 pointer-events: none !important; 2355 opacity: 0 !important; 2356 } 2357 html.et-mobile-active body.sleek-home.pollsmax-home-page #mainHeader .pollsmax-header-donate, 2358 html.et-mobile-active body.sleek-home.pollsmax-home-page #mainHeader #pollsmax-header-donate { 2359 right: 0 !important; 2360 } 2361 2362 /* Home mobile: full-width green âlast updatedâ bar under the header. */ 2363 .home-mobile-last-updated-bar { 2364 display: none !important; 2365 } 2366 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeMobileLastUpdatedBar.home-mobile-last-updated-bar { 2367 display: block !important; 2368 box-sizing: border-box; 2369 width: 100%; 2370 margin: 0; 2371 padding: calc(0.42rem + 1px) max(1rem, env(safe-area-inset-right)) calc(0.42rem - 1px) max(1rem, env(safe-area-inset-left)); 2372 background: #16a34a; 2373 color: #ffffff; 2374 font-size: 0.6875rem; 2375 font-weight: 600; 2376 line-height: 1.3; 2377 text-align: center; 2378 border: 0; 2379 border-bottom: 1px solid rgba(5, 46, 22, 0.18); 2380 } 2381 html.et-mobile-active body.sleek-home.pollsmax-home-page.pollsmax-header-hidden #homeMobileLastUpdatedBar { 2382 display: none !important; 2383 } 2384 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeMobileLastUpdatedBar .sleek-home-header-all-toggle { 2385 color: inherit; 2386 font: inherit; 2387 font-weight: inherit; 2388 line-height: inherit; 2389 background: transparent; 2390 border: none; 2391 padding: 0; 2392 margin: 0; 2393 cursor: pointer; 2394 } 2395 2396 /* Each map/forecast/chart pane becomes a rounded card at the standard inset. */ 2397 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane { 2398 border: 1px solid var(--et-home-panel-border) !important; 2399 border-radius: var(--et-home-panel-radius) !important; 2400 background: var(--et-home-panel-bg) !important; 2401 margin: var(--et-home-gap-above) var(--et-home-inset-r) var(--et-home-gap-below) var(--et-home-inset-l) !important; 2402 overflow: visible !important; 2403 box-sizing: border-box; 2404 } 2405 2406 /* In-panel horizontal padding (fixed) â overrides the channel padding. */ 2407 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"], 2408 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] { 2409 padding-left: var(--et-home-pad-x) !important; 2410 padding-right: var(--et-home-pad-x) !important; 2411 box-sizing: border-box; 2412 } 2413 /* Consistent inner top/bottom padding per panel. */ 2414 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"]:first-of-type { 2415 padding-top: var(--et-home-pad-y) !important; 2416 } 2417 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"]:last-of-type { 2418 padding-bottom: var(--et-home-pad-y) !important; 2419 } 2420 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] { 2421 padding-top: var(--et-home-pad-y) !important; 2422 padding-bottom: var(--et-home-pad-y) !important; 2423 } 2424 2425 /* Kill the partial-width / right-offset: force bars/maps full width. */
2426 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .forecast-hub-seat-bar-wrap, 2427 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .home-forecast-map-stage, 2428 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > div[class*="px-4"] > div.block { 2429 width: 100% !important; 2430 max-width: none !important; 2431 margin-left: 0 !important; 2432 margin-right: 0 !important; 2433 } 2434 /* Charts: stage window â6px left, +5px width (1px inset on right vs prior +6). 2435 Trump / Search / 2028 Dem+GOP must match Generic Ballot geometry. */ 2436 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage, 2437 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#trumpHomeApprovalChart), 2438 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#gbHomeBallotChart), 2439 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#demHomePrimaryChart), 2440 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#gopHomePrimaryChart), 2441 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-chart-stage--home-search { 2442 width: calc(100% + 5px) !important; 2443 max-width: none !important; 2444 margin-left: -6px !important; 2445 margin-right: 0 !important; 2446 margin-bottom: 0 !important; 2447 overflow: visible !important; 2448 box-sizing: border-box !important; 2449 padding-left: 0 !important; 2450 padding-right: 0 !important; 2451 background: var(--et-home-panel-bg, #0d0f14) !important; 2452 background-color: var(--et-home-panel-bg, #0d0f14) !important; 2453 } 2454 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#trumpHomeApprovalChart), 2455 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#gbHomeBallotChart), 2456 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#demHomePrimaryChart), 2457 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage:has(#gopHomePrimaryChart), 2458 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-chart-stage--home-search { 2459 /* Match GB: stage pad is vertical only (see base sleek-home chart rule). */ 2460 padding-top: 0.5rem !important; 2461 padding-bottom: 0.5rem !important; 2462 } 2463 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage > canvas#trumpHomeApprovalChart, 2464 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage > canvas#gbHomeBallotChart, 2465 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage > canvas#demHomePrimaryChart, 2466 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-chart-stage > canvas#gopHomePrimaryChart, 2467 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-chart-stage--home-search > canvas#searchChart { 2468 display: block !important; 2469 margin-left: 2px !important; 2470 margin-right: 0 !important; 2471 width: calc(100% - 2px) !important; 2472 max-width: calc(100% - 2px) !important; 2473 box-sizing: border-box !important; 2474 } 2475 /* Light theme Search stage uses 0.65rem side pad on desktop â zero it on mobile to match GB. */ 2476 html.et-mobile-active[data-theme="light"] body.sleek-h
2476ome.pollsmax-home-page #searchAllPollsSection .sleek-chart-stage--home-search, 2477 html.et-mobile-active[data-pollsmax-theme="light"] body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-chart-stage--home-search { 2478 padding-left: 0 !important; 2479 padding-right: 0 !important; 2480 padding-top: 0.5rem !important; 2481 padding-bottom: 0.5rem !important; 2482 } 2483 2484 /* All home panel title rules: match Senate hub Simulated Distribution (mobile). */ 2485 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-home-forecast-head, 2486 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head { 2487 display: block !important; 2488 position: relative !important; 2489 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 2490 padding-bottom: 0.65rem !important; 2491 margin-bottom: 0.65rem !important; 2492 } 2493 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .max-w-4xl { 2494 display: block !important; 2495 position: relative !important;
2496 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 2497 /* Space above title rule: +3px vs other panel heads. */ 2498 padding-bottom: calc(0.65rem + 3px) !important; 2499 /* Title rule â filters: +8px vs gov Democrats gap. */ 2500 margin-bottom: calc(0.65rem + 8px) !important; 2501 } 2502 /* Trump / Generic Ballot / 2028 Dem+GOP: 19px tighter under title rule. */ 2503 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#trumpHomeApprovalChart) > .home-panel-head, 2504 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#gbHomeBallotChart) > .home-panel-head, 2505 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#demHomePrimaryChart) > .home-panel-head, 2506 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section:has(#gopHomePrimaryChart) > .home-panel-head { 2507 margin-bottom: calc(0.65rem - 19px) !important; 2508 } 2509 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-home-forecast-head__countdown { 2510 display: none !important; 2511 } 2512 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a { 2513 display: block !important; 2514 text-decoration: none; 2515 color: inherit; 2516 } 2517 /* Kill the forecast-hub ::after divider that doubles up with the 1px 2518 border-bottom above (rendered ~2px / thick). Keep only the border. */ 2519 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-home-forecast-head::after, 2520 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head::after, 2521 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps section > a.border-b::after, 2522 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps section > .group.border-b::after { 2523 display: none !important; 2524 } 2525 2526 /* Uniform header size + trailing arrow vertically centered with the title. */ 2527 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-home-forecast-head__link h2, 2528 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a h2 { 2529 font-size: 1.25rem !important; 2530 line-height: 1.3 !important; 2531 top: 0 !important; 2532 } 2533 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-home-forecast-head__link h2 > span:last-child, 2534 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a h2 > span:last-child, 2535 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-arrow, 2536 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-state-heading #entityArrow { 2537 vertical-align: middle !important; 2538 display: inline-flex !important; 2539 align-items: center !important; 2540 transform: none !important; 2541 top: var(--pm-trailing-arrow-nudge-y, 0) !important; 2542 left: 0 !important; 2543 position: relative !important; 2544 } 2545 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-home-forecast-head__link:hover h2 > span:last-child, 2546 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane > section[class*="px-4"] > .home-panel-head > a.group:hover h2 > span:last-child, 2547 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-link:hover .search-all-polls-title-arrow,
2548 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityArrow { 2549 transform: none !important; 2550 color: #94a3b8 !important; 2551 } 2552 2553 /* Show the in-title year prefix; hide the caps eyebrow inside the panes. */ 2554 html.et-mobile-active body.sleek-home.pollsmax-home-page .home-mob-title-year { 2555 display: inline !important; 2556 padding-right: 0.25em !important; /* normal word space */ 2557 } 2558 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps .sleek-map-pane .sleek-eyebrow { 2559 display: none !important; 2560 } 2561 2562 /* Top/bottom panels: match the full between-panel gap (above + below). */ 2563 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps--home-senate-house .sleek-map-pane:first-child { 2564 margin-top: calc(var(--et-home-gap-above) + var(--et-home-gap-below)) !important; 2565 } 2566 html.et-mobile-active body.sleek-home.pollsmax-home-page main .sleek-maps--home-primaries .sleek-map-pane:last-of-type { 2567 margin-bottom: calc(var(--et-home-gap-above) + var(--et-home-gap-below)) !important; 2568 } 2569 2570 /* Mid-ads: panel OUTER width + equal padding gaps (collapse-proof). */ 2571 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]), 2572 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]) { 2573 margin-top: 0 !important; 2574 margin-bottom: 0 !important; 2575 margin-left: var(--et-home-inset-l) !important; 2576 margin-right: var(--et-home-inset-r) !important; 2577 padding-top: var(--pm-mobile-ad-gap, var(--et-home-panel-gap)) !important; 2578 padding-bottom: var(--pm-mobile-ad-gap, var(--et-home-panel-gap)) !important; 2579 display: block !important; 2580 opacity: 1 !important; 2581 visibility: visible !important; 2582 height: auto !important; 2583 max-height: none !important; 2584 overflow: hidden !important; 2585 pointer-events: auto !important; 2586 background: transparent !important; 2587 } 2588 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection:has(+ #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])), 2589 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-maps--home-gov-donate:has(+ #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-map-pane, 2590 /* Only GB (last pane) faces the Dem-primary ad â keep TrumpâGB full 30px gap. */ 2591 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-maps--home-approval:has(+ #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-map-pane:last-child, 2592 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-maps--home-approval:has(~ #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-map-pane:last-child { 2593 margin-bottom: 0 !important; 2594 } 2595 /* ~ / :has â Key Races (hidden) sits between the ad and 2028 Dem Primary. */ 2596 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]) + #searchAllPollsSection, 2597 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"]) ~ .sleek-maps--home-primaries > .sleek-map-pane:first-child,
2598 html.et-mobile-active body.sleek-home.pollsmax-home-page:has(#homeAdBetweenGbAndDemPrimary:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) .sleek-maps--home-primaries > .sleek-map-pane:first-child { 2599 margin-top: 0 !important; 2600 } 2601 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-map-pane:has(+ .pm-tx-ad-band--mobile:has([id^="mvp-"], iframe, .mv-ad-box)), 2602 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection:has(+ .pm-tx-ad-band--mobile:has([id^="mvp-"], iframe, .mv-ad-box)) { 2603 margin-bottom: 0 !important; 2604 } 2605 html.et-mobile-active body.sleek-home.pollsmax-home-page .pm-tx-ad-band--mobile:has([id^="mvp-"], iframe, .mv-ad-box) + .sleek-map-pane { 2606 margin-top: 0 !important; 2607 } 2608 2609 /* Search All Polls + Upcoming Elections â same card, fixed inset. */ 2610 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection, 2611 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection { 2612 border: 1px solid var(--et-home-panel-border) !important; 2613 border-radius: var(--et-home-panel-radius) !important; 2614 background: var(--et-home-panel-bg) !important; 2615 margin: var(--et-home-gap-above) var(--et-home-inset-r) var(--et-home-gap-below) var(--et-home-inset-l) !important; 2616 padding: var(--et-home-pad-y) var(--et-home-pad-x) !important; 2617 box-sizing: border-box; 2618 overflow: visible !important; 2619 } 2620 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-poll-sidebar, 2621 html.et-mobile-active body.sleek-home.pollsmax-home-page .sleek-poll-sidebar-head, 2622 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-poll-sidebar, 2623 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-poll-sidebar-head, 2624 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-poll-list, 2625 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-poll-list > li { 2626 background: var(--et-home-panel-bg, #0d0f14) !important; 2627 background-color: var(--et-home-panel-bg, #0d0f14) !important; 2628 } 2629 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-poll-list > li:hover { 2630 background: rgba(15, 23, 42, 0.35) !important; 2631 } 2632 2633 /* Upcoming Elections: no countdown; match other panel title + divider; one-card carousel. */ 2634 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection > .sleek-eyebrow { 2635 display: none !important; 2636 } 2637 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .sleek-home-forecast-head__countdown { 2638 display: none !important; 2639 } 2640 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-elections__title { 2641 font-size: 1.25rem !important; 2642 line-height: 1.3 !important; 2643 padding-right: 0 !important; 2644 top: 0 !important; 2645 } 2646 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-elections__title-arrow { 2647 vertical-align: middle !important; 2648 display: inline-flex !important; 2649 align-items: center !important; 2650 transform: none !important; 2651 top: var(--pm-trailing-arrow-nudge-y, 0) !important; 2652 left: 0 !important; 2653 position: relative !important; 2654 } 2655 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-elections__title-link:hover .home-upcoming-elections__title-arrow { 2656 transform: none !important; 2657 color: #94a3b8 !important; 2658 }
2659 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-carousel { 2660 display: flex !important; 2661 align-items: center; 2662 gap: 0.15rem; 2663 width: 100%; 2664 } 2665 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-carousel__nav { 2666 display: inline-flex !important; 2667 align-items: center; 2668 justify-content: center; 2669 flex: 0 0 auto; 2670 width: 2rem; 2671 height: 2.5rem; 2672 padding: 0; 2673 margin: 0; 2674 border: 0; 2675 background: transparent; 2676 color: #94a3b8; 2677 cursor: pointer; 2678 -webkit-tap-highlight-color: transparent; 2679 } 2680 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-carousel__nav--prev { 2681 transform: translateX(-3px); 2682 } 2683 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-carousel__nav--next { 2684 transform: translateX(3px); 2685 } 2686 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-carousel__nav:disabled { 2687 opacity: 0.28; 2688 cursor: default; 2689 } 2690 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-carousel__nav svg { 2691 width: 1.15rem; 2692 height: 1.15rem; 2693 display: block; 2694 } 2695 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-scroll { 2696 display: block !important; 2697 flex: 1 1 auto; 2698 min-width: 0; 2699 /* Must not clip the card/bars â item can be slightly wider than the slot. */ 2700 overflow: visible !important; 2701 margin: 0 !important; 2702 padding: 0 !important; 2703 scroll-snap-type: none !important; 2704 } 2705 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item { 2706 display: none !important; 2707 /* 10px wider than the scroll slot (was +6; +4 more), centered between the arrows. */ 2708 width: calc(100% + 10px) !important; 2709 max-width: none !important; 2710 margin-left: -5px !important; 2711 margin-right: -5px !important; 2712 flex: none !important; 2713 box-sizing: border-box !important; 2714 } 2715 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item.is-active { 2716 display: flex !important; 2717 } 2718 /* 2719 * Upcoming Elections card chrome (mobile): 2720 * - Date strip: site page bg + rounded corners (own drop). 2721 * - Body card: no outline, rounded corners. 2722 * - Bars inset on the right so name/% arenât clipped by the card edge. 2723 * - Between-panel gap: block siblings collapse margins, so use the full 2724 * above+below gap on margin-bottom (same 30px as grid map panes). 2725 */ 2726 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection { 2727 margin-bottom: calc(var(--et-home-gap-above) + var(--et-home-gap-below)) !important; 2728 padding-bottom: var(--et-home-pad-y) !important; 2729 overflow: visible !important; 2730 } 2731 /* When a filled mid-ad follows, the ad owns the gap (not Upcomingâs mb). */ 2732 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection:has(+ #homeAdBetweenGovAndSearch:is([data-ad-state="filled"], [data-ad-state="live"], [data-pollsmax-ad-mock="1"])) { 2733 margin-bottom: 0 !important; 2734 }
2735 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection { 2736 /* Gap fully owned by Upcomingâs margin-bottom (or mid-ad below Upcoming). */ 2737 margin-top: 0 !important; 2738 } 2739 /* Title rule â date strip: gov 0.65rem + 15px. */ 2740 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .sleek-home-forecast-head { 2741 margin-bottom: calc(0.65rem + 15px) !important; 2742 } 2743 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date { 2744 border: none !important; 2745 box-shadow: none !important; 2746 /* PC chip-style proportional radius (small strip â 6px, not card-scale cqi). */ 2747 border-radius: 6px !important; 2748 color: #fff !important; 2749 margin-bottom: 6px !important; 2750 /* Same underbar recipe as .eh-tip-bar-track (tint over slate base). */ 2751 --upcoming-date-tint: rgba(135, 149, 166, 0.14); 2752 background: 2753 linear-gradient(var(--upcoming-date-tint), var(--upcoming-date-tint)), 2754 rgba(15, 23, 42, 0.5) !important; 2755 } 2756 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--d { 2757 --upcoming-date-tint: rgba(12, 109, 246, 0.14); 2758 } 2759 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--r { 2760 --upcoming-date-tint: rgba(244, 39, 38, 0.14); 2761 } 2762 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--open { 2763 --upcoming-date-tint: rgba(135, 149, 166, 0.14); 2764 } 2765 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__card { 2766 background: var(--et-home-panel-bg, #0d0f14) !important; 2767 border: none !important; 2768 box-shadow: none !important; 2769 border-radius: clamp(0.5rem, 6cqi, 1.25rem) !important; 2770 padding: 0.75rem 0.8rem 0.7rem !important; 2771 overflow: visible !important; 2772 } 2773 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item:hover:not(.home-upcoming-item--no-polls) .home-upcoming-item__date { 2774 border: none !important; 2775 box-shadow: none !important; 2776 color: #fff !important; 2777 background: 2778 linear-gradient(var(--upcoming-date-tint), var(--upcoming-date-tint)), 2779 rgba(15, 23, 42, 0.5) !important; 2780 } 2781 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item:hover:not(.home-upcoming-item--no-polls) .home-upcoming-item__card { 2782 background: var(--et-home-panel-bg, #0d0f14) !important; 2783 border: none !important; 2784 box-shadow: none !important; 2785 } 2786 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve, 2787 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve:hover { 2788 box-shadow: none !important; 2789 } 2790 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve .home-upcoming-item__date, 2791 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve .home-upcoming-item__card, 2792 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve:hover .home-upcoming-item__date, 2793 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve:hover .home-upcoming-item__card,
2794 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve:hover:not(.home-upcoming-item--no-polls) .home-upcoming-item__date, 2795 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--eve:hover:not(.home-upcoming-item--no-polls) .home-upcoming-item__card { 2796 border: none !important; 2797 border-color: transparent !important; 2798 box-shadow: none !important; 2799 } 2800 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__avg, 2801 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands { 2802 overflow: visible !important; 2803 } 2804 /* Polling Average + bars share one inset (no double pad on cands). */ 2805 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__avg { 2806 display: block !important; 2807 width: 100% !important; 2808 text-align: left !important; 2809 padding-left: 6px !important; 2810 padding-right: 6px !important; 2811 box-sizing: border-box !important; 2812 } 2813 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__avg-label { 2814 text-align: left !important; 2815 width: 100% !important; 2816 } 2817 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands { 2818 display: block !important; 2819 width: 100% !important; 2820 padding-left: 0 !important; 2821 padding-right: 0 !important; 2822 box-sizing: border-box !important; 2823 min-width: 0 !important; 2824 } 2825 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands-empty { 2826 text-align: left !important; 2827 width: 100% !important; 2828 } 2829 /* "No polls yet": keep centered (override left-align / block display above). */ 2830 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--no-polls .home-upcoming-item__avg { 2831 display: flex !important; 2832 align-items: center !important; 2833 justify-content: center !important; 2834 text-align: center !important; 2835 } 2836 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--no-polls .home-upcoming-item__cands { 2837 display: flex !important; 2838 align-items: center !important; 2839 justify-content: center !important; 2840 } 2841 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item--no-polls .home-upcoming-item__cands-empty { 2842 text-align: center !important; 2843 width: auto !important; 2844 } 2845 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands .eh-tip-bars { 2846 width: 100% !important; 2847 max-width: 100% !important; 2848 min-width: 0 !important; 2849 margin-left: 0 !important; 2850 margin-right: 0 !important; 2851 box-sizing: border-box !important; 2852 overflow: visible !important; 2853 } 2854 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands .eh-tip-bar-track, 2855 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands .eh-tip-bar-row { 2856 max-width: 100% !important; 2857 width: 100% !important; 2858 box-sizing: border-box !important; 2859 min-width: 0 !important; 2860 }
2861 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands .eh-tip-bar-track { 2862 border-radius: 6px !important; 2863 overflow: hidden !important; 2864 background-clip: padding-box !important; 2865 } 2866 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands .eh-tip-bar-fill { 2867 border-radius: 6px !important; 2868 } 2869 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands .eh-tip-bar-labels { 2870 padding-right: 0.65rem !important; 2871 } 2872 html.et-mobile-active body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__cands .eh-tip-bar-pct { 2873 padding-right: 0 !important; 2874 } 2875 html.et-mobile-active[data-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date, 2876 html.et-mobile-active[data-pollsmax-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date { 2877 border: none !important; 2878 box-shadow: none !important; 2879 border-radius: 6px !important; 2880 color: #fff !important; 2881 margin-bottom: 6px !important; 2882 /* Light bars use stronger tint alpha (0.14 * 1.6) over light track base. */ 2883 --upcoming-date-tint: rgba(135, 149, 166, 0.224); 2884 background: 2885 linear-gradient(var(--upcoming-date-tint), var(--upcoming-date-tint)), 2886 var(--pm-light-bar-track-bg, var(--pm-light-chart-bg, #fdfdfd)) !important; 2887 } 2888 html.et-mobile-active[data-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--d, 2889 html.et-mobile-active[data-pollsmax-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--d { 2890 --upcoming-date-tint: rgba(12, 109, 246, 0.224); 2891 } 2892 html.et-mobile-active[data-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--r, 2893 html.et-mobile-active[data-pollsmax-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--r { 2894 --upcoming-date-tint: rgba(244, 39, 38, 0.224); 2895 } 2896 html.et-mobile-active[data-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--open, 2897 html.et-mobile-active[data-pollsmax-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__date--open { 2898 --upcoming-date-tint: rgba(135, 149, 166, 0.224); 2899 } 2900 html.et-mobile-active[data-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__card, 2901 html.et-mobile-active[data-pollsmax-theme="light"] body.sleek-home.pollsmax-home-page #homeUpcomingElectionsSection .home-upcoming-item__card { 2902 background: var(--et-home-panel-bg, #ffffff) !important; 2903 border: none !important; 2904 box-shadow: none !important; 2905 border-radius: clamp(0.5rem, 6cqi, 1.25rem) !important; 2906 } 2907 /* Search title divider: +3px above the rule; +8px below gov Democrats gap. */ 2908 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .max-w-4xl {
2909 border-bottom: 1px solid rgba(30, 41, 59, 0.8) !important; 2910 padding-bottom: calc(0.65rem + 3px) !important; 2911 margin-bottom: calc(0.65rem + 8px) !important; 2912 } 2913 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-all-polls-title-link h2 { 2914 font-size: 1.25rem !important; 2915 line-height: 1.3 !important; 2916 } 2917 /* Nudge the whole dropdown row up 4px (visual only). */ 2918 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-all-polls-filters { 2919 transform: translateY(-4px); 2920 } 2921 /* Caps Year/Race/State/District/Type labels: down 4px only (selects stay put). */ 2922 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-all-polls-filters label { 2923 position: relative !important; 2924 top: 6px !important; 2925 } 2926 /* Preview flag: full eyebrowâstate size; keep the "2026 SENATE/GOVERNOR" eyebrow. */ 2927 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection { 2928 --search-poll-flag-state-line-px: 28; 2929 } 2930 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection #trendLabel.sleek-eyebrow { 2931 display: block !important; 2932 position: relative !important; 2933 /* Cancel desktop top:4px (that was pushing it down); 3px left with state title. */ 2934 top: 0 !important; 2935 transform: translateX(-3px) !important; 2936 } 2937 /* Michigan (or state) name + â arrow: up 12px, 3px left (with eyebrow). */ 2938 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-state-heading { 2939 position: relative !important; 2940 top: 0 !important; 2941 transform: translate(-3px, -12px) !important; 2942 } 2943 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-state-heading #entityLink { 2944 position: relative !important; 2945 top: 0 !important; 2946 transform: none !important; 2947 } 2948 /* Arrow keeps +2px right / -2px up relative to the heading (heading already lifts both). */ 2949 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-state-heading #entityArrow { 2950 transform: none !important; 2951 } 2952 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-head-wrap h3.group:hover #entityArrow { 2953 transform: none !important; 2954 color: #94a3b8 !important; 2955 } 2956 /* Search preview head full width; chart is 3px wider (see chart rule above). 2957 Nudge flag + year/race + state + arrow down 11px (visual only) so the gap 2958 to the horizontal rule under them shrinks without moving the rule/chart. */ 2959 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-head-text-row { 2960 max-width: none !important; 2961 width: 100% !important; 2962 transform: translateY(11px); 2963 } 2964 /* Race-head rule â chart: 12px tighter than gov Democrats gap. 2965 Chart margin-top (below) is the visible air under the flag rule. */ 2966 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .search-poll-head-wrap > .border-b { 2967 margin-bottom: calc(0.65rem - 12px) !important; 2968 } 2969 html.et-mobile-active body.sleek-home.pollsmax-home-page #searchAllPollsSection .sleek-chart-stage--home-search { 2970 margin-top: calc(3.75rem - 4px) !important; 2971 } 2972 } 2973 </style> 2974 <!-- Vercel insights: injected after load in home-lazy-boot to free first paint --> 2975
2975<script type="text/javascript" async="async" data-noptimize="1" data-cfasync="false" src="//scripts.mediavine.com/tags/177f11e0-5cb3-48de-bfea-0a340210da36.js"></script>
2975 2976</head> 2977 2978<body class="sleek-home pollsmax-home-page" data-pm-no-page-top="1" data-pm-no-multiplex="1"> 2979
2979<script> 2980 (function () { 2981 try { 2982 if (document.documentElement.classList.contains("et-mobile-active")) { 2983 document.body.classList.add("et-mobile-active"); 2984 } 2985 } catch (e) { /* ignore */ } 2986 })(); 2987 </script>
2987 2988 <!-- Header --> 2989 <header id="mainHeader" class="relative z-50 transition-all duration-300 ease-out"> 2990 <div class="w-full px-4 sm:px-6 lg:px-10 xl:px-14"> 2991 <div class="flex items-center justify-between gap-4 sm:gap-6 py-0.5 relative"> 2992<!-- Logo + main nav (left-aligned, not page-centered) --> 2993 <div class="flex items-center gap-4 sm:gap-6 md:gap-8 min-w-0"> 2994 <button type="button" class="et-mobile-nav-btn" aria-label="Open site menu" aria-expanded="false" aria-controls="et-mobile-nav-drawer"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16" stroke-linecap="butt" stroke-linejoin="miter" /></svg></button> 2995 <a href="/" class="flex items-center shrink-0"> 2996 <img src="/images/logo.webp" alt="POLLSMAX" 2997 class="sleek-home-header-logo h-[48px] sm:h-[52px] md:h-[56px] w-auto block" /> 2998 </a> 2999 3000 <nav class="flex items-center gap-4 sm:gap-5 md:gap-6 shrink-0 ml-2 sm:ml-4 md:ml-6 et-header-nav--desktop" 3001 style="font-size:16px!important; line-height:1.28!important;"> 3002 3003 <!-- 2026 Senate --> 3004 <div class="relative group"> 3005 <a href="/senate/" 3006 class="inline-flex items-center gap-2 px-1 py-1 text-slate-200 hover:text-white"> 3007 2026 Senate 3008 <svg width="16" height="16" viewBox="0 0 20 20" fill="currentColor" 3009 class="text-slate-500 opacity-90 transition-transform duration-200 ease-out group-hover:text-slate-300 group-hover:rotate-180"> 3010 <path 3011 d="M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.71a.75.75 0 011.08 1.04l-4.25 4.25a.75.75 0 01-1.06 0L5.21 8.27a.75.75 0 01.02-1.06z" /> 3012 </svg> 3013 </a> 3014 <ul class="sleek-nav-dropdown sleek-nav-dropdown--races absolute top-full left-0 z-50 opacity-0 invisible translate-y-1 group-hover:opacity-100 group-hover:visible group-hover:translate-y-0 transition-all duration-200 ease-out" 3015 style="line-height:1.32!important;"> 3016 <li><a class="sleek-nav-dropdown-lead" href="/senate/">Forecast</a></li> 3017 <li><a class="sleek-nav-dropdown-lead" href="/latest-polls/?year=2026&race=senate">Latest Polls</a></li> 3018 <li><a href="/senate/alaska/forecast/">Alaska</a></li> 3019 <li><a href="/senate/georgia/forecast/">Georgia</a></li> 3020 <li><a href="/senate/iowa/forecast/">Iowa</a></li> 3021 <li><a href="/senate/maine/forecast/">Maine</a></li> 3022 <li><a href="/senate/michigan/forecast/">Michigan</a></li> 3023 <li><a href="/senate/nebraska/forecast/">Nebraska</a></li> 3024 <li><a href="/senate/new-hampshire/forecast/">New Hampshire</a></li> 3025 <li><a href="/senate/north-carolina/forecast/">North Carolina</a></li> 3026 <li><a href="/senate/ohio/forecast/">Ohio</a></li> 3027 <li><a href="/senate/texas/forecast/">Texas</a></li> 3028 </ul> 3029 </div> 3030 <!-- 2026 House --> 3031 <div class="relative group"> 3032 <a href="/2026-us-house/" 3033 class="inline-flex items-center gap-2 px-1 py-1 text-slate-200 hover:text-white"> 3034 2026 House 3035 <svg width="16" height="16" viewBox="0 0 20 20" fill="currentColor" 3036 class="text-slate-500 opacity-90 transition-transform duration-200 ease-out group-hover:text-slate-300 group-hover:rotate-180"> 3037 <path 3038 d="M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.71a.75.75 0 011.08 1.04l-4.25 4.25a.75.75 0 01-1.06 0L5.21 8.27a.75.75 0 01.02-1.06z" /> 3039 </svg> 3040 </a> 3041 <ul class="sleek-nav-dropdown sleek-nav-dropdown--races absolute top-full left-0 z-50 opacity-0 invisible translate-y-1 group-hover:opacity-100 group-hover:visible group-hover:translate-y-0 transition-all duration-200 ease-out" 3042 style="line-height:1.32!important;"> 3043 <li><a class="sleek-nav-dropdown-lead" href="/2026-us-house/">Forecast</a></li> 3044 <li><a class="sleek-nav-dropdown-lead" href="/latest-polls/?year=2026&race=house">Latest Polls</a></li> 3045 </ul> 3046 </div> 3047 <!-- 2026 Governors --><div class="relative group"> 3048 <a href="/governor/" 3049 class="inline-flex items-center gap-2 px-1 py-1 text-slate-200 hover:text-white"> 3050 2026 Governors 3051 <svg width="16" height="16" viewB
3051ox="0 0 20 20" fill="currentColor" 3052 class="text-slate-500 opacity-90 transition-transform duration-200 ease-out group-hover:text-slate-300 group-hover:rotate-180"> 3053 <path 3054 d="M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.71a.75.75 0 011.08 1.04l-4.25 4.25a.75.75 0 01-1.06 0L5.21 8.27a.75.75 0 01.02-1.06z" /> 3055 </svg> 3056 </a> 3057 <ul class="sleek-nav-dropdown sleek-nav-dropdown--races absolute top-full left-0 z-50 opacity-0 invisible translate-y-1 group-hover:opacity-100 group-hover:visible group-hover:translate-y-0 transition-all duration-200 ease-out" 3058 style="line-height:1.32!important;"> 3059 <li><a class="sleek-nav-dropdown-lead" href="/governor/">Forecast</a></li> 3060 <li><a class="sleek-nav-dropdown-lead" href="/latest-polls/?year=2026&race=governor">Latest Polls</a></li> 3061 <li><a href="/governor/arizona/forecast/">Arizona</a></li> 3062 <li><a href="/governor/california/forecast/">California</a></li> 3063 <li><a href="/governor/florida/forecast/">Florida</a></li> 3064 <li><a href="/governor/georgia/forecast/">Georgia</a></li> 3065 <li><a href="/governor/iowa/forecast/">Iowa</a></li> 3066 <li><a href="/governor/kansas/democratic-primary/">Kansas</a></li> 3067 <li><a href="/governor/michigan/forecast/">Michigan</a></li> 3068 <li><a href="/governor/nevada/forecast/">Nevada</a></li> 3069 <li><a href="/governor/ohio/forecast/">Ohio</a></li> 3070 <li><a href="/governor/wisconsin/forecast/">Wisconsin</a></li> 3071 </ul> 3072 </div> 3073 3074 <!-- 2028 President --> 3075 <div class="relative group"> 3076 <a href="/2028-president/" 3077 class="inline-flex items-center gap-2 px-1 py-1 text-slate-200 hover:text-white"> 3078 2028 President 3079 <svg width="16" height="16" viewBox="0 0 20 20" fill="currentColor" 3080 class="text-slate-500 opacity-90 transition-transform duration-200 ease-out group-hover:text-slate-300 group-hover:rotate-180"> 3081 <path 3082 d="M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.71a.75.75 0 011.08 1.04l-4.25 4.25a.75.75 0 01-1.06 0L5.21 8.27a.75.75 0 01.02-1.06z" /> 3083 </svg> 3084 </a> 3085 <ul class="sleek-nav-dropdown sleek-nav-dropdown--2028 absolute top-full left-0 z-50 opacity-0 invisible translate-y-1 group-hover:opacity-100 group-hover:visible group-hover:translate-y-0 transition-all duration-200 ease-out" 3086 style="line-height:1.32!important;"> 3087 <li><a class="sleek-nav-dropdown-lead" href="/2028-president/">Primaries Hub</a> 3088 </li> 3089 <li><a class="sleek-nav-dropdown-lead" href="/latest-polls/?year=2028&race=president">Latest Polls</a></li> 3090 <li><a href="/2028-democratic-primary/">Democratic Primary</a></li> 3091 <li><a href="/2028-republican-primary/">Republican Primary</a></li> 3092 </ul> 3093 </div> 3094 3095 </nav> 3096 </div> 3097 3098 <!-- Right-side controls (static so they don't pop in after shared.js) --> 3099 <div class="sleek-home-header-meta flex items-end gap-2 sm:gap-3 shrink-0 min-w-0"> 3100 <a href="/" class="text-slate-300 hover:text-white" 3101 style="font-size:16px!important; line-height:1.28!important;">pollsmax.com</a> 3102 <a id="pollsmax-header-latest-polls" class="pollsmax-header-latest-polls" href="/latest-polls/" 3103 aria-label="Latest Polls" title="Latest Polls"> 3104 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" 3105 stroke-linecap="round" aria-hidden="true"> 3106 <path d="M8 6h13M8 12h13M8 18h13" /> 3107 <path d="M3 6h.01M3 12h.01M3 18h.01" /> 3108 </svg> 3109 </a> 3110 <a href="https://x.com/Pollsmax" target="_blank" rel="noopener noreferrer" 3111 class="hover:opacity-70 transition-opacity" aria-label="Pollsmax on X"> 3112 <img src="/images/twitter.svg" alt="Pollsmax on X" class="h-4 w-4" /> 3113 </a> 3114 <button type="button" id="pollsmax-theme-toggle" class="pollsmax-theme-toggle" 3115 aria-label="Switch to light mode" aria-pressed="false" title="Switch to light mode"> 3116 <svg class="pollsmax-theme-toggle__moon" viewB
3116ox="0 0 24 24" fill="currentColor" aria-hidden="true"> 3117 <path d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79z" /> 3118 </svg> 3119 <svg class="pollsmax-theme-toggle__sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" 3120 stroke-width="2" aria-hidden="true"> 3121 <circle cx="12" cy="12" r="4" /> 3122 <path 3123 d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" /> 3124 </svg> 3125 </button> 3126 <a id="pollsmax-header-donate" class="pollsmax-header-donate" href="/login/">Login</a> 3127 </div> 3128 </div> 3129 </div> 3130 </header> 3131 3132 <p id="homeMobileLastUpdatedBar" class="home-mobile-last-updated-bar" aria-live="polite" hidden></p> 3133 3134 <nav id="site-primary-nav" class="sleek-sitelinks-strip w-full px-4 sm:px-6 lg:px-10 xl:px-14 py-2 flex flex-wrap items-center gap-x-5 sm:gap-x-6 lg:gap-x-8 gap-y-1.5 border-b border-slate-700/45" 3135 aria-label="Pollsmax primary sections"> 3136 <a href="/latest-polls/" class="sleek-sitelinks-item">Latest Polls</a> 3137 <a href="/approval/trump/" class="sleek-sitelinks-item">Trump Approval</a> 3138 <a href="/approval/generic-ballot/" class="sleek-sitelinks-item">Generic Ballot</a> 3139 <a href="/2028-democratic-primary/" class="sleek-sitelinks-item">2028 Democratic Primary</a> 3140 <a href="/2028-republican-primary/" class="sleek-sitelinks-item">2028 Republican Primary</a> 3141 <a href="/electoral-history/" class="sleek-sitelinks-item">Electoral History</a> 3142 <a href="/election-map/fillable-maps/" class="sleek-sitelinks-item">Fillable Maps</a> 3143 <p id="homeHeaderLastUpdated" class="sleek-home-header-updated sleek-sitelinks-strip__updated" aria-live="polite"> 3144 <button type="button" class="sleek-home-header-all-toggle" aria-label="Toggle header visibility">All</button> 3145 <span class="sleek-home-header-updated-tail">forecasts and polling data last updated 12:00 AM on July 12, 2026.</span> 3146 </p> 3147 </nav> 3148 3149 <main class="w-full max-w-none min-w-0 overflow-x-hidden pt-0 pb-20 mv-content"> 3150 <aside class="pm-tx-ad-band pm-tx-ad-band--desktop" data-pm-home-place="page-top" aria-hidden="true"><div class="pm-ad-slot"></div></aside> 3151<section class="home-intro" aria-label="About Pollsmax"> 3152 <span class="home-intro__logo-wrap"> 3153 <img class="home-intro__logo" src="/images/logo.webp" alt="Pollsmax" width="220" height="72" decoding="async" /> 3154 </span> 3155 <p class="home-intro__copy">Pollsmax is a political data platform that tracks key elections across the United States. We aggregate political polling data and provide forecasts for major races, including all 35 Senate, 435 House, and 36 governor elections in 2026. Our polling averages and forecasts are updated daily, helping you stay informed on the latest developments in US politics.</p> 3156 </section> 3157 3158 <!-- Senate + House forecasts (maps); tooltips need overflow-visible --> 3159 <!-- border-t matches the top of the vertical column divider (Senate | House). --> 3160 <div class="sleek-maps sleek-maps--home-senate-house grid lg:grid-cols-2 gap-0 border-t border-b border-slate-800/80 overflow-visible pollsmax-content"> 3161 <!-- Senate Map --> 3162 <div class="sleek-map-pane max-lg:border-b lg:border-r border-slate-800/80 p-0"> 3163 <div class="px-4 sm:px-6 lg:px-10 xl:px-14 pt-8"> 3164 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2026 3165 MIDTERMS</p> 3166 <div class="sleek-home-forecast-head border-b border-slate-800/80 pb-4 mb-3"> 3167 <a href="/senate/" 3168 class="group sleek-home-forecast-head__link no-underline text-inherit hover:opacity-90 transition-opacity"> 3169 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white" 3170 style="position:relative;top:2px;">
3171 <span class="home-mob-title-year">2026</span>Senate Forecast<span 3172 class="text-slate-500 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 3173 </h2> 3174 </a> 3175 <p class="home-forecast-chance" data-home-forecast-chance="senate" aria-live="polite"><span class="home-forecast-chance__em home-forecast-chance__em--r">Republicans</span> have a <span class="home-forecast-chance__em home-forecast-chance__em--r">75.9%</span> chance of winning the Senate.</p> 3176 <div class="sleek-home-forecast-head__countdown"> 3177 <div class="forecast-hub-midterm-countdown forecast-hub-midterm-countdown--home" 3178 data-forecast-hub-midterm-countdown aria-live="polite"> 3179 <div class="forecast-hub-midterm-countdown__boxes"> 3180 <div class="forecast-hub-midterm-countdown__box"> 3181 <span class="forecast-hub-midterm-countdown__value" 3182 data-hub-cd="months">00</span> 3183 <span class="forecast-hub-midterm-countdown__unit">Mos</span> 3184 </div> 3185 <div class="forecast-hub-midterm-countdown__box"> 3186 <span class="forecast-hub-midterm-countdown__value" 3187 data-hub-cd="days">00</span> 3188 <span class="forecast-hub-midterm-countdown__unit">Days</span> 3189 </div> 3190 <div class="forecast-hub-midterm-countdown__box"> 3191 <span class="forecast-hub-midterm-countdown__value" 3192 data-hub-cd="hours">00</span> 3193 <span class="forecast-hub-midterm-countdown__unit">Hrs</span> 3194 </div> 3195 <div class="forecast-hub-midterm-countdown__box"> 3196 <span class="forecast-hub-midterm-countdown__value" 3197 data-hub-cd="minutes">00</span> 3198 <span class="forecast-hub-midterm-countdown__unit">Mins</span> 3199 </div> 3200 <div class="forecast-hub-midterm-countdown__box"> 3201 <span class="forecast-hub-midterm-countdown__value" 3202 data-hub-cd="seconds">00</span> 3203 <span class="forecast-hub-midterm-countdown__unit">Secs</span> 3204 </div> 3205 </div> 3206 </div> 3207 </div> 3208 </div> 3209 </div> 3210 3211 <div class="px-4 sm:px-6 lg:px-10 xl:px-14 pb-6"> 3212 <!-- Seat bar --> 3213 <div class="block mb-3 mt-6"> 3214 <div class="w-full forecast-hub-seat-bar-wrap"> 3215 <div 3216 class="flex items-center justify-between text-sm tracking-wide mb-1 sleek-seat-bar-label"> 3217 <span class="font-normal">Democrats</span> 3218 <span class="font-normal">Republicans</span> 3219 </div> 3220 3221 <div class="relative w-full h-10 forecast-hub-bar-rail" 3222 style="border:0;outline:0;box-shadow:none"> 3223 <div class="absolute inset-0 rounded-md overflow-hidden pointer-events-none" 3224 style="border:0;outline:0;box-shadow:none"> 3225 <div id="barR" class="absolute right-0 top-0 h-full rounded-r-md overflow-hidden" 3226 style="background:#f42726;width:50%;box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.38)"> 3227 <div id="barRFlip" class="absolute top-0 left-0 h-full pointer-events-none" 3228 style="width:0%"></div> 3229 </div> 3230 <div id="barTie" class="absolute top-0 h-full" 3231 style="background:#64748b;width:0%;left:50%;box-shadow:inset 0 0 0 1px rgba(255,255,255,.38)"> 3232 </div> 3233 <div id="barD" class="absolute left-0 top-0 h-full rounded-l-md overflow-hidden" 3234 style="background:#0c6df6;width:50%;box-shadow:inset -1px 0 0 rgba(255, 255, 255, 0.38)"> 3235 <div id="barDFlip" class="absolute top-0 right-0 h-full pointer-events-none" 3236 style="width:0%"></div> 3237 </div> 3238 </div> 3239 3240 <div id="numD" 3241 class="absolute left-3 top-1/2 -translate-y-1/2 text-xl md:text-2xl font-bold">â 3242 </div> 3243 <div id="numR" 3244 class="absolute right-3 top-1/2 -translate-y-1/2 text-xl md:text-2xl font-bold">â 3245 </div> 3246 3247 <div class="absolute left-1/2 -translate-x-1/2 -top-6 text-[10px] sleek-seat-threshold"> 3248 51 seats to win</div> 3249 <div class="absolute left-1/2 -translate-x-1/2 -top-2 sleek-seat-indicator" 3250 aria-hidden="true"></div> 3251 </div> 3252 </div> 3253 </div> 3254 3255 <!-- Map --> 3256 <div class="mt-2 relative home-forecast-map-stage"> 3257
3257<script> 3258(function () { 3259 var FRAG = '/fragments/home-us-map.svg?v=20260926chamberhub0945'; 3260 var htmlFrag = window.__pmHomeUsMapFrag; 3261 if (!htmlFrag) { 3262 try { 3263 var xhr = new XMLHttpRequest(); 3264 xhr.open('GET', FRAG, false); 3265 xhr.send(null); 3266 if (xhr.status >= 200 && xhr.status < 300) htmlFrag = xhr.responseText; 3267 } catch (eX) { htmlFrag = ''; } 3268 } 3269 if (htmlFrag) { 3270 document.write(htmlFrag); 3271 } else { 3272 document.write('<svg id="usMap" viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet" data-chamber-map-prerendered="0" aria-hidden="true"></svg>'); 3273 } 3274})(); 3275</script>
3275 3276 <div id="mapTip" role="tooltip"></div> 3277 </div> 3278 </div> 3279 </div> 3280 3281 <aside class="pm-tx-ad-band pm-tx-ad-band--mobile" data-pm-mob-place="under-senate" aria-hidden="true"><div class="pollsmax-ad-single__inner pm-ad-slot"></div></aside> 3282 3283 <!-- House Map (same pane geometry as former Governors slot) --> 3284 <div class="sleek-map-pane p-0"> 3285 <div class="px-4 sm:px-6 lg:px-10 xl:px-14 pt-8"> 3286 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2026 3287 MIDTERMS</p> 3288 <div class="sleek-home-forecast-head border-b border-slate-800/80 pb-4 mb-3"> 3289 <a href="/2026-us-house/" 3290 class="group sleek-home-forecast-head__link no-underline text-inherit hover:opacity-90 transition-opacity"> 3291 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white" 3292 style="position:relative;top:2px;"> 3293 <span class="home-mob-title-year">2026</span>House Forecast<span 3294 class="text-slate-500 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 3295 </h2> 3296 </a> 3297 <p class="home-forecast-chance" data-home-forecast-chance="house" aria-live="polite"><span class="home-forecast-chance__em home-forecast-chance__em--d">Democrats</span> have a <span class="home-forecast-chance__em home-forecast-chance__em--d">69.6%</span> chance of winning the House.</p> 3298 <div class="sleek-home-forecast-head__countdown"> 3299 <div class="forecast-hub-midterm-countdown forecast-hub-midterm-countdown--home" 3300 data-forecast-hub-midterm-countdown aria-live="polite"> 3301 <div class="forecast-hub-midterm-countdown__boxes"> 3302 <div class="forecast-hub-midterm-countdown__box"> 3303 <span class="forecast-hub-midterm-countdown__value" 3304 data-hub-cd="months">00</span> 3305 <span class="forecast-hub-midterm-countdown__unit">Mos</span> 3306 </div> 3307 <div class="forecast-hub-midterm-countdown__box"> 3308 <span class="forecast-hub-midterm-countdown__value" 3309 data-hub-cd="days">00</span> 3310 <span class="forecast-hub-midterm-countdown__unit">Days</span> 3311 </div> 3312 <div class="forecast-hub-midterm-countdown__box"> 3313 <span class="forecast-hub-midterm-countdown__value" 3314 data-hub-cd="hours">00</span> 3315 <span class="forecast-hub-midterm-countdown__unit">Hrs</span> 3316 </div> 3317 <div class="forecast-hub-midterm-countdown__box"> 3318 <span class="forecast-hub-midterm-countdown__value" 3319 data-hub-cd="minutes">00</span> 3320 <span class="forecast-hub-midterm-countdown__unit">Mins</span> 3321 </div> 3322 <div class="forecast-hub-midterm-countdown__box"> 3323 <span class="forecast-hub-midterm-countdown__value" 3324 data-hub-cd="seconds">00</span>
3325 <span class="forecast-hub-midterm-countdown__unit">Secs</span> 3326 </div> 3327 </div> 3328 </div> 3329 </div> 3330 </div> 3331 </div> 3332 3333 <div class="px-4 sm:px-6 lg:px-10 xl:px-14 pb-6"> 3334 <!-- House seat bar --> 3335 <div class="block mb-3 mt-6"> 3336 <div id="homeHouseSeatBar" class="w-full forecast-hub-seat-bar-wrap"> 3337 <div 3338 class="flex items-center justify-between text-sm tracking-wide mb-1 sleek-seat-bar-label"> 3339 <span class="font-normal">Democrats</span> 3340 <span class="font-normal">Republicans</span> 3341 </div> 3342 3343 <div class="relative w-full h-10 forecast-hub-bar-rail" 3344 style="border:0;outline:0;box-shadow:none"> 3345 <div class="absolute inset-0 rounded-md overflow-hidden pointer-events-none" 3346 style="border:0;outline:0;box-shadow:none"> 3347 <div id="houseBarR" class="absolute right-0 top-0 h-full rounded-r-md overflow-hidden" 3348 style="background:#f42726;width:50%;box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.38)"> 3349 <div id="houseBarRFlip" class="absolute top-0 left-0 h-full pointer-events-none" 3350 style="width:0%"></div> 3351 </div> 3352 <div id="houseBarTie" class="absolute top-0 h-full" 3353 style="background:#64748b;width:0%;left:50%;box-shadow:inset 0 0 0 1px rgba(255,255,255,.38)"> 3354 </div> 3355 <div id="houseBarD" class="absolute left-0 top-0 h-full rounded-l-md overflow-hidden" 3356 style="background:#0c6df6;width:50%;box-shadow:inset -1px 0 0 rgba(255, 255, 255, 0.38)"> 3357 <div id="houseBarDFlip" class="absolute top-0 right-0 h-full pointer-events-none" 3358 style="width:0%"></div> 3359 </div> 3360 </div> 3361 3362 <div id="houseNumD" 3363 class="absolute left-3 top-1/2 -translate-y-1/2 text-xl md:text-2xl font-bold">â 3364 </div> 3365 <div id="houseNumR" 3366 class="absolute right-3 top-1/2 -translate-y-1/2 text-xl md:text-2xl font-bold">â 3367 </div> 3368 3369 <div class="absolute left-1/2 -translate-x-1/2 -top-6 text-[10px] sleek-seat-threshold"> 3370 218 seats to win</div> 3371 <div class="absolute left-1/2 -translate-x-1/2 -top-2 sleek-seat-indicator" 3372 aria-hidden="true"></div> 3373 </div> 3374 </div> 3375 </div> 3376 3377 <!-- House Map --> 3378 <div class="mt-2 relative home-forecast-map-stage home-forecast-map-stage--house"> 3379
3379<script> 3380(function () { 3381 var FRAG = '/fragments/home-house-cd-map.svg?v=20260926chamberhub0945'; 3382 var htmlFrag = window.__pmHomeHouseMapFrag; 3383 if (!htmlFrag) { 3384 try { 3385 var xhr = new XMLHttpRequest(); 3386 xhr.open('GET', FRAG, false); 3387 xhr.send(null); 3388 if (xhr.status >= 200 && xhr.status < 300) htmlFrag = xhr.responseText; 3389 } catch (eX) { htmlFrag = ''; } 3390 } 3391 if (htmlFrag) { 3392 document.write(htmlFrag); 3393 } else { 3394 document.write('<svg id="houseCdMap" viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet" data-house-map-prerendered="0" aria-hidden="true"></svg>'); 3395 } 3396})(); 3397</script>
3397 3398 <div id="houseMapTip" role="tooltip"></div> 3399 </div> 3400 </div> 3401 </div> 3402 </div> 3403 3404 <!-- Governors forecast + Support Pollsmax --> 3405 <!-- Senate/House already has border-b â no border-t here (would double). --> 3406 <div class="sleek-maps sleek-maps--home-gov-donate grid lg:grid-cols-2 gap-0 border-b border-slate-800/80 overflow-visible"> 3407 <!-- Governor Map --> 3408 <div class="sleek-map-pane max-lg:border-b lg:border-r border-slate-800/80 p-0"> 3409 <div class="px-4 sm:px-6 lg:px-10 xl:px-14 pt-8"> 3410 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2026 3411 MIDTERMS</p> 3412 <div class="sleek-home-forecast-head border-b border-slate-800/80 pb-4 mb-3"> 3413 <a href="/governor/" 3414 class="group sleek-home-forecast-head__link no-underline text-inherit hover:opacity-90 transition-opacity"> 3415 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white" 3416 style="position:relative;top:2px;"> 3417 <span class="home-mob-title-year">2026</span>Governors Forecast<span 3418 class="text-slate-500 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 3419 </h2> 3420 </a> 3421 <p class="home-forecast-chance" data-home-forecast-chance="gov" aria-live="polite"><span class="home-forecast-chance__em home-forecast-chance__em--r">Republicans</span> are projected to win <span class="home-forecast-chance__em home-forecast-chance__em--r">25</span> governorships and <span class="home-forecast-chance__em home-forecast-chance__em--d">Democrats</span> are projected to win <span class="home-forecast-chance__em home-forecast-chance__em--d">25</span>.</p> 3422 <div class="sleek-home-forecast-head__countdown"> 3423 <div class="forecast-hub-midterm-countdown forecast-hub-midterm-countdown--home" 3424 data-forecast-hub-midterm-countdown aria-live="polite"> 3425 <div class="forecast-hub-midterm-countdown__boxes"> 3426 <div class="forecast-hub-midterm-countdown__box"> 3427 <span class="forecast-hub-midterm-countdown__value" 3428 data-hub-cd="months">00</span> 3429 <span class="forecast-hub-midterm-countdown__unit">Mos</span> 3430 </div> 3431 <div class="forecast-hub-midterm-countdown__box"> 3432 <span class="forecast-hub-midterm-countdown__value" 3433 data-hub-cd="days">00</span> 3434 <span class="forecast-hub-midterm-countdown__unit">Days</span> 3435 </div> 3436 <div class="forecast-hub-midterm-countdown__box"> 3437 <span class="forecast-hub-midterm-countdown__value" 3438 data-hub-cd="hours">00</span> 3439 <span class="forecast-hub-midterm-countdown__unit">Hrs</span> 3440 </div> 3441 <div class="forecast-hub-midterm-countdown__box"> 3442 <span class="forecast-hub-midterm-countdown__value" 3443 data-hub-cd="minutes">00</span>
3444 <span class="forecast-hub-midterm-countdown__unit">Mins</span> 3445 </div> 3446 <div class="forecast-hub-midterm-countdown__box"> 3447 <span class="forecast-hub-midterm-countdown__value" 3448 data-hub-cd="seconds">00</span> 3449 <span class="forecast-hub-midterm-countdown__unit">Secs</span> 3450 </div> 3451 </div> 3452 </div> 3453 </div> 3454 </div> 3455 </div> 3456 3457 <div class="px-4 sm:px-6 lg:px-10 xl:px-14 pb-6"> 3458 <!-- Governor seat bar --> 3459 <div class="block mb-3 mt-6"> 3460 <div class="w-full forecast-hub-seat-bar-wrap"> 3461 <div 3462 class="flex items-center justify-between text-sm tracking-wide mb-1 sleek-seat-bar-label"> 3463 <span class="font-normal">Democrats</span> 3464 <span class="font-normal">Republicans</span> 3465 </div> 3466 3467 <div class="relative w-full h-10 forecast-hub-bar-rail" 3468 style="border:0;outline:0;box-shadow:none"> 3469 <div class="absolute inset-0 rounded-md overflow-hidden pointer-events-none" 3470 style="border:0;outline:0;box-shadow:none"> 3471 <div id="govBarR" class="absolute right-0 top-0 h-full rounded-r-md overflow-hidden" 3472 style="background:#f42726;width:50%;box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.38)"> 3473 <div id="govBarRFlip" class="absolute top-0 left-0 h-full pointer-events-none" 3474 style="width:0%"></div> 3475 </div> 3476 <div id="govBarD" class="absolute left-0 top-0 h-full rounded-l-md overflow-hidden" 3477 style="background:#0c6df6;width:50%;box-shadow:inset -1px 0 0 rgba(255, 255, 255, 0.38)"> 3478 <div id="govBarDFlip" class="absolute top-0 right-0 h-full pointer-events-none" 3479 style="width:0%"></div> 3480 </div> 3481 </div> 3482 3483 <div id="govNumD" 3484 class="absolute left-3 top-1/2 -translate-y-1/2 text-xl md:text-2xl font-bold">â 3485 </div> 3486 <div id="govNumR" 3487 class="absolute right-3 top-1/2 -translate-y-1/2 text-xl md:text-2xl font-bold">â 3488 </div> 3489 3490 <div 3491 class="absolute left-1/2 -translate-x-1/2 -top-6 text-[10px] text-center max-w-[11rem] leading-tight sleek-seat-threshold"> 3492 26 governors for a majority</div> 3493 <div class="absolute left-1/2 -translate-x-1/2 -top-2 sleek-seat-indicator" 3494 aria-hidden="true"></div> 3495 </div> 3496 </div> 3497 </div> 3498 3499 <!-- Governor Map --> 3500 <div class="mt-2 relative home-forecast-map-stage"> 3501
3501<script> 3502(function () { 3503 var FRAG = '/fragments/home-gov-map.svg?v=20260926chamberhub0945'; 3504 var htmlFrag = window.__pmHomeGovMapFrag; 3505 if (!htmlFrag) { 3506 try { 3507 var xhr = new XMLHttpRequest(); 3508 xhr.open('GET', FRAG, false); 3509 xhr.send(null); 3510 if (xhr.status >= 200 && xhr.status < 300) htmlFrag = xhr.responseText; 3511 } catch (eX) { htmlFrag = ''; } 3512 } 3513 if (htmlFrag) { 3514 document.write(htmlFrag); 3515 } else { 3516 document.write('<svg id="govMap" viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet" data-chamber-map-prerendered="0" aria-hidden="true"></svg>'); 3517 } 3518})(); 3519</script>
3519 3520 <div id="govMapTip" role="tooltip"></div> 3521 </div> 3522 </div> 3523 </div> 3524 3525 <aside class="pm-tx-ad-band pm-tx-ad-band--mobile" data-pm-mob-place="under-gov" aria-hidden="true"><div class="pollsmax-ad-single__inner pm-ad-slot"></div></aside> 3526 3527 <!-- Support Pollsmax (right of Governors; height follows Governors on desktop) --> 3528 <div class="sleek-map-pane sleek-map-pane--home-donate p-0 overflow-visible"> 3529 <section class="home-donate-pane px-4 sm:px-6 lg:px-10 xl:px-14 pt-8 pb-6"> 3530 <div class="home-donate-pane__head"> 3531 <p class="sleek-eyebrow home-donate-pane__eyebrow mb-1.5 block">DONATE</p> 3532 <a href="/donate/" 3533 class="home-donate-pane__title-link group block border-b border-slate-800/80 hover:opacity-90 transition-opacity"> 3534 <h2 class="home-donate-pane__title text-xl sm:text-2xl font-bold tracking-tight text-white group-hover:text-slate-200"> 3535 Support Pollsmax<span class="home-donate-pane__title-arrow text-slate-500 font-normal pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 3536 </h2> 3537 </a> 3538 </div> 3539 <div class="home-donate-pane__body"> 3540 <p class="home-donate-pane__blurb"> 3541 Unlock an ad-free experience and exclusive forecasts and polling data. Subscriptions are the best way to support Pollsmax. All proceeds go toward site maintenance and development. If you feel that Pollsmax has provided some value to you, please consider subscribing! 3542 </p> 3543 <div class="donate-grid donate-grid--plans home-donate-pane__grid" aria-label="Subscription plans"> 3544 <article class="donate-card"> 3545 <h3 class="donate-plan-name">Pollsmax Plus</h3> 3546 <div class="donate-amount">$5</div> 3547 <div class="donate-frequency">per month</div> 3548 <ul class="donate-perks"> 3549 <li>100% ad-free experience</li> 3550 <li>Access to all 435 House forecasts for the 2026 midterms</li> 3551 </ul> 3552 <a class="donate-button" href="/subscribe/">Subscribe</a> 3553 </article> 3554 <article class="donate-card donate-card--popular"> 3555 <div class="donate-popular"><span class="donate-popular__text">Most Popular!</span></div> 3556 <h3 class="donate-plan-name">Pollsmax Pro</h3> 3557 <div class="donate-amount">$10</div> 3558 <div class="donate-frequency">per month</div> 3559 <ul class="donate-perks"> 3560 <li>Everything in Pollsmax Plus</li> 3561 <li>Exclusive polling data tracking Trump's approval by issue, Vance approval, and more</li> 3562 </ul> 3563 <a class="donate-button" href="/subscribe/">Subscribe</a> 3564 </article> 3565 </div> 3566 <a class="donate-one-time home-donate-pane__once" 3567 href="https://donate.stripe.com/dRm4gycML5JXfmkaKR9oc00" target="_blank" 3568 rel="noopener noreferrer">Make a one-time donation instead.</a> 3569 </div> 3570 </section> 3571 </div> 3572 </div> 3573 3574 3575 <!-- Poll explorer / Latest Polls (under Governors forecast) --> 3576 <aside class="pm-tx-ad-band pm-tx-ad-band--desktop" data-pm-home-place="under-upcoming" aria-hidden="true"><div class="pm-ad-slot"></div></aside> 3577<section id="searchAllPollsSection" 3578 class="border-b border-slate-800/80 px-4 sm:px-6 lg:px-10 xl:px-14 pt-[calc(2rem-6px)] pb-8"> 3579 <div class="max-w-4xl"> 3580 <a href="/latest-polls/"
3581 class="group search-all-polls-title-link inline-flex items-center no-underline text-inherit hover:opacity-90 transition-opacity"> 3582 <h2 3583 class="text-[1.95rem] sm:text-[2.15rem] font-bold tracking-tight text-white group-hover:text-slate-200 transition-colors m-0"> 3584 Search All Polls<span 3585 class="search-all-polls-title-arrow text-slate-500 font-normal inline-block" 3586 aria-hidden="true"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 3587 </h2> 3588 </a> 3589 <p class="home-panel-blurb">Select a race you're interested in to see the latest polling data.</p> 3590 </div> 3591 3592 <div class="search-all-polls-filters flex flex-col sm:flex-row flex-wrap items-stretch sm:items-end gap-4 sm:gap-8 mt-1"> 3593 <div id="homeSearchYearField" class="flex items-center gap-2"> 3594 <label class="text-[11px] font-semibold uppercase tracking-wider text-slate-500">Year</label> 3595 <select id="yearSelect" class="sleek-select pill px-0 py-2 text-slate-100 text-sm min-w-[10rem]"> 3596 <option value="2026">2026</option> 3597 </select> 3598 </div> 3599 <div id="homeSearchRaceField" class="flex items-center gap-2"> 3600 <label class="text-[11px] font-semibold uppercase tracking-wider text-slate-500">Race</label> 3601 <select id="categorySelect" 3602 class="sleek-select pill px-0 py-2 text-slate-100 text-sm min-w-[10rem]"> 3603 <option value="2026-us-senate">Senate</option> 3604 <option value="2026-governors">Governor</option> 3605 <option value="2026-us-house">House</option> 3606 </select> 3607 </div> 3608 <div id="homeSearchStateField" class="flex items-center gap-2"> 3609 <label class="text-[11px] font-semibold uppercase tracking-wider text-slate-500">State</label> 3610 <select id="entitySelect" class="sleek-select pill px-0 py-2 text-slate-100 text-sm min-w-[10rem]"> 3611 <option value="MI" data-key="MI">Michigan</option> 3612 </select> 3613 </div> 3614 <div id="homeSearchDistrictField" class="flex items-center gap-2"> 3615 <label class="text-[11px] font-semibold uppercase tracking-wider text-slate-500">District</label> 3616 <select id="districtSelect" class="sleek-select pill px-0 py-2 text-slate-100 text-sm min-w-[10rem]" disabled aria-label="District"> 3617 </select> 3618 </div> 3619 <div id="homeSearchTypeField" class="flex items-center gap-2"> 3620 <label class="text-[11px] font-semibold uppercase tracking-wider text-slate-500">Type</label> 3621 <select id="typeSelect" class="sleek-select pill px-0 py-2 text-slate-100 text-sm min-w-[10rem]"> 3622 <option value="general-election">General Election</option> 3623 </select> 3624 </div> 3625 </div> 3626 3627 <div class="grid lg:grid-cols-[minmax(0,2.5fr)_minmax(0,1fr)] gap-x-8 gap-y-10 lg:mt-4"> 3628 <div class="min-w-0 lg:-mt-3"> 3629 <div class="search-poll-head-wrap"> 3630 <div class="border-b border-slate-800/80 pb-4 mb-5"> 3631 <div class="search-poll-head-text-row"> 3632 <div id="searchPollFlagWrap" class="search-poll-flag-rail is-visible" aria-hidden="true"> 3633 <img id="searchPollFlagImg" class="search-poll-flag-img" src="/images/mi.webp" alt="" 3634 decoding="async" fetchpriority="low" /> 3635 </div> 3636 <div class="min-w-0 flex-1 flex flex-col"> 3637 <a id="trendLabel" href="/senate/" 3638 class="sleek-eyebrow mb-1.5 block hover:text-slate-300 transition-colors no-u
3638nderline" 3639 style="font-size:0.9rem;">2026 SENATE</a> 3640 <h3 3641 class="search-poll-state-heading group text-xl sm:text-2xl font-semibold tracking-tight text-white m-0 relative"> 3642 <a id="entityLink" href="/senate/michigan/" 3643 class="hover:text-slate-300 transition-colors">Michigan</a><a 3644 id="entityArrow" href="/senate/michigan/" 3645 class="text-slate-600 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></a> 3646 </h3> 3647 </div> 3648 </div> 3649 </div> 3650 </div> 3651 <div 3652 class="sleek-chart-stage sleek-chart-stage--home-search et-mobile-standard-width-ref relative w-full h-[340px]"> 3653 <canvas id="searchChart"></canvas> 3654 <div id="searchChartEmptyOverlay" 3655 class="absolute inset-0 z-[1] flex items-center justify-center pointer-events-none hidden" 3656 aria-hidden="true"> 3657 <span class="text-3xl sm:text-4xl font-normal text-slate-500">No Polls Yet</span> 3658 </div> 3659 </div> 3660 </div> 3661 <div class="min-w-0 lg:mt-[-2px]"> 3662 <div class="sleek-poll-sidebar overflow-hidden"> 3663 <div class="sleek-poll-sidebar-head flex items-center justify-between gap-2 px-3 py-2.5"> 3664 <span class="text-[11px] font-bold uppercase tracking-[0.12em] text-slate-400">All 3665 polls</span> 3666 </div> 3667 <ul id="searchTable" class="sleek-poll-list space-y-0 text-[13px] min-h-0"></ul> 3668 </div> 3669 </div> 3670 </div> 3671 3672</section> 3673 <aside class="pm-tx-ad-band pm-tx-ad-band--mobile" data-pm-mob-place="under-search" aria-hidden="true"><div class="pollsmax-ad-single__inner pm-ad-slot"></div></aside> 3674 3675 <!-- National charts: Trump approval + generic ballot (below Search All Polls) --> 3676 <!-- border-t matches the top of the vertical column divider (Trump | Generic Ballot). --> 3677 <aside class="pm-tx-ad-band pm-tx-ad-band--desktop" data-pm-home-place="under-search" aria-hidden="true"><div class="pm-ad-slot"></div></aside> 3678<div class="sleek-maps sleek-maps--home-approval grid lg:grid-cols-2 gap-0 border-t border-b border-slate-800/80 overflow-visible"> 3679 <div class="sleek-map-pane max-lg:border-b lg:border-r border-slate-800/80 p-0 overflow-visible"> 3680 <section class="px-4 sm:px-6 lg:px-10 xl:px-14 pt-8 pb-11 overflow-visible"> 3681 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">APPROVAL 3682 RATINGS</p> 3683 <div class="home-panel-head border-b border-slate-800/80 pb-4 mb-5"> 3684 <a href="/approval/trump/" 3685 class="group block no-underline text-inherit hover:opacity-90 transition-opacity"> 3686 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white group-hover:text-slate-200" 3687 style="position:relative;top:2px;"> 3688 Donald Trump Job Approval<span 3689 class="text-slate-500 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 3690 </h2> 3691 </a> 3692 <p class="home-panel-blurb" data-home-panel-blurb="trump" aria-l
3692ive="polite">President Donald Trump is <span class="home-panel-blurb__em home-panel-blurb__em--r">disapproved</span> of by <span class="home-panel-blurb__em home-panel-blurb__em--r">57.9%</span> of Americans and <span class="home-panel-blurb__em home-panel-blurb__em--approve">approved</span> of by <span class="home-panel-blurb__em home-panel-blurb__em--approve">39.3%</span>.</p> 3693 </div> 3694 <div class="sleek-chart-stage relative w-full h-[374px] mt-[3.75rem]"> 3695 <canvas id="trumpHomeApprovalChart"></canvas> 3696 </div> 3697 </section> 3698 </div> 3699 <div class="sleek-map-pane p-0 overflow-visible"> 3700 <section class="px-4 sm:px-6 lg:px-10 xl:px-14 pt-8 pb-11 overflow-visible"> 3701 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2026 3702 MIDTERMS</p> 3703 <div class="home-panel-head border-b border-slate-800/80 pb-4 mb-5"> 3704 <a href="/approval/generic-ballot/" 3705 class="group block no-underline text-inherit hover:opacity-90 transition-opacity"> 3706 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white group-hover:text-slate-200" 3707 style="position:relative;top:2px;"> 3708 Generic Congressional Ballot<span 3709 class="text-slate-500 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 3710 </h2> 3711 </a> 3712 <p class="home-panel-blurb" data-home-panel-blurb="generic-ballot" aria-live="polite"><span class="home-panel-blurb__em home-panel-blurb__em--d">Democrats</span> are favored by <span class="home-panel-blurb__em home-panel-blurb__em--d">47.5%</span> of Americans and <span class="home-panel-blurb__em home-panel-blurb__em--r">Republicans</span> are favored by <span class="home-panel-blurb__em home-panel-blurb__em--r">40.8%</span>.</p> 3713 </div> 3714 <div class="sleek-chart-stage relative w-full h-[374px] mt-[3.75rem]"> 3715 <canvas id="gbHomeBallotChart"></canvas> 3716 </div> 3717 </section> 3718 </div> 3719 <aside class="pm-tx-ad-band pm-tx-ad-band--mobile" data-pm-mob-place="under-gb" aria-hidden="true"><div class="pollsmax-ad-single__inner pm-ad-slot"></div></aside> 3720 </div> 3721 3722<!-- Key races: pt-8 matches section headers above; pb-8 above outer border-b --> 3723 <div id="homeKeyRacesSection" class="border-b border-slate-800/80"> 3724 <div class="home-key-races-grid grid lg:grid-cols-3 px-4 sm:px-6 lg:px-10 xl:px-14"> 3725 <section 3726 class="home-key-races-col home-key-races-col--senate border-b lg:border-b-0 lg:border-r border-slate-800/80 pt-8 pb-8"> 3727 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2026 3728 MIDTERMS</p> 3729 <div class="border-b border-slate-800/80 pb-4 mb-3"> 3730 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white" 3731 style="position:relative;top:2px;">Key Senate Races</h2> 3732 </div> 3733 <div class="mt-6"> 3734 <div class="mb-2 senate-races-sort-row sleek-home-key-races-sort"> 3735 <span class="senate-sort-btn senate-sort-state shrink-0">STATE</span> 3736 <div class="senate-races-sort-metrics"> 3737 <div class="senate-sort-cands-col"> 3738 <span class="senate-sort-btn senate-sort-polling">PROJECTED VOTE</span> 3739 </div>
3740 <span class="senate-sort-btn senate-sort-margin">RATING</span> 3741 </div> 3742 </div> 3743 <a href="/senate/alaska/forecast/" class="sleek-race-row race-link group w-full text-left"> 3744 <div class="flex flex-wrap items-center min-w-0"> 3745 <span class="key-race-flag-wrap"><img src="/images/ak.webp" alt="" class="key-race-flag" 3746 width="18" height="12" decoding="async" /></span> 3747 <span class="text-lg font-medium text-white">Alaska</span> 3748 </div> 3749 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3750 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3751 id="alaskaCandidates"> 3752 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3753 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3754 </div> 3755 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3756 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3757 </div> 3758 </div> 3759 </a> 3760 <a href="/senate/georgia/forecast/" class="sleek-race-row race-link group w-full text-left"> 3761 <div class="flex flex-wrap items-center min-w-0"> 3762 <span class="key-race-flag-wrap"><img src="/images/ga.webp" alt="" class="key-race-flag" 3763 width="18" height="12" decoding="async" /></span> 3764 <span class="text-lg font-medium text-white">Georgia</span> 3765 </div> 3766 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3767 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3768 id="georgiaCandidates"> 3769 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3770 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3771 </div> 3772 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3773 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3774 </div> 3775 </div> 3776 </a> 3777 <a href="/senate/iowa/forecast/" class="sleek-race-row race-link group w-full text-left"> 3778 <div class="flex flex-wrap items-center min-w-0"> 3779 <span class="key-race-flag-wrap"><img src="/images/ia.webp" alt="" class="key-race-flag" 3780 width="18" height="12" decoding="async" /></span> 3781 <span class="text-lg font-medium text-white">Iowa</span> 3782 </div> 3783 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3784 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3785 id="iowaCandidates">
3786 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3787 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3788 </div> 3789 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3790 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3791 </div> 3792 </div> 3793 </a> 3794 <a href="/senate/maine/forecast/" class="sleek-race-row race-link group w-full text-left"> 3795 <div class="flex flex-wrap items-center min-w-0"> 3796 <span class="key-race-flag-wrap"><img src="/images/me.webp" alt="" class="key-race-flag" 3797 width="18" height="12" decoding="async" /></span> 3798 <span class="text-lg font-medium text-white">Maine</span> 3799 </div> 3800 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3801 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3802 id="maineCandidates"> 3803 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3804 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3805 </div> 3806 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3807 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3808 </div> 3809 </div> 3810 </a> 3811 <a href="/senate/michigan/forecast/" class="sleek-race-row race-link group w-full text-left"> 3812 <div class="flex flex-wrap items-center min-w-0"> 3813 <span class="key-race-flag-wrap"><img src="/images/mi.webp" alt="" class="key-race-flag" 3814 width="18" height="12" decoding="async" /></span> 3815 <span class="text-lg font-medium text-white">Michigan</span> 3816 </div> 3817 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3818 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3819 id="michiganCandidates"> 3820 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3821 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3822 </div> 3823 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3824 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3825 </div> 3826 </div> 3827 </a> 3828 <a href="/senate/nebraska/forecast/" class="sleek-race-row race-link group w-full text-left"> 3829 <div class="flex flex-wrap items-center min-w-0">
3830 <span class="key-race-flag-wrap"><img src="/images/ne.webp" alt="" class="key-race-flag" 3831 width="18" height="12" decoding="async" /></span> 3832 <span class="text-lg font-medium text-white">Nebraska</span> 3833 </div> 3834 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3835 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3836 id="nebraskaCandidates"> 3837 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3838 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3839 </div> 3840 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3841 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3842 </div> 3843 </div> 3844 </a> 3845 <a href="/senate/new-hampshire/forecast/" class="sleek-race-row race-link group w-full text-left"> 3846 <div class="flex flex-wrap items-center min-w-0"> 3847 <span class="key-race-flag-wrap"><img src="/images/nh.webp" alt="" class="key-race-flag" 3848 width="18" height="12" decoding="async" /></span> 3849 <span class="text-lg font-medium text-white">New Hampshire</span> 3850 </div> 3851 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3852 <div class="senate-race-cands-col text-[12px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3853 id="newHampshireCandidates"> 3854 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3855 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3856 </div> 3857 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3858 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3859 </div> 3860 </div> 3861 </a> 3862 <a href="/senate/north-carolina/forecast/" class="sleek-race-row race-link group w-full text-left"> 3863 <div class="flex flex-wrap items-center min-w-0"> 3864 <span class="key-race-flag-wrap"><img src="/images/nc.webp" alt="" class="key-race-flag" 3865 width="18" height="12" decoding="async" /></span> 3866 <span class="text-lg font-medium text-white">North Carolina</span> 3867 </div> 3868 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3869 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3870 id="northCarolinaCandidates"> 3871 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span>
3872 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3873 </div> 3874 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3875 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3876 </div> 3877 </div> 3878 </a> 3879 <a href="/senate/ohio/forecast/" class="sleek-race-row race-link group w-full text-left"> 3880 <div class="flex flex-wrap items-center min-w-0"> 3881 <span class="key-race-flag-wrap"><img src="/images/oh.webp" alt="" class="key-race-flag" 3882 width="18" height="12" decoding="async" /></span> 3883 <span class="text-lg font-medium text-white">Ohio</span> 3884 </div> 3885 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3886 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3887 id="ohioCandidates"> 3888 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3889 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3890 </div> 3891 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3892 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3893 </div> 3894 </div> 3895 </a> 3896 <a href="/senate/texas/forecast/" class="sleek-race-row race-link group w-full text-left"> 3897 <div class="flex flex-wrap items-center min-w-0"> 3898 <span class="key-race-flag-wrap"><img src="/images/tx.webp" alt="" class="key-race-flag" 3899 width="18" height="12" decoding="async" /></span> 3900 <span class="text-lg font-medium text-white">Texas</span> 3901 </div> 3902 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3903 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3904 id="texasCandidates"> 3905 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3906 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3907 </div> 3908 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3909 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3910 </div> 3911 </div> 3912 </a> 3913 </div> 3914 3915</section> 3916 <section 3917 class="home-key-races-col home-key-races-col--house border-b lg:border-b-0 lg:border-r border-slate-800/80 pt-8 pb-8"> 3918 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2026 3919 MIDTERMS</p> 3920 <div class="border-b border-slate-800/80 pb-4 mb-3"> 3921 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white" 3922 style="position:relative;top:2px;">Key House Races</h2> 3923 </div> 3924 <div class="mt-6"> 3925 <div class="mb-2 senate-races-sort-row sleek-home-key-races-sort">
3926 <span class="senate-sort-btn senate-sort-state shrink-0">DISTRICT</span> 3927 <div class="senate-races-sort-metrics"> 3928 <div class="senate-sort-cands-col"> 3929 <span class="senate-sort-btn senate-sort-polling">PROJECTED VOTE</span> 3930 </div> 3931 <span class="senate-sort-btn senate-sort-margin">RATING</span> 3932 </div> 3933 </div> 3934 <div id="homeKeyHouseRacesList"> 3935 <div class="sleek-race-row w-full text-left"> 3936 <div class="flex flex-wrap items-center min-w-0"> 3937 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-row" aria-hidden="true"></span> 3938 </div> 3939 </div> 3940 </div> 3941 </div> 3942 3943</section> 3944 <section class="home-key-races-col home-key-races-col--gov pt-8 pb-8"> 3945 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2026 3946 MIDTERMS</p> 3947 <div class="border-b border-slate-800/80 pb-4 mb-3"> 3948 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white" 3949 style="position:relative;top:2px;">Key Governor Races</h2> 3950 </div> 3951 <div class="mt-6"> 3952 <div class="mb-2 senate-races-sort-row sleek-home-key-races-sort"> 3953 <span class="senate-sort-btn senate-sort-state shrink-0">STATE</span> 3954 <div class="senate-races-sort-metrics"> 3955 <div class="senate-sort-cands-col"> 3956 <span class="senate-sort-btn senate-sort-polling">PROJECTED VOTE</span> 3957 </div> 3958 <span class="senate-sort-btn senate-sort-margin">RATING</span> 3959 </div> 3960 </div> 3961 <a href="/governor/arizona/forecast/" class="sleek-race-row race-link group w-full text-left"> 3962 <div class="flex flex-wrap items-center min-w-0"> 3963 <span class="key-race-flag-wrap"><img src="/images/az.webp" alt="" class="key-race-flag" 3964 width="18" height="12" decoding="async" /></span> 3965 <span class="text-lg font-medium text-white">Arizona</span> 3966 </div> 3967 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3968 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3969 id="arizonaGovCandidates"> 3970 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3971 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3972 </div> 3973 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3974 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3975 </div> 3976 </div> 3977 </a> 3978 <a href="/governor/california/forecast/" class="sleek-race-row race-link group w-full text-left"> 3979 <div class="flex flex-wrap items-center min-w-0">
3980 <span class="key-race-flag-wrap"><img src="/images/ca.webp" alt="" class="key-race-flag" 3981 width="18" height="12" decoding="async" /></span> 3982 <span class="text-lg font-medium text-white">California</span> 3983 </div> 3984 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 3985 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 3986 id="californiaGovCandidates"> 3987 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3988 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 3989 </div> 3990 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 3991 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 3992 </div> 3993 </div> 3994 </a> 3995 <a href="/governor/florida/forecast/" class="sleek-race-row race-link group w-full text-left"> 3996 <div class="flex flex-wrap items-center min-w-0"> 3997 <span class="key-race-flag-wrap"><img src="/images/fl.webp" alt="" class="key-race-flag" 3998 width="18" height="12" decoding="async" /></span> 3999 <span class="text-lg font-medium text-white">Florida</span> 4000 </div> 4001 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4002 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4003 id="floridaGovCandidates"> 4004 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4005 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4006 </div> 4007 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4008 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4009 </div> 4010 </div> 4011 </a> 4012 <a href="/governor/georgia/forecast/" class="sleek-race-row race-link group w-full text-left"> 4013 <div class="flex flex-wrap items-center min-w-0"> 4014 <span class="key-race-flag-wrap"><img src="/images/ga.webp" alt="" class="key-race-flag" 4015 width="18" height="12" decoding="async" /></span> 4016 <span class="text-lg font-medium text-white">Georgia</span> 4017 </div> 4018 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4019 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4020 id="georgiaGovCandidates"> 4021 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span>
4022 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4023 </div> 4024 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4025 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4026 </div> 4027 </div> 4028 </a> 4029 <a href="/governor/iowa/forecast/" class="sleek-race-row race-link group w-full text-left"> 4030 <div class="flex flex-wrap items-center min-w-0"> 4031 <span class="key-race-flag-wrap"><img src="/images/ia.webp" alt="" class="key-race-flag" 4032 width="18" height="12" decoding="async" /></span> 4033 <span class="text-lg font-medium text-white">Iowa</span> 4034 </div> 4035 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4036 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4037 id="iowaGovCandidates"> 4038 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4039 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4040 </div> 4041 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4042 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4043 </div> 4044 </div> 4045 </a> 4046 <a href="/governor/kansas/democratic-primary/" id="kansasGovRaceLink" 4047 class="sleek-race-row race-link group w-full text-left"> 4048 <div class="flex flex-wrap items-center min-w-0"> 4049 <span class="key-race-flag-wrap"><img src="/images/ks.webp" alt="" class="key-race-flag" 4050 width="18" height="12" decoding="async" /></span> 4051 <span class="text-lg font-medium text-white">Kansas</span> 4052 </div> 4053 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4054 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4055 id="kansasGovCandidates"> 4056 <div class="font-normal text-slate-400">No Polls Yet</div> 4057 </div> 4058 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4059 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4060 </div> 4061 </div> 4062 </a> 4063 <a href="/governor/michigan/forecast/" class="sleek-race-row race-link group w-full text-left"> 4064 <div class="flex flex-wrap items-center min-w-0"> 4065 <span class="key-race-flag-wrap"><img src="/images/mi.webp" alt="" class="key-race-flag" 4066 width="18" height="12" decoding="async" /></span> 4067 <span class="text-lg font-medium text-white">Michigan</span> 4068 </div> 4069 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4070 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4071 id="michiganGovCandidates">
4072 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4073 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4074 </div> 4075 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4076 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4077 </div> 4078 </div> 4079 </a> 4080 <a href="/governor/nevada/forecast/" class="sleek-race-row race-link group w-full text-left"> 4081 <div class="flex flex-wrap items-center min-w-0"> 4082 <span class="key-race-flag-wrap"><img src="/images/nv.webp" alt="" class="key-race-flag" 4083 width="18" height="12" decoding="async" /></span> 4084 <span class="text-lg font-medium text-white">Nevada</span> 4085 </div> 4086 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4087 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4088 id="nevadaGovCandidates"> 4089 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4090 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4091 </div> 4092 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4093 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4094 </div> 4095 </div> 4096 </a> 4097 <a href="/governor/ohio/forecast/" class="sleek-race-row race-link group w-full text-left"> 4098 <div class="flex flex-wrap items-center min-w-0"> 4099 <span class="key-race-flag-wrap"><img src="/images/oh.webp" alt="" class="key-race-flag" 4100 width="18" height="12" decoding="async" /></span> 4101 <span class="text-lg font-medium text-white">Ohio</span> 4102 </div> 4103 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4104 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4105 id="ohioGovCandidates"> 4106 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4107 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4108 </div> 4109 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4110 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4111 </div> 4112 </div> 4113 </a> 4114 <a href="/governor/wisconsin/forecast/" class="sleek-race-row race-link group w-full text-left"> 4115 <div class="flex flex-wrap items-center min-w-0">
4116 <span class="key-race-flag-wrap"><img src="/images/wi.webp" alt="" class="key-race-flag" 4117 width="18" height="12" decoding="async" /></span> 4118 <span class="text-lg font-medium text-white">Wisconsin</span> 4119 </div> 4120 <div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0"> 4121 <div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px] pollsmax-skel-cands" 4122 id="wisconsinGovCandidates"> 4123 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4124 <span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-cand" aria-hidden="true"></span> 4125 </div> 4126 <div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0"> 4127 <span class="key-race-chip pollsmax-skel pollsmax-skel-chip" aria-hidden="true"></span> 4128 </div> 4129 </div> 4130 </a> 4131 </div> 4132 4133</section> 4134 </div> 4135 </div> 4136 4137 <!-- 2028 primaries (below Key Senate / House / Governor races) --> 4138 <!-- Key races already has border-b â no border-t here (would double). --> 4139 <div class="sleek-maps sleek-maps--home-primaries grid lg:grid-cols-2 gap-0 border-b border-slate-800/80 overflow-visible"> 4140 <div class="sleek-map-pane max-lg:border-b lg:border-r border-slate-800/80 p-0 overflow-visible"> 4141 <section class="px-4 sm:px-6 lg:px-10 xl:px-14 pt-8 pb-11 overflow-visible"> 4142 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2028 4143 PRESIDENT</p> 4144 <div class="home-panel-head border-b border-slate-800/80 pb-4 mb-5"> 4145 <a href="/2028-democratic-primary/" 4146 class="group block no-underline text-inherit hover:opacity-90 transition-opacity"> 4147 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white group-hover:text-slate-200" 4148 style="position:relative;top:2px;"> 4149 <span class="home-mob-title-year">2028</span>Democratic Primary<span 4150 class="text-slate-500 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 4151 </h2> 4152 </a> 4153 <p class="home-panel-blurb" data-home-panel-blurb="dem-2028" aria-live="polite"><span class="home-panel-blurb__em home-panel-blurb__em--d">Kamala Harris</span> leads the 2028 Democratic primary with <span class="home-panel-blurb__em home-panel-blurb__em--d">26.3%</span> support, followed by <span class="home-panel-blurb__em home-panel-blurb__em--d">Gavin Newsom</span> at <span class="home-panel-blurb__em home-panel-blurb__em--d">16.0%</span>.</p> 4154 </div> 4155 <div class="sleek-chart-stage relative w-full h-[374px] mt-[3.75rem]"> 4156 <canvas id="demHomePrimaryChart"></canvas> 4157 </div> 4158 4159</section> 4160 </div> 4161 <div class="sleek-map-pane p-0 overflow-visible"> 4162 <section class="px-4 sm:px-6 lg:px-10 xl:px-14 pt-8 pb-11 overflow-visible"> 4163 <p class="sleek-eyebrow mb-1.5 block" style="font-size:0.9rem;position:relative;top:4px;">2028 4164 PRESIDENT</p> 4165 <div class="home-panel-head border-b border-slate-800/80 pb-4 mb-5"> 4166 <a href="/2028-republican-primary/" 4167 class="group block no-underline text-inherit hover:opacity-90 transition-opacity"> 4168 <h2 class="text-xl sm:text-2xl font-bold tracking-tight text-white group-hover:text-slate-200" 4169 style="position:relative;top:2px;">
4170 <span class="home-mob-title-year">2028</span>Republican Primary<span 4171 class="text-slate-500 font-normal inline-block pm-trailing-arrow"><svg class="pm-trailing-arrow__icon" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M14.65 12.67a.35.35 0 01-.5-.01L10 8.55 5.85 12.66a.35.35 0 11-.5-.49l4.4-4.4a.35.35 0 01.5 0l4.4 4.4a.35.35 0 01-.01.5z" clip-rule="evenodd"/></svg></span> 4172 </h2> 4173 </a> 4174 <p class="home-panel-blurb" data-home-panel-blurb="gop-2028" aria-live="polite"><span class="home-panel-blurb__em home-panel-blurb__em--r">JD Vance</span> leads the 2028 Republican primary with <span class="home-panel-blurb__em home-panel-blurb__em--r">39.5%</span> support, followed by <span class="home-panel-blurb__em home-panel-blurb__em--r">Marco Rubio</span> at <span class="home-panel-blurb__em home-panel-blurb__em--r">19.4%</span>.</p> 4175 </div> 4176 <div class="sleek-chart-stage relative w-full h-[374px] mt-[3.75rem]"> 4177 <canvas id="gopHomePrimaryChart"></canvas> 4178 </div> 4179 4180</section> 4181 </div> 4182 <aside class="pm-tx-ad-band pm-tx-ad-band--mobile" data-pm-mob-place="under-gop" aria-hidden="true"><div class="pollsmax-ad-single__inner pm-ad-slot"></div></aside> 4183 </div> 4184 <aside class="pm-tx-ad-band pm-tx-ad-band--desktop" data-pm-home-place="page-bottom" aria-hidden="true"><div class="pm-ad-slot"></div></aside> 4185 4186</main> 4187 4188
4188<script> 4189 /* ET.buildMap and ET.buildGovMap: /assets/pm-shared-20260714s.js?v=hub-polls-20260926 (sleek bar map tooltips). */ 4190 // Governor seat bar: ET.updateGovSeatBar in /assets/pm-shared-20260714s.js?v=hub-polls-20260926 4191 4192 // Render mini charts for quick links 4193 function renderMiniChart(canvasId, data, colors, labels) { 4194 if (!window.Chart) return; 4195 var ctx = document.getElementById(canvasId); 4196 if (!ctx) return; 4197 var axisTheme = pollsmaxHomeChartAxisTheme(); 4198 4199 new Chart(ctx, { 4200 type: 'line', 4201 data: { 4202 labels: labels, 4203 datasets: data.map(function (dataset, i) { 4204 return { 4205 label: dataset.label, 4206 data: dataset.data, 4207 borderColor: colors[i], 4208 backgroundColor: colors[i] + '10', 4209 borderWidth: 2.5, 4210 fill: true, 4211 tension: 0.3, 4212 pointRadius: 0, 4213 pointHoverRadius: 0 4214 }; 4215 }) 4216 }, 4217 options: { 4218 responsive: true, 4219 maintainAspectRatio: false, 4220 plugins: { 4221 legend: { display: false }, 4222 tooltip: { 4223 enabled: true, 4224 backgroundColor: '#1f2937', 4225 titleColor: '#f1f5f9', 4226 bodyColor: '#e2e8f0', 4227 borderColor: '#374151', 4228 borderWidth: 1, 4229 cornerRadius: 8, 4230 displayColors: false, 4231 titleFont: { size: 12 }, 4232 bodyFont: { size: 11 }, 4233 padding: 8 4234 } 4235 }, 4236 scales: { 4237 x: { 4238 display: false 4239 }, 4240 y: { 4241 display: true, 4242 grid: { 4243 display: true, 4244 color: axisTheme.grid, 4245 drawBorder: false 4246 }, 4247 ticks: { 4248 color: axisTheme.tick, 4249 font: { size: 10 }, 4250 padding: 10, 4251 maxTicksLimit: 4 4252 } 4253 } 4254 }, 4255 layout: { 4256 padding: { 4257 left: 0, 4258 right: 0, 4259 top: 8, 4260 bottom: 8 4261 } 4262 }, 4263 elements: { 4264 point: { 4265 radius: 0, 4266 hoverRadius: 0 4267 } 4268 } 4269 } 4270 }); 4271 } 4272 4273 function setTextIfPresent(id, text) { 4274 const el = document.getElementById(id); 4275 if (el) el.textContent = text; 4276 } 4277 4278 function calculateVanceFavorabilityMargin() { 4279 // Calculate margin from Vance Favorability data (same logic as Vance page) 4280 const vancePolls = [ 4281 { date: '2025-08-24', pollster: 'Reuters / Ipsos', sample: '1022 A', approve: 39, disapprove: 53 }, 4282 { date: '2025-08-21', pollster: 'Harvard University / HarrisX', sample: '2025 RV', approve: 39, disapprove: 41 }, 4283 { date: '2025-08-11', pollster: 'Economist / YouGov', sample: '1474 RV', approve: 44, disapprove: 50 }, 4284 { date: '2025-08-09', pollster: 'Cygnal (R)', sample: '1500 RV', approve: 45, disapprove: 48 }, 4285 { date: '2025-08-03', pollster: 'Morning Consult', sample: '2201 RV', approve: 40, disapprove: 45 }, 4286 { date: '2025-07-16', pollster: 'Reuters / Ipsos', sample: '1027 A', approve: 38, disapprove: 52 }, 4287 { date: '2025-07-18', pollster: 'Atlas Intel', sample: '1935 A', approve: 44, disapprove: 55 }, 4288 { date: '2025-07-21', pollster: 'Gallup', sample: '750 A', approve: 38, disapprove: 49 }, 4289 { date: '2025-07-14', pollster: 'Big Data Poll (R)', sample: '3022 RV', approve: 45, disapprove: 46 }, 4290 { date: '2025-07-14', pollster: 'Economist / YouGov', sample: '1506 RV', approve: 41, disapprove: 52 }, 4291 { date: '2025-07-16', pollster: 'Marquette University', sample: '1005 A', approve: 38, disapprove: 49 }, 4292 { date: '2025-07-08', pollster: 'Harvard University / HarrisX', sample: '2044 RV', approve: 39, disapprove: 41 }, 4293 { date: '2025-07-02', pollster: 'Cygnal (R)', sample: '1500 LV', approve: 45, disapprove: 48 }, 4294 { date: '2025-06-30', pollster: 'Economist / YouGov', sample: '1491 RV', approve: 42, disapprove: 53 }, 4295 { date: '2025-06-27', pollster: 'TIPP Insights (R)', sample: '1421 A', approve: 39, disapprove: 37 },
4296 { date: '2025-06-16', pollster: 'Fox News', sample: '1003 RV', approve: 44, disapprove: 53 }, 4297 { date: '2025-06-16', pollster: 'Economist / YouGov', sample: '1351 RV', approve: 42, disapprove: 52 }, 4298 { date: '2025-06-12', pollster: 'Harvard University / HarrisX', sample: '2097 RV', approve: 41, disapprove: 39 }, 4299 { date: '2025-06-09', pollster: 'Quinnipiac University', sample: '1265 RV', approve: 35, disapprove: 48 }, 4300 { date: '2025-05-27', pollster: 'Atlas Intel', sample: '3469 A', approve: 42, disapprove: 56 }, 4301 { date: '2025-05-20', pollster: 'Quantus Insights (R)', sample: '1000 RV', approve: 43, disapprove: 45 }, 4302 { date: '2025-05-19', pollster: 'Economist / YouGov', sample: '1558 RV', approve: 42, disapprove: 51 } 4303 ]; 4304 4305 // Calculate 21-day moving average 4306 const today = new Date(); 4307 const cutoff = new Date(today.getTime() - (21 * 24 * 60 * 60 * 1000)); 4308 4309 const recentPolls = vancePolls.filter(poll => new Date(poll.date) >= cutoff); 4310 if (recentPolls.length === 0) { 4311 setTextIfPresent('vanceFavorabilityMargin', 'Unfavorable +8.0'); 4312 return; 4313 } 4314 4315 // Calculate averages 4316 const totals = { approve: 0, disapprove: 0 }; 4317 recentPolls.forEach(poll => { 4318 totals.approve += poll.approve || 0; 4319 totals.disapprove += poll.disapprove || 0; 4320 }); 4321 4322 const averages = { 4323 approve: totals.approve / recentPolls.length, 4324 disapprove: totals.disapprove / recentPolls.length 4325 }; 4326 4327 // Find leader and margin 4328 const margin = Math.abs(averages.approve - averages.disapprove); 4329 const leader = averages.disapprove >= averages.approve ? 'Unfavorable' : 'Favorable'; 4330 const marginText = leader + ' +' + (Math.round(margin * 10) / 10).toFixed(1); 4331 4332 setTextIfPresent('vanceFavorabilityMargin', marginText); 4333 } 4334 4335 function calculateNYCMayorMargin() { 4336 console.log('calculateNYCMayorMargin called'); 4337 // Use the actual data from shared.js 4338 if (window.ET && ET.MAYOR && ET.MAYOR.NYC2025 && ET.MAYOR.NYC2025.series) { 4339 console.log('NYC data found:', ET.MAYOR.NYC2025.series.length, 'polls'); 4340 const series = ET.MAYOR.NYC2025.series; 4341 if (series.length > 0) { 4342 // Calculate running average (last 5 polls) 4343 const recentPolls = series.slice(0, 5); 4344 const dAvg = recentPolls.reduce((sum, p) => sum + p.D, 0) / recentPolls.length; 4345 const rAvg = recentPolls.reduce((sum, p) => sum + p.R, 0) / recentPolls.length; 4346 const iyAvg = recentPolls.reduce((sum, p) => sum + p.IY, 0) / recentPolls.length; 4347 const igAvg = recentPolls.reduce((sum, p) => sum + p.IG, 0) / recentPolls.length; 4348 4349 // Find the top two candidates 4350 const candidates = [ 4351 { name: 'Mamdani', value: dAvg }, 4352 { name: 'Sliwa', value: rAvg }, 4353 { name: 'Cuomo', value: iyAvg }, 4354 { name: 'Adams', value: igAvg } 4355 ].sort((a, b) => b.value - a.value); 4356 4357 const lead = candidates[0]; 4358 const second = candidates[1]; 4359 const margin = second ? (lead.value - second.value) : 0; 4360 4361 const marginText = lead.name + (second ? ' +' + (Math.round(Math.abs(margin) * 10) / 10).toFixed(1) : ''); 4362 console.log('NYC calculated margin:', marginText); 4363 setTextIfPresent('nycMayorMargin', marginText); 4364 } else { 4365 // Fallback to hardcoded value if no data 4366 console.log('NYC no data, using fallback'); 4367 setTextIfPresent('nycMayorMargin', 'Mamdani +16.7'); 4368 } 4369 } else { 4370 // Fallback to hardcoded value if no data 4371 console.log('NYC ET data not available, using fallback'); 4372 setTextIfPresent('nycMayorMargin', 'Mamdani +16.7'); 4373 } 4374 } 4375 4376 function calculateVAGovMargin() { 4377 // Use the actual data from the Virginia Governor page 4378 if (window.ET && ET.SENATE && ET.SENATE.VA) { 4379 const vaData = ET.SENATE.VA; 4380 if (vaData.length > 0) { 4381 // Calculate running average (last 5 polls) 4382 const recentPolls = vaData.slice(0, 5); 4383 const dAvg = recentPolls.reduce((sum, p) => sum + p.D, 0) / recentPolls.length; 4384 const rAvg = recentPolls.reduce((sum, p) => sum + p.R, 0) / recentPolls.length; 4385 const margin = dAvg - rAvg; 4386 4387 const marginText = margin > 0 ? `Spanberger +${margin.toFixed(1)}` : `Earle-Sears +${Math.abs(margin).toFixed(1)}`; 4388 setTextIfPresent('vaGovMargin', marginText); 4389 } else { 4390 // Fallback to hardcoded value if no data 4391 setTextIfPresent('vaGovMargin', 'Spanberger +4.2'); 4392 } 4393 } else { 4394 // Fallback to hardcoded value if no data 4395 setTextIfPresent('vaGovMargin', 'Spanberger +4.2'); 4396 } 4397 } 4398 4399 function calculateGenericBallotMargin() { 4400 const genericBallotPolls = window.GENERIC_BALLOT_POLLS; 4401 if (!genericBallotPolls || !genericBallotPolls.length) { 4402 const el = document.getElementById('genericBallotMargin'); 4403 if (el) el.textContent = 'â'; 4404 return; 4405 } 4406 4407 // Calculate 28-day moving average 4408 const today = new Date(); 4409 const cutoff = new Date(today.getTime() - (28 * 24 * 60 * 60 * 1000)); 4410 4411 const recentPolls = genericBallotPolls.filter(poll => new Date(poll.date) >= cutoff); 4412 if (recentPolls.length === 0) { 4413 setTextIfPresent('genericBallotMargin', 'Democrats +0.3'); 4414 return; 4415 } 4416 4417 // Calculate averages 4418 const totals = { approve: 0, disapprove: 0 };
4419 recentPolls.forEach(poll => { 4420 totals.approve += poll.approve || 0; 4421 totals.disapprove += poll.disapprove || 0; 4422 }); 4423 4424 const averages = { 4425 approve: totals.approve / recentPolls.length, 4426 disapprove: totals.disapprove / recentPolls.length 4427 }; 4428 4429 // Find leader and margin 4430 const margin = Math.abs(averages.approve - averages.disapprove); 4431 const leader = averages.approve >= averages.disapprove ? 'Democrats' : 'Republicans'; 4432 const marginText = leader + ' +' + (Math.round(margin * 10) / 10).toFixed(1); 4433 4434 setTextIfPresent('genericBallotMargin', marginText); 4435 } 4436 4437 window.__pollsmaxAfterNationalPollRefresh = function () { 4438 calculateGenericBallotMargin(); 4439 }; 4440 4441 // Function to update all margins daily 4442 function updateAllMargins() { 4443 calculateNYCMayorMargin(); 4444 calculateVAGovMargin(); 4445 calculateGenericBallotMargin(); 4446 calculateVanceFavorabilityMargin(); 4447 } 4448 4449 // Set up daily updates (every 24 hours) 4450 function setupDailyUpdates() { 4451 // Wait for shared.js to load and then update 4452 function waitForDataAndUpdate() { 4453 if (window.ET && ET.MAYOR && ET.MAYOR.NYC2025) { 4454 console.log('Data available, calling updateAllMargins...'); 4455 updateAllMargins(); 4456 } else { 4457 console.log('Data not yet available, retrying in 100ms...'); 4458 setTimeout(waitForDataAndUpdate, 100); 4459 } 4460 } 4461 4462 waitForDataAndUpdate(); 4463 4464 // Then update every 24 hours 4465 setInterval(updateAllMargins, 24 * 60 * 60 * 1000); 4466 } 4467 4468 // Also run calculations on window load as a backup 4469 window.addEventListener('load', function () { 4470 console.log('Window loaded, running calculations...'); 4471 setTimeout(() => { 4472 updateAllMargins(); 4473 }, 1000); 4474 }); 4475 4476 var HOME_KEY_SENATE_RACES = [ 4477 { key: 'AK', href: '/state/alaska/', candId: 'alaskaCandidates' }, 4478 { key: 'GA', href: '/state/georgia/', candId: 'georgiaCandidates' }, 4479 { key: 'IA', href: '/state/iowa/', candId: 'iowaCandidates' }, 4480 { key: 'ME', href: '/state/maine/', candId: 'maineCandidates' }, 4481 { key: 'MI', href: '/state/michigan/', candId: 'michiganCandidates' }, 4482 { key: 'NE', href: '/state/nebraska/', candId: 'nebraskaCandidates' }, 4483 { key: 'NH', href: '/state/new-hampshire/', candId: 'newHampshireCandidates' }, 4484 { key: 'NC', href: '/state/north-carolina/', candId: 'northCarolinaCandidates' }, 4485 { key: 'OH', href: '/state/ohio/', candId: 'ohioCandidates' }, 4486 { key: 'TX', href: '/state/texas/', candId: 'texasCandidates' } 4487 ]; 4488 4489 var HOME_KEY_GOV_RACES = [ 4490 { key: 'AZ', href: '/governor/arizona/', candId: 'arizonaGovCandidates' }, 4491 { key: 'CA', href: '/governor/california/', candId: 'californiaGovCandidates' }, 4492 { key: 'FL', href: '/governor/florida/', candId: 'floridaGovCandidates' }, 4493 { key: 'GA', href: '/governor/georgia/', candId: 'georgiaGovCandidates' }, 4494 { key: 'IA', href: '/governor/iowa/', candId: 'iowaGovCandidates' }, 4495 { key: 'KS', href: '/governor/kansas/', candId: 'kansasGovCandidates', rowId: 'kansasGovRaceLink' }, 4496 { key: 'MI', href: '/governor/michigan/', candId: 'michiganGovCandidates' }, 4497 { key: 'NV', href: '/governor/nevada/', candId: 'nevadaGovCandidates' }, 4498 { key: 'OH', href: '/governor/ohio/', candId: 'ohioGovCandidates' }, 4499 { key: 'WI', href: '/governor/wisconsin/', candId: 'wisconsinGovCandidates' } 4500 ]; 4501 4502 function escapeHomeKeyRaceText(s) { 4503 if (typeof ET !== 'undefined' && typeof ET.escapeHtml === 'function') return ET.escapeHtml(s); 4504 return String(s == null ? '' : s) 4505 .replace(/&/g, '&') 4506 .replace(/</g, '<') 4507 .replace(/>/g, '>') 4508 .replace(/"/g, '"'); 4509 } 4510 4511 function homeKeyRaceLabelHtml(full, abbr) { 4512 return '<span class="key-race-label text-lg font-medium text-white">' + 4513 '<span class="key-race-label__full">' + escapeHomeKeyRaceText(full) + '</span>' + 4514 '<span class="key-race-label__abbr">' + escapeHomeKeyRaceText(abbr) + '</span>' + 4515 '</span>'; 4516 } 4517 4518 function homeKeyHouseAbbrLabel(row) { 4519 var st = String((row && row.st) || '').toUpperCase();
4520 if (!st && row && row.code) { 4521 var m = /^([A-Z]{2})-/i.exec(String(row.code)); 4522 if (m) st = m[1].toUpperCase(); 4523 } 4524 if (!st) return ''; 4525 var dist = row && row.dist; 4526 if (dist === 0) return st + ' AL'; 4527 if (dist != null && isFinite(dist)) return st + ' ' + dist; 4528 if (typeof ET !== 'undefined' && typeof ET.houseCompactDistrictCode === 'function') { 4529 return String(ET.houseCompactDistrictCode(row.code || '')).replace('-', ' '); 4530 } 4531 return st; 4532 } 4533 4534 function setHomeKeyRaceRowLabel(row, full, abbr) { 4535 if (!row || !full) return; 4536 abbr = abbr || full; 4537 var nameBox = row.querySelector(':scope > div:first-of-type'); 4538 if (!nameBox) return; 4539 var label = nameBox.querySelector('.key-race-label'); 4540 if (label) { 4541 var fullEl = label.querySelector('.key-race-label__full'); 4542 var abbrEl = label.querySelector('.key-race-label__abbr'); 4543 if (fullEl) fullEl.textContent = full; 4544 if (abbrEl) abbrEl.textContent = abbr; 4545 return; 4546 } 4547 var old = nameBox.querySelector('.text-lg.font-medium'); 4548 if (old) old.outerHTML = homeKeyRaceLabelHtml(full, abbr); 4549 } 4550 4551 function syncHomeKeyRacesCompactLabels() { 4552 var grid = document.querySelector('.home-key-races-grid'); 4553 if (!grid) return; 4554 var rows = grid.querySelectorAll('a.sleek-race-row'); 4555 if (!rows.length) { 4556 grid.classList.remove('home-key-races--compact'); 4557 grid.dataset.homeKeyCompact = '0'; 4558 return; 4559 } 4560 4561 var wasCompact = grid.dataset.homeKeyCompact === '1'; 4562 grid.classList.remove('home-key-races--compact'); 4563 void grid.offsetWidth; 4564 4565 var candsHidden = false; 4566 var anyNeedsAbbr = false; 4567 var i, row, nameBox, metrics, cands, gap, spare; 4568 for (i = 0; i < rows.length; i++) { 4569 row = rows[i]; 4570 nameBox = row.querySelector(':scope > div:first-of-type'); 4571 metrics = row.querySelector('.key-race-metrics, .senate-race-metrics'); 4572 if (!nameBox || !metrics) continue; 4573 cands = metrics.querySelector('.senate-race-cands-col'); 4574 if (cands && window.getComputedStyle(cands).display === 'none') { 4575 candsHidden = true; 4576 break; 4577 } 4578 if (metrics.offsetTop > nameBox.offsetTop + 2) { 4579 anyNeedsAbbr = true; 4580 break; 4581 } 4582 } 4583 4584 if (candsHidden) { 4585 grid.classList.remove('home-key-races--compact'); 4586 grid.dataset.homeKeyCompact = '0'; 4587 return; 4588 } 4589 4590 if (!anyNeedsAbbr && wasCompact) { 4591 gap = 16; 4592 for (i = 0; i < rows.length; i++) { 4593 row = rows[i]; 4594 nameBox = row.querySelector(':scope > div:first-of-type'); 4595 metrics = row.querySelector('.key-race-metrics, .senate-race-metrics'); 4596 if (!nameBox || !metrics) continue; 4597 spare = row.clientWidth - (nameBox.offsetWidth + metrics.offsetWidth + gap); 4598 if (spare < 28) { 4599 anyNeedsAbbr = true; 4600 break; 4601 } 4602 } 4603 } 4604 4605 if (anyNeedsAbbr) { 4606 grid.classList.add('home-key-races--compact'); 4607 grid.dataset.homeKeyCompact = '1'; 4608 } else { 4609 grid.dataset.homeKeyCompact = '0'; 4610 } 4611 } 4612 4613 var _homeKeyRacesCompactRo = null; 4614 var _homeKeyRacesCompactTimer = null; 4615 function scheduleHomeKeyRacesCompactSync() { 4616 if (_homeKeyRacesCompactTimer) clearTimeout(_homeKeyRacesCompactTimer); 4617 _homeKeyRacesCompactTimer = setTimeout(function () { 4618 _homeKeyRacesCompactTimer = null; 4619 syncHomeKeyRacesCompactLabels(); 4620 }, 50); 4621 } 4622 4623 function ensureHomeKeyRacesCompactObserver() { 4624 var grid = document.querySelector('.home-key-races-gri
4624d'); 4625 if (!grid || _homeKeyRacesCompactRo) { 4626 scheduleHomeKeyRacesCompactSync(); 4627 return; 4628 } 4629 if (typeof ResizeObserver === 'function') { 4630 _homeKeyRacesCompactRo = new ResizeObserver(scheduleHomeKeyRacesCompactSync); 4631 _homeKeyRacesCompactRo.observe(grid); 4632 var cols = grid.querySelectorAll('.home-key-races-col'); 4633 for (var i = 0; i < cols.length; i++) _homeKeyRacesCompactRo.observe(cols[i]); 4634 } else { 4635 window.addEventListener('resize', scheduleHomeKeyRacesCompactSync); 4636 } 4637 scheduleHomeKeyRacesCompactSync(); 4638 } 4639 4640 function applyHomeKeyRaceForecastRow(kind, cfg) { 4641 if (!cfg || !cfg.key || typeof ET === 'undefined') return; 4642 if (typeof ET.homeKeyRaceForecastRowMetrics !== 'function') return; 4643 var name = ET.NAME_BY_KEY && ET.NAME_BY_KEY[cfg.key]; 4644 var metrics = ET.homeKeyRaceForecastRowMetrics(kind, cfg.key, name); 4645 var row = cfg.rowId ? document.getElementById(cfg.rowId) : null; 4646 if (!row && cfg.candId) { 4647 var candHost = document.getElementById(cfg.candId); 4648 if (candHost) row = candHost.closest('a.sleek-race-row'); 4649 } 4650 if (!row && cfg.href) { 4651 row = document.querySelector('a.sleek-race-row[href="' + cfg.href + '"]'); 4652 } 4653 if (!row) return; 4654 if (typeof ET.homeKeyRaceForecastHref === 'function') { 4655 var dest = ET.homeKeyRaceForecastHref(kind, cfg.key); 4656 if (dest) row.href = dest; 4657 } 4658 if (name) setHomeKeyRaceRowLabel(row, name, cfg.key); 4659 var candEl = cfg.candId ? document.getElementById(cfg.candId) : row.querySelector('.key-race-cands'); 4660 var chipEl = row.querySelector('.key-race-chip'); 4661 if (candEl && metrics.candHtml) { 4662 candEl.innerHTML = metrics.candHtml; 4663 candEl.classList.remove('pollsmax-skel-cands'); 4664 } 4665 if (chipEl) { 4666 chipEl.innerHTML = metrics.ratingHtml || ''; 4667 chipEl.classList.remove('pollsmax-skel', 'pollsmax-skel-chip'); 4668 chipEl.removeAttribute('aria-hidden'); 4669 } 4670 } 4671 4672 function updateKeyRacesCandidates() { 4673 if (typeof ET === 'undefined' || typeof ET.homeKeyRaceForecastRowMetrics !== 'function') return; 4674 HOME_KEY_SENATE_RACES.forEach(function (cfg) { 4675 applyHomeKeyRaceForecastRow('senate', cfg); 4676 }); 4677 ensureHomeKeyRacesCompactObserver(); 4678 } 4679 4680 function updateGovernorRacesCandidates() { 4681 if (typeof ET === 'undefined' || typeof ET.homeKeyRaceForecastRowMetrics !== 'function') return; 4682 HOME_KEY_GOV_RACES.forEach(function (cfg) { 4683 applyHomeKeyRaceForecastRow('gov', cfg); 4684 }); 4685 ensureHomeKeyRacesCompactObserver(); 4686 } 4687 4688 function updateKeyHouseRacesCandidates() { 4689 if (typeof ET === 'undefined') return; 4690 var host = document.getElementById('homeKeyHouseRacesList'); 4691 if (!host) return; 4692 var rowsFn = typeof ET.homeKeyHouseProminentRaceRows === 'function' 4693 ? ET.homeKeyHouseProminentRaceRows 4694 : ET.homeKeyHouseClosestRaceRows; 4695 if (typeof rowsFn !== 'function' || 4696 typeof ET.homeKeyHouseRaceForecastRowMetrics !== 'function') { 4697 return; 4698 } 4699 if (typeof ET.applyHouseHubBakedForecast === 'function' && !ET._houseHubBakedForecastApplied) { 4700 try { ET.applyHouseHubBakedForecast(); } catch (e) { /* ignore */ } 4701 } 4702 var closest = rowsFn.call(ET); 4703 if (!closest || !closest.length) { 4704 host.innerHTML = '<div class="sleek-race-row w-full text-left"><div class="flex flex-wrap items-center min-w-0">' + 4705 '<span class="pollsmax-skel pollsmax-skel-line pollsmax-skel-line--key-row" aria-hidden="true"></span></div></div>'; 4706 return; 4707 } 4708 var html = ''; 4709 var i; 4710 for (i = 0; i < closest.length; i++) { 4711 var item = closest[i]; 4712 var row = item.row; 4713 var label = (typeof ET.houseHubAsideDistrictLabel === 'function') 4714 ? ET.houseHubAsideDistrictLabel(row, true) 4715 : (row.code || ''); 4716 var abbr = homeKeyHouseAbbrLabel(row) || label; 4717 var href = (typeof ET.homeKeyHouseRaceForecastHref === 'function') 4718 ? ET.homeKeyHouseRaceForecastHref(row) 4719 : null;
4720 if (!href && typeof ET.houseForecastDistrictUrl === 'function') { 4721 href = ET.houseForecastDistrictUrl(row.st, row.dist); 4722 } 4723 href = href || '#'; 4724 var metrics = ET.homeKeyHouseRaceForecastRowMetrics(row, item.snap); 4725 var st = String(row.st || '').toLowerCase(); 4726 var flagSrc = st ? ('/images/' + st + '.webp') : ''; 4727 html += '<a href="' + escapeHomeKeyRaceText(href) + '" class="sleek-race-row race-link group w-full text-left" data-district="' + 4728 escapeHomeKeyRaceText(row.code || '') + '">' + 4729 '<div class="flex flex-wrap items-center min-w-0">' + 4730 (flagSrc 4731 ? '<span class="key-race-flag-wrap"><img src="' + flagSrc + '" alt="" class="key-race-flag" width="18" height="12" decoding="async" /></span>' 4732 : '') + 4733 homeKeyRaceLabelHtml(label, abbr) + 4734 '</div>' + 4735 '<div class="senate-race-metrics key-race-metrics flex items-center shrink-0 ml-auto min-w-0">' + 4736 '<div class="senate-race-cands-col text-[13px] leading-[1.15] text-right tabular-nums min-w-0 flex-1 key-race-cands senate-race-cands-hub flex flex-col justify-center min-h-[30px]">' + 4737 (metrics.candHtml || '') + 4738 '</div>' + 4739 '<div class="senate-race-rating-col w-[5.5rem] flex justify-end items-center flex-shrink-0">' + 4740 '<span class="key-race-chip">' + (metrics.ratingHtml || '') + '</span>' + 4741 '</div></div></a>'; 4742 } 4743 host.innerHTML = html; 4744 ensureHomeKeyRacesCompactObserver(); 4745 } 4746 4747 /** Match margin chip height to #searchTable âAll pollsâ rows (`transform:scale(1.08)` on chip HTML). */ 4748 var SEARCH_ALL_POLLS_CHART_CHIP_SCALE = 1.08; 4749 /** General-election Search chart: `py` offset in ET.etPositionSleekHoverHeaderTooltip (negative = higher). */ 4750 var SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX = 0; 4751 /** Kept for compatibility; Search All Polls primaries now match GE hover header Y. */ 4752 var SEARCH_ALL_POLLS_PRIMARY_HOVER_HEADER_Y_EXTRA = 0; 4753 /** Desktop Search hover-dot radius. Mobile matches Trump Approval (uniform sleek = 5). */ 4754 var SEARCH_ALL_POLLS_DESKTOP_HOVER_DOT_RADIUS = 5.2; 4755 function searchAllPollsHoverDotRadius() { 4756 if (window.ET && typeof ET.isMobileLayout === 'function' && ET.isMobileLayout()) { 4757 if (ET.POLLSMAX_MOBILE_UNIFORM_SLEEK_HOVER_DOT_RADIUS != null && 4758 isFinite(ET.POLLSMAX_MOBILE_UNIFORM_SLEEK_HOVER_DOT_RADIUS)) { 4759 return ET.POLLSMAX_MOBILE_UNIFORM_SLEEK_HOVER_DOT_RADIUS; 4760 } 4761 return 5; 4762 } 4763 return SEARCH_ALL_POLLS_DESKTOP_HOVER_DOT_RADIUS; 4764 } 4765 /** Mobile Search All Polls: same dashed-line circle size/rings as home Trump Approval. */ 4766 function applySearchAllPollsMobileHoverDotSize(chartInst) { 4767 if (!chartInst || !window.ET) return; 4768 if (typeof ET.isMobileLayout !== 'function' || !ET.isMobileLayout()) return; 4769 chartInst._etSleekHoverPointRadius = searchAllPollsHoverDotRadius(); 4770 /* Match applyPollsmaxHomeApprovalHoverFormat rings used by Trump Approval. */ 4771 chartInst._etSleekHoverDotRingOuter = 2.15; 4772 chartInst._etSleekHoverDotRingInner = 1.05; 4773 var hoverLine = chartInst._etSleekHoverLine; 4774 if (hoverLine && hoverLine.points) { 4775 var dotR = chartInst._etSleekHoverPointRadius; 4776 for (var ri = 0; ri < hoverLine.points.length; ri++) { 4777 if (hoverLine.points[ri]) hoverLine.points[ri].r = dotR; 4778 } 4779 } 4780 } 4781 function wrapSearchAllPollsChartHoverChip(chipHtml) { 4782 return ( 4783 '<span style="display:inline-block;transform:scale(' + 4784 SEARCH_ALL_POLLS_CHART_CHIP_SCALE + 4785 ');transform-origin:center top">' +
4786 chipHtml + 4787 '</span>' 4788 ); 4789 } 4790 4791 // Search Latest Polls functionality (copied from Senate page) 4792 function initializeSearchLatestPolls() { 4793 const categorySelect = document.getElementById('categorySelect'); 4794 const entitySelect = document.getElementById('entitySelect'); 4795 const districtSelect = document.getElementById('districtSelect'); 4796 const entityLink = document.getElementById('entityLink'); 4797 const entityArrow = document.getElementById('entityArrow'); 4798 const trendLabel = document.getElementById('trendLabel'); 4799 let ctx = document.getElementById('searchChart'); 4800 let chart = null; 4801 let searchPollFlagResizeBound = false; 4802 4803 if (!categorySelect || !entitySelect) return; 4804 4805 if (typeof ET.initHomeSearchAllPollsFilters === 'function') { 4806 ET.initHomeSearchAllPollsFilters(); 4807 } 4808 4809 if (window.__pollsmaxHomeSearchPollsBound === '1') { 4810 return; 4811 } 4812 /* GE search only needs Chart.js + shared helpers â do not block on primary hub bundles. */ 4813 if (!window.Chart || !window.ET || typeof ET.gaFillSearchTypeSelect !== 'function') { 4814 var _pmWait = (window.__pollsmaxHomeSearchPollsWait = (window.__pollsmaxHomeSearchPollsWait || 0) + 1); 4815 if (_pmWait <= 120) { 4816 setTimeout(initializeSearchLatestPolls, 30); 4817 return; 4818 } 4819 } 4820 window.__pollsmaxHomeSearchPollsBound = '1'; 4821 4822 /* Reuse MI Senate preview chart when full search boots on the same race. */ 4823 if (ctx && window.Chart && typeof Chart.getChart === 'function') { 4824 var existingPreview = Chart.getChart(ctx); 4825 if (existingPreview) { 4826 chart = existingPreview; 4827 ctx._pollsmaxChartInstance = existingPreview; 4828 } else if (ctx._pollsmaxChartInstance) { 4829 chart = ctx._pollsmaxChartInstance; 4830 } 4831 } 4832 var tsBind = document.getElementById('typeSelect'); 4833 if (tsBind && !tsBind.dataset.pmSearchTypeBound) { 4834 tsBind.dataset.pmSearchTypeBound = '1'; 4835 tsBind.addEventListener('change', function () { 4836 scheduleSearchRender(); 4837 }); 4838 } 4839 4840 function bindSearchChartNav() { 4841 if (!ctx || ctx.dataset.pmChartNavBound === '1') return; 4842 ctx.dataset.pmChartNavBound = '1'; 4843 ctx.style.cursor = 'pointer'; 4844 ctx.addEventListener('click', function () { 4845 const a = document.getElementById('entityLink'); 4846 const h = a && a.getAttribute('href'); 4847 if (h && h !== '#' && h.indexOf('javascript:') !== 0) { 4848 window.location.href = h; 4849 } 4850 }); 4851 } 4852 function homeSearchChartMonthInterval() { 4853 return (typeof ET.homeSearchPollChartMonthInterval === 'function') 4854 ? ET.homeSearchPollChartMonthInterval() 4855 : 2; 4856 } 4857 function homeSearchChartOpts(extra) { 4858 return Object.assign({ xMonthInterval: homeSearchChartMonthInterval() }, extra || {}); 4859 } 4860 const govSearchPollOpts = homeSearchChartOpts({ blankSinglePoll: false }); 4861 4862 // All 2026 Senate races on site (ET.STATES); gray in dropdown when no polls yet. 4863 function senateEntityOptions() { 4864 if (!window.ET || !ET.STATES) return []; 4865 return ET.STATES 4866 .filter(function (s) { return ET.senateKeyHasSearchablePolling && ET.senateKeyHasSearchablePolling(s.key); }) 4867 .slice() 4868 .sort(function (a, b) { return a.name.localeCompare(b.name); }) 4869 .map(function (s) { return { value: s.key, text: s.name, key: s.key }; }); 4870 } 4871 4872 // All 2026 governor races with pages that have searchable GE or primary polling. 4873 function governorEntityOptions() { 4874 if (!window.ET || !ET.GOV_PAGE_KEYS || !ET.SLUG_BY_KEY || !ET.NAME_BY_KEY) return []; 4875 return ET.GOV_PAGE_KEYS 4876 .filter(function (k) { return ET.govKeyHasSearchablePollingLikeSenate && ET.govKeyHasSearchablePollingLikeSenate(k); }) 4877 .slice() 4878 .map(function (k) { return { value: ET.SLUG_BY_KEY[k], text: ET.NAME_BY_KEY[k] || k, key: k }; }) 4879 .sort(function (a, b) { return a.text.localeCompare(b.text); }); 4880 } 4881 4882 function refreshSearchChartCanvas(forceClone) { 4883 var canvas = document.getElementById('searchChart'); 4884 if (!canvas) return null; 4885 if (!forceClone) { 4886 if (canvas.style) { 4887 canvas.style.width = ''; 4888 canvas.style.height = ''; 4889 } 4890 return canvas; 4891 } 4892 var stage = canvas.parentNode; 4893 if (!stage) return canvas; 4894 var fresh = canvas.cloneNode(false); 4895 fresh.id = 'searchChart'; 4896 if (fresh.style) { 4897 fresh.style.width = ''; 4898 fresh.style.height = ''; 4899 }
4900 stage.replaceChild(fresh, canvas); 4901 return fresh; 4902 } 4903 4904 function ensureSearchChartStageHeight() { 4905 var stage = document.querySelector('.sleek-chart-stage--home-search'); 4906 var canvas = document.getElementById('searchChart'); 4907 if (!stage || !stage.style) return; 4908 if (window.ET && typeof ET.isMobileLayout === 'function' && ET.isMobileLayout()) { 4909 stage.style.height = '227px'; 4910 stage.style.minHeight = '227px'; 4911 if (canvas && canvas.style) { 4912 canvas.style.width = ''; 4913 canvas.style.height = ''; 4914 } 4915 } else { 4916 stage.style.height = ''; 4917 stage.style.minHeight = ''; 4918 if (canvas && canvas.style) { 4919 canvas.style.width = ''; 4920 canvas.style.height = ''; 4921 } 4922 } 4923 } 4924 4925 function applySearchChartMobilePostInit(chartInst, labels) { 4926 if (!chartInst) return; 4927 var mobCfg = (window.ET && typeof ET.pollsmaxHomeMobileChartConfig === 'function') 4928 ? ET.pollsmaxHomeMobileChartConfig() 4929 : null; 4930 if (mobCfg && typeof ET.applyCompactMobileChartPostInit === 'function') { 4931 ET.applyCompactMobileChartPostInit(chartInst, labels || (chartInst.data && chartInst.data.labels) || [], { 4932 headerYOffset: typeof SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX !== 'undefined' 4933 ? SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX 4934 : 0, 4935 autoplayHover: false, 4936 skipHoverApply: true 4937 }, mobCfg); 4938 } 4939 if (window.ET && typeof ET.isMobileLayout === 'function' && ET.isMobileLayout() && 4940 typeof ET.applyPollsmaxHomeApprovalHoverFormat === 'function') { 4941 var is2028Search = !!(chartInst._etSleekHover2028LabelPctSuffix || chartInst._etSleekHoverLabelAlignDotCenter); 4942 ET.applyPollsmaxHomeApprovalHoverFormat(chartInst, { 4943 headerYOffset: SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX, 4944 primary2028: is2028Search, 4945 autoplayHover: false 4946 }); 4947 /* Primaries + GE: EH glow chip + slightly larger Search All Polls date/chip. */ 4948 if (typeof ET.applyPollsmaxHomeMobileGlowChipHoverChrome === 'function') { 4949 ET.applyPollsmaxHomeMobileGlowChipHoverChrome(chartInst); 4950 } else if (typeof ET.applyHomeMobileSearchAllPollsHoverChrome === 'function') { 4951 ET.applyHomeMobileSearchAllPollsHoverChrome(chartInst); 4952 } 4953 /* Match GE chip+date Y for primaries and other race types. */ 4954 chartInst._etSleekHoverHeaderYOffset = SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX; 4955 chartInst._etSleekHover2028HeaderExtraDown = null; 4956 if (typeof ET.syncSearchPollHoverHeaderPosition === 'function') { 4957 ET.syncSearchPollHoverHeaderPosition(chartInst); 4958 } 4959 /* After approval hover format (which may null radius), lock dots to Trump size. */ 4960 applySearchAllPollsMobileHoverDotSize(chartInst); 4961 } 4962 } 4963 4964 function scheduleSearchChartResize(chartInst) { 4965 if (!chartInst || typeof chartInst.resize !== 'function') return; 4966 function doResize() { 4967 ensureSearchChartStageHeight(); 4968 try { chartInst.resize(); } catch (eSz) { /* ignore */ } 4969 if (chartInst.update) chartInst.update('none'); 4970 } 4971 requestAnimationFrame(function () { 4972 requestAnimationFrame(doResize); 4973 }); 4974 if (window.ET && typeof ET.isMobileLayout === 'function' && ET.isMobileLayout()) { 4975 setTimeout(doResize, 160); 4976 setTimeout(doResize, 420); 4977 } 4978 } 4979 4980 function disposeSearchChartInstance() { 4981 if (chart) { 4982 if (typeof ET.disposeSleekChartHoverChrome === 'function') { 4983 ET.disposeSleekChartHoverChrome(chart); 4984 } 4985 try { chart.destroy(); } catch (eDest) { } 4986 chart = null; 4987 } 4988 var cnv = document.getElementById('searchChart'); 4989 if (cnv && window.Chart && typeof Chart.getChart === 'function') { 4990 var reg = Chart.getChart(cnv); 4991 if (reg) { 4992 if (typeof ET.disposeSleekChartHoverChrome === 'function') { 4993 ET.disposeSleekChartHoverChrome(reg); 4994 } 4995 try { reg.destroy(); } catch (eReg) { } 4996 } 4997 } 4998 if (cnv && cnv._pollsmaxChartInstance) { 4999 try { cnv._pollsmaxChartInstance.destroy(); } catch (ePm) { } 5000 cnv._pollsmaxChartInstance = null; 5001 } 5002 var stage = document.querySelector('.sleek-chart-stage--home-search'); 5003 if (stage && typeof ET.clearSleekChartStageHoverDom === 'function') { 5004 ET.clearSleekChartStageHoverDom(stage); 5005 } 5006 clearSearchChartCanvas(); 5007 } 5008 5009 function clearSearchChartCanvas() { 5010 const c = document.getElementById('searchChart'); 5011 if (!c || !c.getContext) return; 5012 const g = c.getContext('2d'); 5013 if (g) g.clearRect(0, 0, c.width, c.height); 5014 } 5015 5016 function setSearchChartEmptyOverlay(show) { 5017 if (typeof ET.setSearchChartEmptyOverlayVisible === 'function') { 5018 ET.setSearchChartEmptyOverlayVisible(document.getElementById('searchChartEmptyOverlay'), show); 5019 } 5020 } 5021 5022 function hasPollingFor(category, key) { 5023 if (category === '2026-us-senate') { 5024 return !!(ET.senateKeyHasSearchablePolling && ET.senateKeyHasSearchablePolling(key)); 5025 } 5026 if (category === '2026-governors') { 5027 return !!(ET.govKeyHasSearchablePollingLikeSenate && ET.govKeyHasSearchablePollingLikeSenate(key)); 5028 } 5029 if (category === '2026-us-house') { 5030 return !!(ET.gaHouseSlugHasPollingForSearch && ET.gaHouseSlugHasPollingForSearch(key)); 5031 } 5032 return false;
5033 } 5034 5035 function clearDistrictDropdown() { 5036 if (!districtSelect) return; 5037 districtSelect.innerHTML = ''; 5038 var emptyOpt = document.createElement('option'); 5039 emptyOpt.value = ''; 5040 emptyOpt.textContent = ''; 5041 districtSelect.appendChild(emptyOpt); 5042 districtSelect.disabled = true; 5043 districtSelect.value = ''; 5044 } 5045 5046 function syncHomeSearchFilterVisibility(category) { 5047 var filtersEl = document.querySelector('.search-all-polls-filters'); 5048 var districtField = document.getElementById('homeSearchDistrictField'); 5049 var typeEl = document.getElementById('typeSelect'); 5050 var isHouse = category === '2026-us-house'; 5051 if (filtersEl) filtersEl.classList.toggle('search-all-polls-filters--house', isHouse); 5052 if (!isHouse) clearDistrictDropdown(); 5053 if (typeEl) typeEl.disabled = false; 5054 } 5055 5056 function populateDistrictDropdown(st, preferredSlug) { 5057 if (!districtSelect || !ET.gaHouseDistrictOptionsWithPolling) return ''; 5058 var options = ET.gaHouseDistrictOptionsWithPolling(st); 5059 districtSelect.innerHTML = ''; 5060 if (!options.length) { 5061 districtSelect.disabled = true; 5062 return ''; 5063 } 5064 districtSelect.disabled = false; 5065 options.forEach(function (option) { 5066 var el = document.createElement('option'); 5067 el.value = option.value; 5068 el.textContent = option.label; 5069 el.dataset.key = option.key; 5070 districtSelect.appendChild(el); 5071 }); 5072 var slug = preferredSlug; 5073 if (!slug || !options.some(function (o) { return o.key === slug; })) { 5074 slug = ET.gaHouseLowestPollingSlugForState 5075 ? ET.gaHouseLowestPollingSlugForState(st) 5076 : options[0].key; 5077 } 5078 if (slug && options.some(function (o) { return o.key === slug; })) { 5079 districtSelect.value = slug; 5080 } else { 5081 districtSelect.value = options[0].value; 5082 } 5083 return districtSelect.value; 5084 } 5085 5086 function populateHouseSearchDropdowns(priorStateKey, preferredSlug) { 5087 syncHomeSearchFilterVisibility('2026-us-house'); 5088 var yearSel = document.getElementById('yearSelect'); 5089 if (yearSel) yearSel.value = '2026'; 5090 if (typeof ET.gaSyncHomeSearchYearToRace === 'function') { 5091 ET.gaSyncHomeSearchYearToRace(yearSel, '2026-us-house'); 5092 } 5093 categorySelect.dataset.pmPrevHomeSearchCat = '2026-us-house'; 5094 5095 var states = ET.gaHouseStateOptionsWithPolling ? ET.gaHouseStateOptionsWithPolling() : []; 5096 entitySelect.innerHTML = ''; 5097 if (!states.length) { 5098 entitySelect.disabled = true; 5099 clearDistrictDropdown(); 5100 disposeSearchChartInstance(); 5101 ctx = refreshSearchChartCanvas(); 5102 entityLink.textContent = 'â'; 5103 entityLink.innerHTML = 'â'; 5104 entityLink.href = '#'; 5105 if (entityArrow) entityArrow.href = '#'; 5106 document.getElementById('searchTable').innerHTML = ''; 5107 return; 5108 } 5109 entitySelect.disabled = false; 5110 states.forEach(function (option) { 5111 var el = document.createElement('option'); 5112 el.value = option.value; 5113 el.textContent = option.label; 5114 el.dataset.key = option.key; 5115 entitySelect.appendChild(el); 5116 }); 5117 5118 var stPick = null; 5119 if (preferredSlug && ET.gaHouseRaceFromSlug) { 5120 var prefRace = ET.gaHouseRaceFromSlug(preferredSlug); 5121 if (prefRace && prefRace.st) stPick = prefRace.st; 5122 } 5123 if (!stPick && priorStateKey && ET.gaHouseLowestPollingSlugForState && 5124 ET.gaHouseLowestPollingSlugForState(priorStateKey)) { 5125 stPick = priorStateKey; 5126 } 5127 if (!stPick) { 5128 var defaultSlug = ET.gaHouseHomeSearchDefaultSlug 5129 ? ET.gaHouseHomeSearchDefaultSlug(null) 5130 : 'alaska-at-large'; 5131 var defaultRace = ET.gaHouseRaceFromSlug && ET.gaHouseRaceFromSlug(defaultSlug); 5132 stPick = defaultRace ? defaultRace.st : states[0].key; 5133 } 5134 if (stPick) { 5135 for (var si = 0; si < states.length; si++) { 5136 if (states[si].key === stPick) { 5137 entitySelect.value = states[si].value; 5138 break; 5139 } 5140 } 5141 } 5142 if (!entitySelect.value) entitySelect.value = states[0].value; 5143 5144 var stKey = entitySelect.options[entitySelect.selectedIndex].dataset.key; 5145 var slugPick = preferredSlug; 5146 if (!slugPick || !ET.gaHouseSlugHasPollingForSearch || !ET.gaHouseSlugHasPollingForSearch(slugPick)) { 5147 slugPick = ET.gaHouseHomeSearchDefaultSlug 5148 ? ET.gaHouseHomeSearchDefaultSlug(priorStateKey) 5149 : null; 5150 } 5151 populateDistrictDropdown(stKey, slugPick); 5152 5153 var slugForType = districtSelect && districtSelect.value ? districtSelect.value : slugPick; 5154 syncSearchPollTypeOptions('2026-us-house', slugForType, { initialType: 'general-election' }); 5155 var tsHouse = document.getElementById('typeSelect'); 5156 if (tsHouse) tsHouse.value = 'general-election'; 5157 render(); 5158 } 5159 5160 function homeSearch2028PrimaryTitle(electionType) { 5161 var labels = ET.gaSearchPollTypeLabels || {}; 5162 return labels[electionType || 'dem-primary'] || 'Democratic Primary'; 5163 } 5164 5165 function homeSearch2028PartyTint(electionType) { 5166 return (electionType || 'dem-primary') === 'dem-primary' ? 'D' : 'R'; 5167 } 5168 5169 function layoutSearchPollHeaderFlag() { 5170 var wrap = document.getElementById('searchPollFlagWrap'); 5171 var img = document.getElementById('searchPollFlagImg'); 5172 var trend = document.getElementById('trendLabel'); 5173 var entity = document.getElementById('entityLink'); 5174 var row = document.querySelector('.search-poll-head-text-row'); 5175 if (!wrap || !img || !trend || !entity) return; 5176 if (!wrap.classList.contains('is-visible')) return; 5177 var searchSec = document.getElementById('searchAllPollsSection'); 5178 var isHomeSearch = !!(searchSec && searchSec.contains(wrap)); 5179 var isMobile = typeof ET !== 'undefined' && typeof ET.isMobileLayout === 'function' 5180 ? ET.isMobileLayout() 5181 : (window.matchMedia && window.matchMedia('(max-width: 767px)').matches); 5182 /* Mobile Search All Polls: CSS reserves flag size â skip measure to avoid CLS. */ 5183 if (isHomeSearch && isMobile) { 5184 wrap.style.marginTop = ''; 5185 img.style.height = ''; 5186 img.style.width = ''; 5187 return; 5188 } 5189 /* Reset before measuring â inflated flag margin + flex-end was creating a ~1600px feedback loop on mobile */ 5190 wrap.style.marginTop = '0'; 5191 var rt = trend.getBoundingClientRect(); 5192 var re = entity.getBoundingClientRect(); 5193 var trendTopNudge = parseFloat(getComputedStyle(trend).top); 5194 if (!isFinite(trendTopNudge)) trendTopNudge = 0; 5195 var stateHeading = entity.closest('h3') || entity; 5196 var entityTopNudge = parseFloat(getComputedStyle(stateHeading).top); 5197 if (!isFinite(entityTopNudge)) entityTopNudge = 0; 5198 /* Flag geometry uses flow positions (ignore relative `top` nudges) so text moves 5199 visually vs the flag instead of the flag chasing every nudge. */ 5200 var trendTopFlow = rt.top - trendTopNudge; 5201 var entityTopFlow = re.top - entityTopNudge; 5202 var entityBottomFlow = re.bottom - entityTopNudge; 5203 /* Slightly shorter than eyebrow â state text span; width follows aspect ratio */ 5204 var h = Math.round(entityBottomFlow - trendTopFlow) - 2; 5205 if (isHomeSearch) { 5206 var stateLinePx = 28; 5207 try { 5208 var v = parseFloat(getComputedStyle(searchSec).getPropertyValue('--search-poll-flag-state-line-px')); 5209 if (isFinite(v) && v > 0) stateLinePx = v; 5210 } catch (eFlag) { /* ignore */ } 5211 h = Math.round(entityTopFlow - trendTopFlow) + stateLinePx - 2; 5212 } 5213 if (h < 2) h = 2; 5214 img.style.height = h + 'px'; 5215 img.style.width = 'auto'; 5216 if (row) { 5217 var flowOffsetTop = Math.max(0, trend.offsetTop - trendTopNudge); 5218 var topPad = flowOffsetTop + 1; 5219 if (topPad > 48) { 5220 topPad = 1; 5221 } 5222 wrap.style.marginTop = (topPad + 2) + 'px'; 5223 } 5224 } 5225 5226 function scheduleLayoutSearchPollHeaderFlag() { 5227 requestAnimationFrame(function () { 5228 requestAnimationFrame(layoutSearchPollHeaderFlag); 5229 }); 5230 } 5231 5232 function updateSearchPollHeadVisual(stateKey, partyTint) { 5233 var wrap = document.getElementById('searchPollFlagWrap'); 5234 var img = document.getElementById('searchPollFlagImg'); 5235 if (!wrap || !img) return; 5236 img.onload = null; 5237 wrap.classList.remove('is-party-logo'); 5238 if (partyTint === 'R' || partyTint === 'D') { 5239 wrap.classList.add('is-visible', 'is-party-logo'); 5240 img.onload = function () { scheduleLayoutSearchPollHeaderFlag(); }; 5241 img.src = partyTint === 'R' ? '/images/gop.webp' : '/images/dem.webp'; 5242 img.alt = partyTint === 'R' ? 'Republican Party' : 'Democratic Party'; 5243 if (img.complete) scheduleLayoutSearchPollHeaderFlag(); 5244 return; 5245 } 5246 if (stateKey === 'U.S.') { 5247 wrap.classList.add('is-visible'); 5248 img.onload = function () { scheduleLayoutSearchPollHeaderFlag(); }; 5249 img.src = '/images/usa.webp'; 5250 img.alt = 'United States'; 5251 if (img.complete) scheduleLayoutSearchPollHeaderFlag(); 5252 return; 5253 } 5254 if (!stateKey || typeof stateKey !== 'string' || stateKey.length !== 2) { 5255 wrap.classList.remove('is-visible'); 5256 img.style.height = ''; 5257 img.style.width = ''; 5258 wrap.style.marginTop = ''; 5259 return; 5260 } 5261 wrap.classList.add('is-visible'); 5262 img.onload = function () { scheduleLayoutSearchPollHeaderFlag(); }; 5263 img.src = '/images/' + stateKey.toLowerCase() + '.webp'; 5264 img.alt = ''; 5265 if (img.complete) scheduleLayoutSearchPollHeaderFlag(); 5266 } 5267 5268 if (!searchPollFlagResizeBound) { 5269 searchPollFlagResizeBound = true; 5270 window.addEventListener('resize', function () { scheduleLayoutSearchPollHeaderFlag(); }); 5271 } 5272 5273 function populateEntityDropdown(category, preferredKey, useAlphabeticalDefault) { 5274 syncHomeSearchFilterVisibility(category); 5275 if (typeof ET.gaSyncHomeSearchYearToRace === 'function') { 5276 ET.gaSyncHomeSearchYearToRace(document.getElementById('yearSelect'), category); 5277 } 5278 if (category === '2028-election' || category === 'approval-trump' || category === 'approval-generic') { 5279 entitySelect.innerHTML = ''; 5280 var natOpt = document.createElement('option'); 5281 natOpt.value = 'national'; 5282 natOpt.textContent = 'National'; 5283 natOpt.dataset.key = 'U.S.'; 5284 entitySelect.appendChild(natOpt); 5285 entitySelect.disabled = false;
5286 entitySelect.value = 'national'; 5287 var ts2028 = document.getElementById('typeSelect'); 5288 if (ts2028 && typeof ET.gaFillSearchTypeSelect === 'function') { 5289 var prevCat = categorySelect.dataset.pmPrevHomeSearchCat || ''; 5290 var preserve2028Type = (prevCat === '2028-election') ? ts2028.value : null; 5291 var ts2028Opts = { preserveValue: preserve2028Type }; 5292 if (!preserve2028Type) { 5293 ts2028Opts.initialType = category === '2028-election' ? 'dem-primary' : 'general-election'; 5294 } 5295 ET.gaFillSearchTypeSelect(ts2028, category, 'U.S.', ts2028Opts); 5296 } 5297 if (category === 'approval-trump' && 5298 !(ET.TRUMP_APPROVAL_ISSUES && ET.TRUMP_APPROVAL_ISSUES.length) && 5299 typeof window.pollsmaxEnsureTrumpIssuePolls === 'function') { 5300 Promise.resolve(window.pollsmaxEnsureTrumpIssuePolls('general-election')).then(function () { 5301 var tsReload = document.getElementById('typeSelect'); 5302 if (tsReload && typeof ET.gaFillSearchTypeSelect === 'function') { 5303 ET.gaFillSearchTypeSelect(tsReload, 'approval-trump', 'U.S.', { 5304 preserveValue: tsReload.value || 'general-election' 5305 }); 5306 } 5307 scheduleSearchRender(); 5308 }); 5309 } 5310 categorySelect.dataset.pmPrevHomeSearchCat = category; 5311 render(); 5312 return; 5313 } 5314 if (category === '2026-us-house') { 5315 var priorCat = categorySelect.dataset.pmPrevHomeSearchCat || ''; 5316 var priorStateKey = null; 5317 if (priorCat === '2026-us-senate' || priorCat === '2026-governors') { 5318 var priorOpt = entitySelect.options[entitySelect.selectedIndex]; 5319 priorStateKey = priorOpt ? priorOpt.dataset.key : null; 5320 } 5321 var housePreferredSlug = preferredKey; 5322 if (housePreferredSlug && housePreferredSlug.length === 2 && ET.gaHouseHomeSearchDefaultSlug) { 5323 housePreferredSlug = ET.gaHouseHomeSearchDefaultSlug(housePreferredSlug); 5324 } 5325 if (typeof ET.ensureHomeHouseSearchDataLoaded === 'function') { 5326 ET.ensureHomeHouseSearchDataLoaded(function () { 5327 populateHouseSearchDropdowns(priorStateKey, housePreferredSlug); 5328 }); 5329 } 5330 return; 5331 } 5332 categorySelect.dataset.pmPrevHomeSearchCat = category; 5333 entitySelect.innerHTML = ''; 5334 const options = category === '2026-us-senate' ? senateEntityOptions() : governorEntityOptions(); 5335 5336 if (options.length === 0) { 5337 disposeSearchChartInstance(); 5338 ctx = refreshSearchChartCanvas(); 5339 ensureSearchChartStageHeight(); 5340 entitySelect.disabled = true; 5341 entityLink.textContent = 'â'; 5342 entityLink.href = '#'; 5343 if (entityArrow) entityArrow.href = '#'; 5344 updateSearchPollHeadVisual(null, null); 5345 document.getElementById('searchTable').innerHTML = ''; 5346 return; 5347 } 5348 5349 entitySelect.disabled = false; 5350 options.forEach(option => { 5351 const optionElement = document.createElement('option'); 5352 optionElement.value = option.value; 5353 optionElement.textContent = option.text; 5354 optionElement.dataset.key = option.key; 5355 if (!hasPollingFor(category, option.key)) optionElement.style.color = '#64748b'; 5356 entitySelect.appendChild(optionElement); 5357 }); 5358 5359 var selected = null; 5360 if (preferredKey) { 5361 var matched = options.find(function (o) { return o.key === preferredKey; }); 5362 if (matched) selected = matched; 5363 } 5364 if (!selected && useAlphabeticalDefault) { 5365 var searchDefaultKey = category === '2026-us-senate' ? 'MI' : (category === '2026-governors' ? 'OH' : null); 5366 if (searchDefaultKey) { 5367 selected = options.find(function (o) { return o.key === searchDefaultKey; }) || null; 5368 } 5369 if (!selected) selected = options[0]; 5370 } 5371 if (!selected) selected = options[0]; 5372 entitySelect.value = selected.value; 5373 if (category === '2026-governors' && (selected.key === 'CA' || selected.key === 'AK')) { 5374 syncSearchPollTypeOptions(category, selected.key, { preferGovOpenPrimary: true }); 5375 } 5376 render(); 5377 } 5378 5379 function syncSearchPollTypeOptions(category, stateKey, syncOpts) { 5380 var ts = document.getElementById('typeSelect'); 5381 if (!ts) return; 5382 var prev = ts.value; 5383 if (typeof ET.gaFillSearchTypeSelect === 'function') { 5384 var fillOpts = { preserveValue: prev }; 5385 if (syncOpts && syncOpts.preferGovOpenPrimary) { 5386 fillOpts.preferGovOpenPrimary = true; 5387 } 5388 if (syncOpts && syncOpts.initialType) { 5389 fillOpts.initialType = syncOpts.initialType; 5390 } 5391 ET.gaFillSearchTypeSelect(ts, category, stateKey, fillOpts); 5392 } 5393 } 5394 5395 var _searchRenderRaf = 0; 5396 function scheduleSearchRender() { 5397 if (_searchRenderRaf) return; 5398 _searchRenderRaf = requestAnimationFrame(function () { 5399 _searchRenderRaf = 0; 5400 render(); 5401 }); 5402 } 5403 5404 function searchNeedsPrimaryHubDeps(category, tVal) { 5405 if (category === '2028-election') return true; 5406 if (!tVal || tVal === 'general-election' || tVal === 'open-primary') return false;
5407 return true; 5408 } 5409 5410 function searchPrimaryHubDepsReady() { 5411 return !!(ET.PRIMARY_HUB_BUNDLES && 5412 ET.PRIMARY_HUB_BUNDLES['2028-republican-primary'] && 5413 typeof ET.resolvePrimaryHubBundle === 'function' && 5414 typeof ET.renderPrimaryHubChart === 'function'); 5415 } 5416 5417 function ensureSearchPrimaryHubDepsThenRender() { 5418 if (window.__pollsmaxSearchPrimaryDepsLoading) return; 5419 window.__pollsmaxSearchPrimaryDepsLoading = true; 5420 var done = function () { 5421 window.__pollsmaxSearchPrimaryDepsLoading = false; 5422 scheduleSearchRender(); 5423 }; 5424 if (typeof window.pollsmaxEnsureHomeSearchPrimaryDeps === 'function') { 5425 Promise.resolve(window.pollsmaxEnsureHomeSearchPrimaryDeps()).then(done).catch(done); 5426 } else { 5427 done(); 5428 } 5429 } 5430 5431 function render() { 5432 ctx = document.getElementById('searchChart'); 5433 const category = categorySelect.value; 5434 var is2028 = category === '2028-election'; 5435 var isApproval = category === 'approval-trump' || category === 'approval-generic'; 5436 var isHouse = category === '2026-us-house'; 5437 if (!is2028 && !isApproval && !isHouse && (!entitySelect.options.length || entitySelect.selectedIndex < 0)) return; 5438 if (isHouse && (!districtSelect || !districtSelect.value)) return; 5439 5440 const selectedOption = entitySelect.options[entitySelect.selectedIndex]; 5441 var houseSlug = isHouse && districtSelect ? districtSelect.value : null; 5442 var houseRace = isHouse && houseSlug && ET.gaHouseRaceFromSlug 5443 ? ET.gaHouseRaceFromSlug(houseSlug) 5444 : null; 5445 if (isHouse && houseSlug && ET.HOUSE_BY_SLUG && ET.HOUSE_BY_SLUG[houseSlug]) { 5446 houseRace = ET.HOUSE_BY_SLUG[houseSlug]; 5447 } 5448 const key = (is2028 || isApproval) ? 'U.S.' : (isHouse ? houseSlug : selectedOption.dataset.key); 5449 syncSearchPollTypeOptions(category, key); 5450 const entity = (is2028 || isApproval) ? 'national' : (isHouse ? houseSlug : entitySelect.value); 5451 var tsForTitle = document.getElementById('typeSelect'); 5452 var tValEarly = (tsForTitle && tsForTitle.value) ? tsForTitle.value : (is2028 ? 'dem-primary' : 'general-election'); 5453 const entityName = is2028 5454 ? homeSearch2028PrimaryTitle(tValEarly) 5455 : (isApproval 5456 ? (category === 'approval-trump' ? 'Trump Approval' : 'Generic Ballot') 5457 : (isHouse && houseRace ? houseRace.state : selectedOption.textContent)); 5458 5459 var ts = document.getElementById('typeSelect'); 5460 var tVal = (ts && ts.value) ? ts.value : (is2028 ? 'dem-primary' : 'general-election'); 5461 5462 if (searchNeedsPrimaryHubDeps(category, tVal) && !searchPrimaryHubDepsReady()) { 5463 ensureSearchPrimaryHubDepsThenRender(); 5464 return; 5465 } 5466 5467 var renderFp = category + '|' + key + '|' + tVal + '|' + (houseSlug || ''); 5468 if (window.__pollsmaxSearchRenderFp === renderFp && chart && 5469 document.getElementById('searchChart')) { 5470 return; 5471 } 5472 5473 var nextKind = (tVal !== 'general-election' || is2028) ? 'primary' 5474 : (isApproval ? 'approval' : 'ge'); 5475 var prevKind = window.__pollsmaxSearchChartKind || ''; 5476 var forceClone = !!(prevKind && prevKind !== nextKind); 5477 5478 disposeSearchChartInstance(); 5479 ctx = refreshSearchChartCanvas(forceClone); 5480 if (forceClone && ctx) ctx.dataset.pmChartNavBound = ''; 5481 ensureSearchChartStageHeight(); 5482 window.__pollsmaxSearchChartKind = nextKind; 5483 5484 let entityUrl = '#'; 5485 if ((is2028 || isApproval) && typeof ET.gaHeaderSearchDest === 'function') { 5486 entityUrl = ET.gaHeaderSearchDest( 5487 category, 5488 'national', 5489 (is2028 || category === 'approval-trump') ? tVal : null 5490 ) || '#'; 5491 } else if (typeof ET.gaSearchChartPollsPageUrl === 'function' && key) { 5492 entityUrl = ET.gaSearchChartPollsPageUrl(category, key, tVal); 5493 } else if (typeof ET.gaPollsPageUrlForSelection === 'function' && key) { 5494 entityUrl = ET.gaPollsPageUrlForSelection(category, key, tVal); 5495 } else if (category === '2026-us-senate') { 5496 entityUrl = '/state/' + (ET.SLUG_BY_KEY && ET.SLUG_BY_KEY[key] ? ET.SLUG_BY_KEY[key] : String(entity).toLowerCase()) + '/'; 5497 } else if (category === '2026-governors') { 5498 entityUrl = '/governor/' + entity + '/'; 5499 } else if (category === '2026-us-house' && houseRace && houseRace.url) { 5500 entityUrl = houseRace.url; 5501 } 5502 5503 if (isApproval && trendLabel) { 5504 trendLabel.classList.remove('search-poll-eyebrow-2028'); 5505 trendLabel.style.color = '#94a3b8'; 5506 trendLabel.href = entityUrl; 5507 if (category === 'approval-trump') { 5508 trendLabel.textContent = 'JOB APPROVAL'; 5509 var trumpIssueSearch = (tVal && tVal !== 'general-election' && 5510 typeof ET.trumpApprovalIssueByTypeKey === 'function') 5511 ? ET.trumpApprovalIssueByTypeKey(tVal) 5512 : null; 5513 entityLink.textContent = trumpIssueSearch 5514 ? ('Donald Trump â ' + trumpIssueSearch.shortName) 5515 : 'Donald Trump'; 5516 } else { 5517 trendLabel.textContent = '2026 MIDTERMS'; 5518 entityLink.textContent = 'Generic Congressional Ballot'; 5519 } 5520 } else { 5521 if (trendLabel && typeof ET.gaApplySearchHubTrendEyebrow === 'function') { 5522 ET.gaApplySearchHubTrendEyebrow(trendLabel, category, key, tVal); 5523 } 5524 if (is2028 && trendLabel) { 5525 trendLabel.classList.add('search-poll-eyebrow-2028'); 5526 trendLabel.style.color = '#94a3b8'; 5527 trendLabel.textContent = '2028 PRESIDENT'; 5528 } else if (trendLabel) { 5529 trendLabel.classList.remove('search-poll-eyebrow-2028'); 5530 } 5531 if (isHouse && houseRace && typeof ET.gaHouseDistrictHeaderLabelHtml === 'function') { 5532 entityLink.innerHTML = ET.gaHouseDistrictHeaderLabelHtml(houseRace); 5533 } else if (!isApproval) { 5534 entityLink.textContent = entityName; 5535 } 5536 } 5537 entityLink.href = entityUrl; 5538 if (entityArrow) entityArrow.href = entityUrl; 5539 updateSearchPollHeadVisual( 5540 isApproval ? 'U.S.' : (is2028 ? null : (isHouse && houseRace ? houseRace.st : key)), 5541 is2028 ? homeSearch2028PartyTint(tVal) : null 5542 ); 5543 if (ctx) ctx.style.cursor = 'pointer'; 5544 5545 const ul = document.getElementById('searchTable'); 5546 5547 var hubB = 5548 tVal !== 'general-election' && ET.resolvePrimaryHubBundle 5549 ? ET.resolvePrimaryHubBundle(category, key, tVal) 5550 : null; 5551 var govOpenPrimary = 5552 tVal === 'open-primary' && category === '2026-governors' && 5553 ET.GOV_OPEN_PRIMARY_ROUTES && ET.GOV_OPEN_PRIMARY_ROUTES[key]; 5554 5555 if (hubB) { 5556 chart = null; 5557 if (ET.renderPrimaryHubChart) { 5558 try { 5559 chart = ET.renderPrimaryHubChart(ctx, hubB, homeSearchChartOpts({ 5560 lineChartSinglePoll: true, 5561 lightChartLabels: true, 5562 expandPlotLT: 3, 5563 hubNavigateRacePage: true, 5564 skipChartWhenNoPolls: true, 5565 primary2028DotAlpha: is2028 ? 0.12 : undefined, 5566 sleekHover2028HeaderExtraDown: is2028 ? 22 : undefined, 5567 search2028HoverTopFive: is2028 ? true : undefined 5568 })); 5569 } catch (eHub) { 5570 chart = null; 5571 } 5572 } 5573 if (!chart && ET.renderStateChart && ctx && typeof ctx.getContext === 'function') { 5574 try { 5575 chart = ET.renderStateChart(ctx.getContext('2d'), key, homeSearchChartOpts({ 5576 lineChartSinglePoll: true, 5577 lightChartLabels: true, 5578 expandPlotLT: 3, 5579 hubNavigateRacePage: true, 5580 skipChartWhenNoPolls: true, 5581 hubPrimaryElectionType: tVal, 5582 hubCategory: category, 5583 useGovernorSeries: category === '2026-governors' 5584 })); 5585 } catch (eHub2) { 5586 chart = null; 5587 } 5588 } 5589 if (chart) { 5590 chart._etHubPrimaryElectionType = tVal; 5591 chart._etSleekHoverLabelFontSize = 15; 5592 chart._etSleekHoverLabelFontWeight = 500; 5593 if (is2028) { 5594 chart._etSleekHoverLabelAlignDotCenter = true; 5595 chart._etSleekHoverPairOverlapNudge = false;
5596 chart._etSleekHoverLabelLineGap = 6; 5597 chart._etSleekHoverLabelSepTight = 1; 5598 chart._etSleekHover2028PaletteRing = true; 5599 chart._etSleekHover2028LabelPctSuffix = true; 5600 chart._etSleekHoverLabelYOffset = 0; 5601 } else { 5602 chart._etSleekHoverLabelYOffset = 1; 5603 } 5604 chart._etSleekHoverPointRadius = searchAllPollsHoverDotRadius(); 5605 applySearchAllPollsMobileHoverDotSize(chart); 5606 if (chart.update) chart.update('none'); 5607 } 5608 var nHub = ET.fillPrimaryHubPollList ? ET.fillPrimaryHubPollList(ul, hubB, entityUrl) : 0; 5609 setSearchPollSidebarListHeight(ul, nHub); 5610 } else if (govOpenPrimary && ET.renderGovHubOpenPrimarySearchChart) { 5611 var opSeries = key === 'CA' 5612 ? (ET.govCaOpenPrimarySeries && ET.govCaOpenPrimarySeries()) 5613 : (ET.govAkOpenPrimarySeries && ET.govAkOpenPrimarySeries()); 5614 if (opSeries && opSeries.length) { 5615 try { 5616 chart = ET.renderGovHubOpenPrimarySearchChart(ctx, key, homeSearchChartOpts({ 5617 lineChartSinglePoll: true, 5618 lightChartLabels: true, 5619 expandPlotLT: 3, 5620 hubNavigateRacePage: true, 5621 skipChartWhenNoPolls: true, 5622 blankSinglePoll: false, 5623 stateKey: key 5624 }), opSeries); 5625 } catch (eGovOp) { 5626 chart = null; 5627 } 5628 } 5629 if (chart) { 5630 chart._etHubPrimaryElectionType = 'open-primary'; 5631 chart._etSleekHoverLabelFontSize = 15; 5632 chart._etSleekHoverLabelFontWeight = 500; 5633 chart._etSleekHoverLabelYOffset = 1; 5634 chart._etSleekHoverPointRadius = searchAllPollsHoverDotRadius(); 5635 applySearchAllPollsMobileHoverDotSize(chart); 5636 if (chart.update) chart.update('none'); 5637 } 5638 var nGovOp = ET.fillGovOpenPrimaryHubPollList 5639 ? ET.fillGovOpenPrimaryHubPollList(ul, key, entityUrl) 5640 : 0; 5641 setSearchPollSidebarListHeight(ul, nGovOp); 5642 } else if (isApproval) { 5643 if (category === 'approval-trump' && tVal && tVal !== 'general-election' && 5644 typeof window.pollsmaxEnsureTrumpIssuePolls === 'function') { 5645 var issueReady = typeof ET.trumpApprovalIssueByTypeKey === 'function' 5646 ? ET.trumpApprovalIssueByTypeKey(tVal) 5647 : null; 5648 var issuePollsReady = issueReady && window[issueReady.pollsGlobal] && 5649 window[issueReady.pollsGlobal].length; 5650 if (!issuePollsReady) { 5651 if (!window.__pollsmaxSearchTrumpIssueLoading) { 5652 window.__pollsmaxSearchTrumpIssueLoading = true; 5653 Promise.resolve(window.pollsmaxEnsureTrumpIssuePolls(tVal)).then(function () { 5654 window.__pollsmaxSearchTrumpIssueLoading = false; 5655 window.__pollsmaxSearchRenderFp = ''; 5656 scheduleSearchRender(); 5657 }).catch(function () { 5658 window.__pollsmaxSearchTrumpIssueLoading = false; 5659 }); 5660 } 5661 return; 5662 } 5663 } 5664 var trumpIssueForChart = (category === 'approval-trump' && tVal && tVal !== 'general-election' && 5665 typeof ET.trumpApprovalIssueByTypeKey === 'function') 5666 ? ET.trumpApprovalIssueByTypeKey(tVal) 5667 : null; 5668 var approvalPolls = category === 'approval-trump' 5669 ? (trumpIssueForChart && window[trumpIssueForChart.pollsGlobal] 5670 ? window[trumpIssueForChart.pollsGlobal] 5671 : window.TRUMP_APPROVAL_POLLS) 5672 : window.GENERIC_BALLOT_POLLS; 5673 if (category === 'approval-trump' && typeof window.pollsmaxInitTrumpApprovalHomeChart === 'function') { 5674 chart = window.pollsmaxInitTrumpApprovalHomeChart(homeSearchChartOpts({ 5675 canvasId: 'searchChart', 5676 navigateOnClick: false, 5677 polls: approvalPolls 5678 })); 5679 } else if (category === 'approval-generic' && typeof window.pollsmaxInitGenericBallotHomeChart === 'function') { 5680 chart = window.pollsmaxInitGenericBallotHomeChart(homeSearchChartOpts({ 5681 canvasId: 'searchChart', 5682 navigateOnClick: false 5683 })); 5684 } 5685 if (chart) { 5686 chart._etSleekHoverLabelFontSize = 15; 5687 chart._etSleekHoverLabelFontWeight = 500; 5688 chart._etSleekHoverHeaderYOffset = SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX; 5689 chart._etSleekHoverLabelYOffset = 1; 5690 chart._etSleekHoverDateFontSize = 11; 5691 chart._etSleekHoverChipScale = SEARCH_ALL_POLLS_CHART_CHIP_SCALE; 5692 chart._etSleekHoverPointRadius = searchAllPollsHoverDotRadius(); 5693 applySearchAllPollsMobileHoverDotSize(chart); 5694 if (chart.update) chart.update('none'); 5695 } 5696 createApprovalPollsList(ul, approvalPolls, category); 5697 } else if (tVal !== 'general-election') { 5698 /* Primary selected but no hub bundle â do not show general-election chart/list. */ 5699 ul.innerHTML = ''; 5700 setSearchPollSidebarListHeight(ul, 0); 5701 } else if (category === '2026-us-senate') {
5702 const series = (ET.SENATE && ET.SENATE[key]) || []; 5703 if (series.length >= 1) { 5704 try { 5705 chart = createCustomChart(ctx, series, ET.candName(key, 'D'), ET.candName(key, 'R'), true, { blankSinglePoll: false, stateKey: key }); 5706 } catch (e2) { 5707 chart = null; 5708 } 5709 } 5710 if (series.length >= 1) { 5711 createCustomPollsList(ul, series, ET.candName(key, 'D'), ET.candName(key, 'R'), key); 5712 } else { 5713 ul.innerHTML = ''; 5714 } 5715 } else if (category === '2026-governors') { 5716 var gLoc = (ET.govSeriesWithLocalFallback && ET.govSeriesWithLocalFallback(key)) || []; 5717 const series = (gLoc.length >= 1) ? gLoc : ET.govSeries(key); 5718 const govChartOpts = Object.assign({}, govSearchPollOpts, { stateKey: key }); 5719 5720 if (series && series.length >= 1) { 5721 const dName = ET.govCandName(key, 'D'); 5722 const rName = ET.govCandName(key, 'R'); 5723 var chartSeries = series; 5724 if (key === 'MI' && ET.govMiSeriesHeadToHead) { 5725 chartSeries = ET.govMiSeriesHeadToHead(series); 5726 } else if (key === 'CA' && ET.caGovPartyTotalSeries) { 5727 chartSeries = ET.caGovPartyTotalSeries(series); 5728 } 5729 chart = createCustomChart(ctx, chartSeries, dName, rName, false, govChartOpts); 5730 } 5731 5732 if (series && series.length) { 5733 var listSeries = series; 5734 if (key === 'MI' && ET.govMiSeriesHeadToHead) { 5735 listSeries = ET.govMiSeriesHeadToHead(series); 5736 } 5737 createCustomPollsList(ul, listSeries, ET.govCandName(key, 'D'), ET.govCandName(key, 'R'), key, 'gov'); 5738 } else if (typeof ET.fillGovSearchNoPollSidebarRow === 'function') { 5739 ET.fillGovSearchNoPollSidebarRow(ul, key); 5740 } else { 5741 ul.innerHTML = ''; 5742 } 5743 } else if (category === '2026-us-house' && houseRace) { 5744 var houseBlock = typeof ET.renderHomeHouseSearchBlock === 'function' 5745 ? ET.renderHomeHouseSearchBlock(ctx, ul, houseRace, { 5746 entityUrl: entityUrl, 5747 chartOpts: homeSearchChartOpts({ 5748 lineChartSinglePoll: true, 5749 lightChartLabels: true, 5750 expandPlotLT: 3, 5751 hubNavigateRacePage: true, 5752 skipChartWhenNoPolls: true, 5753 blankSinglePoll: false 5754 }) 5755 }) 5756 : null; 5757 chart = houseBlock && houseBlock.chart ? houseBlock.chart : null; 5758 if (houseBlock && houseBlock.count) { 5759 setSearchPollSidebarListHeight(ul, houseBlock.count); 5760 } else if (!houseBlock || !houseBlock.count) { 5761 ul.innerHTML = ''; 5762 setSearchPollSidebarListHeight(ul, 0); 5763 } 5764 if (chart) { 5765 chart._etSleekHoverLabelFontSize = 15; 5766 chart._etSleekHoverLabelFontWeight = 500; 5767 chart._etSleekHoverHeaderYOffset = SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX; 5768 chart._etSleekHoverLabelYOffset = 1; 5769 chart._etSleekHoverDateFontSize = 11; 5770 chart._etSleekHoverChipScale = SEARCH_ALL_POLLS_CHART_CHIP_SCALE; 5771 chart._etSleekHoverPointRadius = searchAllPollsHoverDotRadius(); 5772 applySearchAllPollsMobileHoverDotSize(chart); 5773 if (chart.update) chart.update('none'); 5774 } 5775 } 5776 5777 var hasListLi = ul && ul.querySelector && ul.querySelector('li'); 5778 var priSer = !!(hubB && hubB.series && hubB.series.length) ||
5779 !!(govOpenPrimary && ET.govCaOpenPrimarySeries && ET.govAkOpenPrimarySeries && 5780 ((key === 'CA' && ET.govCaOpenPrimarySeries().length) || 5781 (key === 'AK' && ET.govAkOpenPrimarySeries().length))) || 5782 !!(isHouse && houseRace && houseRace.series && houseRace.series.length); 5783 if (!chart) { 5784 clearSearchChartCanvas(); 5785 } 5786 setSearchChartEmptyOverlay(!chart && !hasListLi && !priSer); 5787 5788 Array.from(ul.children).forEach(li => { 5789 if (li.tagName === 'LI' && li.getAttribute('data-pm-primary-hub-nav') === '1') return; 5790 if (li.tagName === 'LI') { 5791 li.style.cursor = 'pointer'; 5792 li.setAttribute('role', 'link'); 5793 li.tabIndex = 0; 5794 li.addEventListener('click', () => { window.location.href = entityUrl; }); 5795 li.addEventListener('keydown', e => { 5796 if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); window.location.href = entityUrl; } 5797 }); 5798 } 5799 }); 5800 5801 if (chart) { 5802 ctx = document.getElementById('searchChart'); 5803 if (ctx) ctx._pollsmaxChartInstance = chart; 5804 applySearchChartMobilePostInit(chart); 5805 if (window.ET && typeof ET.applyPollsmaxHomeSearchAllPollsDesktopHoverHeader === 'function') { 5806 ET.applyPollsmaxHomeSearchAllPollsDesktopHoverHeader(chart, { layoutFlush: true }); 5807 } 5808 bindSearchChartNav(); 5809 scheduleSearchChartResize(chart); 5810 if (typeof ET.scheduleSleekChartHoverAutoplay === 'function') { 5811 ET.scheduleSleekChartHoverAutoplay(chart); 5812 } 5813 } 5814 5815 window.__pollsmaxSearchRenderFp = renderFp; 5816 scheduleLayoutSearchPollHeaderFlag(); 5817 } 5818 window.__pollsmaxHomeSearchPollsRerender = render; 5819 window.__pollsmaxHomeSearchPollsOnFiltersChange = function (cat, useAlphaDefault) { 5820 populateEntityDropdown(cat || categorySelect.value, null, !!useAlphaDefault); 5821 }; 5822 5823 // Event listeners 5824 categorySelect.addEventListener('change', function () { 5825 if (ET.gaSearchCategoryRedirectsAwayFromHome && ET.gaSearchCategoryRedirectsAwayFromHome(this.value)) { 5826 var destNat = ET.gaHeaderSearchDest && ET.gaHeaderSearchDest(this.value, 'national', null); 5827 if (destNat) { 5828 if (typeof ET.gaNavigateToPollsDest === 'function') ET.gaNavigateToPollsDest(destNat); 5829 else window.location.href = destNat; 5830 return; 5831 } 5832 } 5833 const selectedOption = entitySelect.options[entitySelect.selectedIndex]; 5834 const currentKey = selectedOption ? selectedOption.dataset.key : null; 5835 populateEntityDropdown(this.value, currentKey, false); 5836 }); 5837 5838 entitySelect.addEventListener('change', function () { 5839 var cat = categorySelect.value; 5840 var opt = entitySelect.options[entitySelect.selectedIndex]; 5841 var entityKey = opt && opt.dataset.key; 5842 if (cat === '2026-us-house') { 5843 populateDistrictDropdown(entityKey, null); 5844 syncSearchPollTypeOptions(cat, districtSelect.value, { initialType: 'general-election' }); 5845 var tsH = document.getElementById('typeSelect'); 5846 if (tsH) tsH.value = 'general-election'; 5847 scheduleSearchRender(); 5848 return; 5849 } 5850 syncSearchPollTypeOptions(cat, entityKey, { 5851 preferGovOpenPrimary: entityKey === 'CA' || entityKey === 'AK' 5852 }); 5853 scheduleSearchRender(); 5854 }); 5855 5856 if (districtSelect && !districtSelect.dataset.pmSearchDistrictBound) { 5857 districtSelect.dataset.pmSearchDistrictBound = '1'; 5858 districtSelect.addEventListener('change', function () { 5859 if (categorySelect.value !== '2026-us-house') return; 5860 syncSearchPollTypeOptions('2026-us-house', districtSelect.value, { initialType: 'general-election' }); 5861 scheduleSearchRender(); 5862 }); 5863 } 5864 5865 // Initialize from URL (?pm_year=&pm_race=&pm_entity=&pm_type=) or defaults 5866 var pmParams = null; 5867 try { 5868 pmParams = new URLSearchParams(window.location.search); 5869 } catch (ePm) { 5870 pmParams = new URLSearchParams(); 5871 } 5872 var pmYear = pmParams.get('pm_year'); 5873 var pmRace = pmParams.get('pm_race'); 5874 var pmEntity = pmParams.get('pm_entity'); 5875 var pmType = pmParams.get('pm_type'); 5876 var yearSelectEl = document.getElementById('yearSelect'); 5877 var typeSelectEl = document.getElementById('typeSelect'); 5878 if (pmYear && yearSelectEl) { 5879 for (var yI = 0; yI < yearSelectEl.options.length; yI++) { 5880 if (yearSelectEl.options[yI].value === pmYear) { 5881 yearSelectEl.value = pmYear; 5882 break; 5883 } 5884 } 5885 if (typeof ET.gaFillHomeSearchAllPollsRaceOptions === 'function') { 5886 ET.gaFillHomeSearchAllPollsRaceOptions(categorySelect, pmRace || null); 5887 }
5887 else if (typeof ET.gaRefreshHeaderSearchRaceOptions === 'function') { 5888 ET.gaRefreshHeaderSearchRaceOptions(yearSelectEl, categorySelect, pmRace || null, { ignoreYearFilter: true }); 5889 } 5890 } 5891 if (pmRace && ET.gaSearchCategoryRedirectsAwayFromHome && ET.gaSearchCategoryRedirectsAwayFromHome(pmRace)) { 5892 var destPm = ET.gaHeaderSearchDest && ET.gaHeaderSearchDest(pmRace, 'national', pmType); 5893 if (destPm) { 5894 if (typeof ET.gaNavigateToPollsDest === 'function') ET.gaNavigateToPollsDest(destPm); 5895 else if (!ET.gaIsSamePollsDestination || !ET.gaIsSamePollsDestination(destPm)) window.location.replace(destPm); 5896 return; 5897 } 5898 } else if (pmRace) { 5899 categorySelect.value = pmRace; 5900 } 5901 var preservedEntityKey = pmEntity; 5902 if (!preservedEntityKey && window.__pollsmaxMichiganSenatePreviewInit === '1' && 5903 entitySelect && entitySelect.selectedIndex >= 0) { 5904 var previewOpt = entitySelect.options[entitySelect.selectedIndex]; 5905 preservedEntityKey = previewOpt && previewOpt.dataset.key; 5906 } 5907 populateEntityDropdown(categorySelect.value, preservedEntityKey, !preservedEntityKey); 5908 if (pmType && typeSelectEl) { 5909 for (var tI = 0; tI < typeSelectEl.options.length; tI++) { 5910 if (typeSelectEl.options[tI].value === pmType) { 5911 typeSelectEl.value = pmType; 5912 break; 5913 } 5914 } 5915 render(); 5916 } 5917 5918 if (window.location.hash === '#searchAllPollsSection') { 5919 var searchSec = document.getElementById('searchAllPollsSection'); 5920 if (searchSec) { 5921 requestAnimationFrame(function () { 5922 searchSec.scrollIntoView({ behavior: 'auto', block: 'start' }); 5923 }); 5924 } 5925 } 5926 } 5927 5928 function etClearSearchChartWrap(canvasEl) { 5929 try { 5930 const w = (canvasEl && canvasEl.parentNode) || (canvasEl && canvasEl.canvas && canvasEl.canvas.parentNode); 5931 if (!w || !w.style) return; 5932 if (window.ET && typeof ET.isMobileLayout === 'function' && ET.isMobileLayout()) { 5933 w.style.height = '227px'; 5934 w.style.minHeight = '227px'; 5935 } else { 5936 w.style.height = ''; 5937 w.style.minHeight = ''; 5938 } 5939 } catch (e) { } 5940 } 5941 5942 function pollsmaxHomeChartAxisTheme() { 5943 var tick = '#94a3b8'; 5944 var grid = 'rgba(31,41,55,0.45)'; 5945 if (window.ET && typeof ET.chartAxisTheme === 'function') { 5946 tick = ET.chartAxisTheme().tick || tick; 5947 } else { 5948 var T = window.PollsmaxTheme || window.PollsmaxHomeTheme; 5949 if (T && typeof T.chartColors === 'function') { 5950 var ax = T.chartColors(); 5951 tick = ax.tick || tick; 5952 grid = ax.grid || grid; 5953 } 5954 } 5955 /* Same grid as ME senate polling charts. */ 5956 if (window.ET && typeof ET.chartGridBaseColor === 'function') { 5957 grid = ET.chartGridBaseColor(); 5958 } 5959 return { tick: tick, grid: grid, border: grid }; 5960 } 5961 5962 function pollsmaxHomeSearchChartMonthInterval() { 5963 return (window.ET && typeof ET.homeSearchPollChartMonthInterval === 'function') 5964 ? ET.homeSearchPollChartMonthInterval() 5965 : 2; 5966 } 5967 5968 // Custom chart creation function (optional senateMode: use Senate average + partisan adjust) 5969 function createCustomChart(ctx, series, dName, rName, senateMode, opts) { 5970 opts = opts || {}; 5971 if (!ctx || !series || series.length === 0 || !window.Chart) return null; 5972 var homeMobCfg = (window.ET && typeof ET.pollsmaxHomeMobileChartConfig === 'function') 5973 ? ET.pollsmaxHomeMobileChartConfig() 5974 : null; 5975 var lineW = homeMobCfg ? homeMobCfg.lineBorderWidth : 2.5; 5976 var scatterR = homeMobCfg ? Math.max(0.7, 1 * homeMobCfg.scatterPointRadius) : 1; 5977 var scatterHoverR = homeMobCfg ? Math.max(1, 1.5 * homeMobCfg.scatterPointRadius) : 1.5; 5978 var axisTheme = pollsmaxHomeChartAxisTheme(); 5979 if (opts.blankSinglePoll && series.length === 1) { 5980 etClearSearchChartWrap(ctx); 5981 return null; 5982 } 5983 5984 var stateKeySearch = opts.stateKey || null; 5985 var indSenateChart = !!(senateMode && stateKeySearch && ET.isSenateIndGeState && ET.isSenateIndGeState(stateKeySearch)); 5986 var blueLineColor = indSenateChart ? ET.COLORS.IND_GOLD : ET.COLORS.BLUE; 5987 var blueFillColor = indSenateChart ? ET.COLORS.IND_GOLD_FILL : 'rgba(12, 109, 246,0.08)'; 5988 var blueDotColor = indSenateChart ? ET.COLORS.IND_GOLD_DOT : ET.COLORS.BLUE_DOT; 5989 5990 const padBottom = (opts.xAxisExtraBottom != null ? opts.xAxisExtraBottom : 0); 5991 const xTicksPad = (opts.xTicksPadding != null ? opts.xTicksPadding : 2); 5992 var labels = ET.dailyRangeToTodayET(series); 5993 if (senateMode && typeof ET.extendLabelsTo === 'function') { 5994 labels = ET.extendLabelsTo(labels, '2025-10-31'); 5995 } 5996 var avgSeries = series; 5997 if (senateMode && ET.senateSeriesForAverage) { 5998 avgSeries = ET.senateSeriesForAverage(series, stateKeySearch); 5999 } 6000 var senSearchAvgOpts = senateMode ? { statePageAdaptiveRecency: true } : undefined; 6001 const lineD = (senateMode && ET.runningAvgSenateOnLabels) 6002 ? ET.runningAvgSenateOnLabels(avgSeries, 'D', labels, senSearchAvgOpts || {}) 6003 : ET.runningAvgOnLabels(avgSeries, 'D', labels); 6004 const lineR = (senateMode && ET.runningAvgSenateOnLabels) 6005 ? ET.runningAvgSenateOnLabels(avgSeries, 'R', labels, senSearchAvgOpts || {}) 6006 : ET.runningAvgOnLabels(avgSeries, 'R', labels); 6007 6008 // Calculate 1% shading bands (above and below each line) 6009 const lineD_upper = lineD.map(v => v != null ? v + 1 : null); 6010 const lineD_lower = lineD.map(v => v != null ? v - 1 : null); 6011 const lineR_upper = lineR.map(v => v != null ? v + 1 : null); 6012 const lineR_lower = lineR.map(v => v != null ? v - 1 : null); 6013 6014 const vals = []; 6015 lineD.forEach(v => v != null && vals.push(v)); 6016 lineR.forEach(v => v != null && vals.push(v)); 6017 let yMin = (vals.length ? Math.min(...vals) : 45) - 2; 6018 let yMax = (vals.length ? Math.max(...vals) : 55) + 2; 6019 const showBottomAxisLine = Math.abs((yMin / 3) - Math.round(yMin / 3)) < 1e-9; 6020 6021 var chartSearch = new Chart(ctx, { 6022 type: 'line', 6023 data: { 6024 labels, 6025 datasets: [ 6026 // D upper band (for shading above line) 6027 { type: 'line', label: dName + ' Upper', data: lineD_upper, borderColor: 'transparent', backgroundColor: blueFillColor, borderWidth: 0, fill: 1, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6028 // D line 6029 { type: 'line', label: dName, data: lineD, borderColor: blueLineColor, backgroundColor: blueFillColor, borderWidth: lineW, fill: 2, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 2 }, 6030 // D lower band (for shading below line) 6031 { type: 'line', label: dName + ' Lower', data: lineD_lower, borderColor: 'transparent', backgroundColor: blueFillColor, borderWidth: 0, fill: false, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6032 // R upper band (for shading above line) 6033 { type: 'line', label: rName + ' Upper', data: lineR_upper, borderColor: 'transparent', backgroundColor: 'rgba(244, 39, 38,0.08)', borderWidth: 0, fill: 4, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6034 // R line 6035 { type: 'line', label: rName, data: lineR, borderColor: ET.COLORS.RED, backgroundColor: 'rgba(244, 39, 38,0.08)', borderWidth: lineW, fill: 5, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 2 }, 6036 // R lower band (for shading below line) 6037 { type: 'line', label: rName + ' Lower', data: lineR_lower, borderColor: 'transparent', backgroundColor: 'rgba(244, 39, 38,0.08)', borderWidth: 0, fill: false, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6038 // Scatter: lower value drawn first so higher line's dot is on top when overlapping 6039 (function () { 6040 const BD = blueDotColor, RD = ET.COLORS.RED_DOT; 6041 const scatterPolls = [];
6042 series.forEach(function (p) { 6043 if (!p || p.D == null || p.R == null) return; 6044 if (p.D <= p.R) { 6045 scatterPolls.push({ x: p.date, y: p.D, _dot: BD }); 6046 scatterPolls.push({ x: p.date, y: p.R, _dot: RD }); 6047 } else { 6048 scatterPolls.push({ x: p.date, y: p.R, _dot: RD }); 6049 scatterPolls.push({ x: p.date, y: p.D, _dot: BD }); 6050 } 6051 }); 6052 return { 6053 type: 'scatter', label: dName + ' / ' + rName + ' polls', data: scatterPolls, pointRadius: scatterR, pointHoverRadius: scatterHoverR, 6054 pointBackgroundColor: function (ctx) { 6055 var raw = ctx.raw; 6056 return (raw && raw._dot) ? raw._dot : RD; 6057 }, 6058 showLine: false, order: 10 6059 }; 6060 })() 6061 ] 6062 }, 6063 options: { 6064 responsive: true, 6065 maintainAspectRatio: false, 6066 layout: { 6067 padding: homeMobCfg 6068 ? { bottom: padBottom, top: homeMobCfg.chartLayoutTop, left: homeMobCfg.chartLayoutLeft, right: 0 } 6069 : { bottom: padBottom, top: (ET.SLEEK_HOME_CHART_TOP_PAD != null ? ET.SLEEK_HOME_CHART_TOP_PAD : 52), left: 0, right: 0 } 6070 }, 6071 interaction: { mode: 'index', intersect: false }, 6072 plugins: { 6073 legend: { display: false }, 6074 tooltip: { 6075 enabled: false, 6076 external: function (obj) { 6077 const c = obj.chart, tt = obj.tooltip; 6078 c._etSleekHoverLabelYOffset = 1; 6079 const ca = c.chartArea; 6080 const xs = c.scales && (c.scales.x || c.scales['x']); 6081 6082 const tip = ET.etEnsureExternalTooltipDiv(c); 6083 if (typeof ET.sleekHoverExternalHandleHideSignal === 'function' && 6084 ET.sleekHoverExternalHandleHideSignal(c, tip, tt, ca, xs)) { 6085 return; 6086 } 6087 6088 const pick = ET.etTooltipIdxAndAnchorX(c, tt, labels); 6089 const idx = pick.idx; 6090 const anchorX = pick.anchorX; 6091 const dv = c.data.datasets[1] && c.data.datasets[1].data ? c.data.datasets[1].data[idx] : null; 6092 const rv = c.data.datasets[4] && c.data.datasets[4].data ? c.data.datasets[4].data[idx] : null; 6093 if (dv == null || rv == null) { 6094 tip.style.opacity = '0'; 6095 c._etCursorX = null; 6096 c._etSleekHoverLine = null; 6097 c.draw(); 6098 return; 6099 } 6100 6101 const lab = labels[idx]; 6102 const yr = +lab.slice(0, 4), mo = +lab.slice(5, 7) - 1, dy = +lab.slice(8, 10); 6103 const _etHoverDt = new Date(Date.UTC(yr, mo, dy, 12, 0, 0, 0)); 6104 const dateText = (typeof ET.fmtSleekHoverDateText === 'function') 6105 ? ET.fmtSleekHoverDateText(_etHoverDt, c) 6106 : _etHoverDt.toLocaleString('en-US', { timeZone: ET.TZ, month: 'short', day: 'numeric', year: 'numeric' }); 6107 6108 const margin = dv - rv; 6109 const lead = margin === 0 ? 'Tie' : (margin > 0 ? 'D' : 'R'); 6110 let chipHtml; 6111 const useHomeMobGlow = typeof ET.shouldUseHomeMobileEhGlowChip === 'function' && 6112 ET.shouldUseHomeMobileEhGlowChip(c); 6113 if (useHomeMobGlow && typeof ET.applyPollsmaxHomeMobileGlowChipHoverChrome === 'function') { 6114 ET.applyPollsmaxHomeMobileGlowChipHoverChrome(c); 6115 } 6116 if (useHomeMobGlow && typeof ET.sleekHoverEhGlowMarginChipHtml === 'function') { 6117 const glowLead = (indSenateChart && lead === 'D') ? 'I' : lead; 6118 chipHtml = ET.sleekHoverEhGlowMarginChipHtml( 6119 glowLead, 6120 Math.abs(margin), 6121 c._etSleekHoverChipFontSize, 6122 c._etSleekHoverEhChipFontWeight 6123 ); 6124 } else if (!senateMode && stateKeySearch && typeof ET.sleekHoverGovRaceChipHtml === 'function') { 6125 chipHtml = ET.sleekHoverGovRaceChipHtml(lead, Math.abs(margin), stateKeySearch); 6126 } else if (senateMode && stateKeySearch && typeof ET.sleekHoverSenateRaceChipHtml === 'function') { 6127 chipHtml = ET.sleekHoverSenateRaceChipHtml(lead, Math.abs(margin), stateKeySearch); 6128 } else if (lead === 'Tie') { 6129 chipHtml = ET.sleekHoverChipHtml('Tie', 0); 6130 } else if (indSenateChart && lead === 'D') { 6131 chipHtml = ET.sleekHoverChipHtml('I', Math.abs(margin)); 6132 } else { 6133 chipHtml = ET.sleekHoverChipHtml(lead, Math.abs(margin)); 6134 } 6135 const dTipFill = indSenateChart ? ET.COLORS.IND_GOLD : ET.COLORS.BLUE; 6136 6137 if (typeof ET.etSleekHoverTooltipCompactStyles === 'function') ET.etSleekHoverTooltipCompactStyles(tip); 6138 if (useHomeMobGlow && typeof ET.etSleekHoverTooltipHeaderHtml === 'function') { 6139 tip.innerHTML = ET.etSleekHoverTooltipHeaderHtml(c, dateText, chipHtml); 6140 } else if (c._etSleekHoverMatchHomeApproval && typeof ET.sleekHoverHeaderLineHtml === 'function') { 6141 tip.innerHTML = ET.sleekHoverHeaderLineHtml(dateText, chipHtml, c); 6142 } else { 6143 tip.innerHTML = ET.sleekHoverHeaderLineHtml(dateText, wrapSearchAllPollsC
6143hartHoverChip(chipHtml)); 6144 } 6145 6146 const mD = c.getDatasetMeta(1), mR = c.getDatasetMeta(4); 6147 const pD = (mD && mD.data && mD.data[idx]) ? mD.data[idx] : null; 6148 const pR = (mR && mR.data && mR.data[idx]) ? mR.data[idx] : null; 6149 let lineX = (typeof ET.etSleekHoverLineXFromIndex === 'function') ? ET.etSleekHoverLineXFromIndex(c, idx) : null; 6150 if (lineX == null || isNaN(lineX)) { 6151 lineX = anchorX; 6152 if (pD && typeof pD.x === 'number' && !isNaN(pD.x)) lineX = pD.x; 6153 else if (pR && typeof pR.x === 'number' && !isNaN(pR.x)) lineX = pR.x; 6154 } 6155 const pts = []; 6156 function searchHoverCandLabel(fullName, party, raceKind) { 6157 if (window.ET && typeof ET.searchAllPollsHoverCandLabel === 'function') { 6158 return ET.searchAllPollsHoverCandLabel(fullName, { 6159 stateKey: stateKeySearch, 6160 party: party, 6161 raceKind: raceKind 6162 }); 6163 } 6164 if (window.ET && typeof ET.gePollBarCandDisplayName === 'function') { 6165 return ET.gePollBarCandDisplayName(fullName, { 6166 stateKey: stateKeySearch, 6167 party: party, 6168 kind: raceKind === 'gov' ? 'gov' : 'senate', 6169 incumbent: ET.candFullNameIsIncumbent && ET.candFullNameIsIncumbent(fullName) 6170 }); 6171 } 6172 return fullName; 6173 } 6174 const raceKindHover = senateMode ? 'senate' : 'gov'; 6175 const dHover = searchHoverCandLabel(dName, 'D', raceKindHover); 6176 const rHover = searchHoverCandLabel(rName, 'R', raceKindHover); 6177 const searchHoverDotR = typeof ET.sleekHoverPointRadiusForChart === 'function' 6178 ? ET.sleekHoverPointRadiusForChart(c) 6179 : ((c._etSleekHoverPointRadius != null) ? c._etSleekHoverPointRadius : searchAllPollsHoverDotRadius()); 6180 function pushSearchHoverPt(el, val, fill, label, dsIdx) { 6181 if (val == null || !isFinite(val)) return; 6182 var ptObj = { 6183 y: el && el.y != null && isFinite(el.y) ? el.y : null, 6184 value: val, 6185 fill: fill, 6186 label: label, 6187 ds: dsIdx 6188 }; 6189 pts.push(typeof ET.etSleekHoverCanvasPoint === 'function' 6190 ? ET.etSleekHoverCanvasPoint(c, ptObj, searchHoverDotR) 6191 : ptObj); 6192 } 6193 if (pD) pushSearchHoverPt(pD, dv, dTipFill, dHover + ' ' + ET.oneDec(dv) + '%', 1); 6194 if (pR) pushSearchHoverPt(pR, rv, ET.COLORS.RED, rHover + ' ' + ET.oneDec(rv) + '%', 4); 6195 pts.sort((a, b) => { 6196 if (a.value != null && b.value != null) return b.value - a.value; 6197 return (a.y || 0) - (b.y || 0); 6198 }); 6199 c._etSleekHoverLine = { idx: idx, x: lineX, points: pts }; 6200 c._etCursorX = null; 6201 6202 tip.style.opacity = '1'; 6203 c._etSleekHoverHeaderYOffset = SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX; 6204 if (typeof ET.etPositionSleekHoverHeaderTooltip === 'function') { 6205 ET.etPositionSleekHoverHeaderTooltip(c, tip, lineX); 6206 } 6207 c.draw(); 6208 } 6209 } 6210 }, 6211 scales: { 6212 x: { 6213 offset: false, 6214 alignToPixels: true, 6215 grid: { 6216 display: true, 6217 drawBorder: false, 6218 drawTicks: false, 6219 drawOnChartArea: true, 6220 color: ET.xGridColorMonthStarts(labels, axisTheme.grid) 6221 }, 6222 border: { display: showBottomAxisLine, color: axisTheme.border, width: 1 }, 6223 ticks: { 6224 color: axisTheme.tick, 6225 autoSkip: false, 6226 maxRotation: 0, 6227 padding: homeMobCfg ? homeMobCfg.axisTickPaddingX : xTicksPad, 6228 font: (typeof ET.homeChartAxisTickFont === 'function') ? ET.homeChartAxisTickFont() : { family: ET.CHART_AXIS_FONT_FAMILY }, 6229 callback: (v, i) => (ET.monthTickByInterval ? ET.monthTickByInterval(pollsmaxHomeSearchChartMonthInterval(), true) : function (l, j) { return ET.monthTick2Start(l, j, true); })(labels, i) 6230 } 6231 }, 6232 y: { 6233 alignToPixels: true, 6234 offset: false, 6235 grid: { color: axisTheme.grid, offset: false, drawBorder: false, drawTicks: false }, 6236 afterBuildTicks: ET.yAxisAfterBuildTicksFromRange(), 6237 ticks: { 6238 color: axisTheme.tick, 6239 font: (typeof ET.homeChartAxisTickFont === 'function') ? ET.homeChartAxisTickFont() : { family: ET.CHART_AXIS_FONT_FAMILY }, 6240 padding: homeMobCfg ? homeMobCfg.axisTickPaddingY : 10, 6241 precision: 0, 6242 callback: v => ET.yAxisPctTickLabel(v) 6243 }, 6244 min: yMin, 6245 max: yMax, 6246 border: { display: false } 6247 } 6248 } 6249 } 6250 }); 6251 chartSearch._etSleekHoverMetaD = 1; 6252 chartSearch._etSleekHoverMetaR = 4; 6253 /* Home Search All Polls: under-line glow a bit stronger than ME senate baseline. */ 6254 if (window.ET && typeof ET.applyHomeStrongerLineChartGlow === 'function') { 6255 ET.applyHomeStrongerLineChartGlow(chartSearch); 6256 } else if (window.ET && typeof ET.applyLineChartGlowToChart === 'function') { 6257 ET.applyLineChartGlowToChart(chartSearch); 6258 } 6259 if (ctx && ctx._pollsmaxChartInstance !== chartSearch) ctx._pollsmaxChartInstance = chartSearch; 6260 return chartSearch; 6261 } 6262 6263 function latestPollLastName(name) { 6264 if (window.ET && typeof ET.latestPollLastName === 'function') return ET.latestPollLastName(name); 6265 var s = String(name || '').trim(); 6266 if (!s) return 'â'; 6267 var parts = s.split(/\s+/); 6268 return parts[parts.length - 1]; 6269 } 6270 6271 function latestPollPct(v) { 6272 if (window.ET && typeof ET.latestPollPctStr === 'function') return ET.latestPollPctStr(v); 6273 var n = (window.ET && typeof ET.oneDec === 'function') ? ET.oneDec(v)
6273: (Math.round(v * 10) / 10); 6274 return String(n).replace(/\.0$/, '') + '%'; 6275 } 6276 6277 function latestPollChipColor(letter) { 6278 if (letter === 'D') return '#0c6df6'; 6279 if (letter === 'R') return '#f42726'; 6280 if (letter === 'I') return ET.COLORS.IND_GOLD; 6281 return '#475569'; 6282 } 6283 6284 function escapePollsterTitle(s) { 6285 if (typeof ET !== 'undefined' && ET.escapeHtml) return ET.escapeHtml(s); 6286 return String(s || '').replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>'); 6287 } 6288 6289 /** Match senate/gov hub Search Polls rows: senate-race-cand-line + min-h-[30px] candidate column. */ 6290 function searchPollCandLineHtml(name, value, color) { 6291 if (typeof ET !== 'undefined' && typeof ET.hubAsideCandLineHtml === 'function') { 6292 return ET.hubAsideCandLineHtml(name, value, color); 6293 } 6294 var pct = latestPollPct(value); 6295 return '<div class="senate-race-cand-line" style="color:' + color + ' !important"><span class="senate-race-cand-n">' + name + '</span><span class="senate-race-cand-p">' + pct + '</span></div>'; 6296 } 6297 6298 function searchPollCandsColHtml(rows, opts) { 6299 opts = opts || {}; 6300 var inner = ''; 6301 rows.forEach(function (row) { 6302 if (opts.stateKey && opts.raceKind !== 'gov' && row.party && 6303 typeof ET.hubSenateGeSearchPollCandLineHtml === 'function') { 6304 inner += ET.hubSenateGeSearchPollCandLineHtml(row.name, row.value, opts.stateKey, row.party); 6305 } else { 6306 inner += searchPollCandLineHtml(row.name, row.value, row.color); 6307 } 6308 }); 6309 return '<div class="text-[0.8125rem] leading-[1.15] text-right tabular-nums senate-race-cands-hub flex flex-col justify-center min-h-[30px]">' + inner + '</div>'; 6310 } 6311 6312 /** Sidebar list: when 7+ polls, cap height to exactly the first 6 rows; scroll for the rest. */ 6313 function setSearchPollSidebarListHeight(ul, pollCount, opts) { 6314 opts = opts || {}; 6315 if (!ul || !ul.style) return; 6316 var visibleRows = 6; 6317 6318 function clearSidebarListBox() { 6319 ul.style.height = ''; 6320 ul.style.maxHeight = ''; 6321 ul.style.overflowY = ''; 6322 } 6323 6324 function applyVisibleRowCap() { 6325 var items = ul.querySelectorAll(':scope > li'); 6326 if (items.length < visibleRows) { 6327 clearSidebarListBox(); 6328 return; 6329 } 6330 var r0 = items[0].getBoundingClientRect(); 6331 var rCap = items[visibleRows - 1].getBoundingClientRect(); 6332 var capPx = Math.ceil(rCap.bottom - r0.top); 6333 if (!capPx || capPx < 120) { 6334 capPx = typeof opts.fallbackCapPx === 'number' ? opts.fallbackCapPx : 411; 6335 } 6336 ul.style.height = capPx + 'px'; 6337 ul.style.maxHeight = capPx + 'px'; 6338 ul.style.overflowY = 'auto'; 6339 } 6340 6341 if (pollCount > visibleRows) { 6342 requestAnimationFrame(function () { 6343 requestAnimationFrame(applyVisibleRowCap); 6344 }); 6345 } else { 6346 clearSidebarListBox(); 6347 } 6348 } 6349 6350 function buildSearchTrumpApprovalChip(poll) { 6351 var a = poll.approve; 6352 var d = poll.disapprove; 6353 if (a == null || d == null || !ET.sleekHoverLabelChipHtml) return ''; 6354 var margin = a - d; 6355 if (Math.abs(margin) < 1e-9) { 6356 return ET.sleekHoverChipHtml ? ET.sleekHoverChipHtml('Tie', 0) : ''; 6357 } 6358 var GREEN = '#00e070'; 6359 var RED = (ET.COLORS && ET.COLORS.RED) || '#f42726'; 6360 var label = margin > 0 ? ('+' + ET.oneDec(margin)) : ET.oneDec(margin); 6361 return ET.sleekHoverLabelChipHtml(margin > 0 ? GREEN : RED, label); 6362 } 6363 6364 function buildSearchGenericBallotChip(poll) { 6365 var a = poll.approve; 6366 var d = poll.disapprove; 6367 if (a == null || d == null || !ET.sleekHoverChipHtml) return ''; 6368 var margin = a - d; 6369 if (Math.abs(margin) < 1e-9) { 6370 return ET.sleekHoverChipHtml('Tie', 0); 6371 } 6372 var lead = margin > 0 ? 'D' : 'R'; 6373 return ET.sleekHoverChipHtml(lead, Math.abs(margin)); 6374 } 6375 6376 function createApprovalPollsList(container, polls, category) { 6377 if (!container || !polls || !polls.length) { 6378 if (container) { 6379 container.innerHTML = ''; 6380 setSearchPollSidebarListHeight(container, 0); 6381 } 6382 return; 6383 } 6384 var GREEN = '#00e070'; 6385 var BLUE = (ET.COLORS && ET.COLORS.BLUE) || '#0c6df6'; 6386 var RED = (ET.COLORS && ET.COLORS.RED) || '#f42726'; 6387 var sorted = polls.slice().sort(function (a, b) { 6388 return new Date(b.date) - new Date(a.date); 6389 }); 6390 var html = ''; 6391 sorted.forEach(function (poll) { 6392 var a = poll.approve; 6393 var d = poll.disapprove; 6394 var margin = (a != null && d != null) ? a - d : 0; 6395 var chipHtml; 6396 var rows; 6397 if (category === 'approval-generic') { 6398 chipHtml = buildSearchGenericBallotChip(poll); 6399 rows = [ 6400 { name: 'Democrats', value: a, color: BLUE }, 6401 { name: 'Republicans', value: d, color: RED } 6402 ].sort(function (x, y) { 6403 return (y.value != null ? y.value : -1) - (x.value != null ? x.value : -1); 6404 }); 6405 } else { 6406 chipHtml = buildSearchTrumpApprovalChip(poll); 6407 rows = [ 6408 { name: 'Approve', value: a, color: GREEN },
6409 { name: 'Disapprove', value: d, color: RED } 6410 ].sort(function (x, y) { 6411 return (y.value != null ? y.value : -1) - (x.value != null ? x.value : -1); 6412 }); 6413 } 6414 var dateStr = ET.fmtPollListDate ? ET.fmtPollListDate(poll) : poll.date; 6415 var pollsterRaw = ET.safePollsterText ? ET.safePollsterText(poll) : escapePollsterTitle(poll.pollster); 6416 html += ` 6417 <li class="flex items-center justify-between gap-2 bg-slate-800/30 rounded-xl px-3 py-2 mb-2"> 6418 <div class="min-w-0 flex-1 pr-2 overflow-hidden"> 6419 <div class="font-medium text-white truncate" title="${escapePollsterTitle(poll.pollster)}">${pollsterRaw}</div> 6420 <div class="text-[11px] text-slate-400">${dateStr} ⢠${poll.sample || 'â'}</div> 6421 </div> 6422 <div class="flex items-center gap-2 shrink-0"> 6423 ${searchPollCandsColHtml(rows)} 6424 <div class="w-[5.5rem] flex justify-end items-center flex-shrink-0"><span style="transform:scale(1.08);transform-origin:right center;display:inline-block">${chipHtml}</span></div> 6425 </div> 6426 </li> 6427 `; 6428 }); 6429 container.innerHTML = html; 6430 setSearchPollSidebarListHeight(container, sorted.length); 6431 } 6432 6433 // Custom polls list creation function 6434 // raceKind: 'gov' | undefined â governor search uses flip chip vs incumbent; undefined + stateKey â Senate race chip. 6435 function createCustomPollsList(container, series, dName, rName, stateKey, raceKind) { 6436 if (!container || !series || series.length === 0) { 6437 container.innerHTML = ''; 6438 setSearchPollSidebarListHeight(container, 0); 6439 return; 6440 } 6441 6442 // Sort by date (newest first); show all polls (fixed 7-row viewport + scroll when 7+) 6443 const sortedSeries = series.slice().sort((a, b) => new Date(b.date) - new Date(a.date)); 6444 6445 let html = ''; 6446 sortedSeries.forEach(poll => { 6447 const t = (stateKey && ET.pollPartyTotalsDR) ? ET.pollPartyTotalsDR(poll) : { D: poll.D, R: poll.R, nD: 1, nR: 1 }; 6448 const dTot = t.D != null ? t.D : 0; 6449 const rTot = t.R != null ? t.R : 0; 6450 const margin = dTot - rTot; 6451 const lead = margin > 0 ? 'D' : (margin < 0 ? 'R' : 'Tie'); 6452 const indSenList = !!(stateKey && raceKind !== 'gov' && ET.isSenateIndGeState && ET.isSenateIndGeState(stateKey)); 6453 let chipHtml; 6454 if (raceKind === 'gov' && stateKey && typeof ET.sleekHoverGovRaceChipHtml === 'function') { 6455 chipHtml = ET.sleekHoverGovRaceChipHtml(lead, Math.abs(margin), stateKey); 6456 } else if (raceKind !== 'gov' && typeof ET.sleekHoverSenateRaceChipHtml === 'function' && stateKey) { 6457 chipHtml = ET.sleekHoverSenateRaceChipHtml(lead, Math.abs(margin), stateKey); 6458 } else if (indSenList && lead === 'D') { 6459 chipHtml = ET.sleekHoverChipHtml('I', Math.abs(margin)); 6460 } else { 6461 chipHtml = ET.sleekHoverChipHtml(lead, Math.abs(margin)); 6462 } 6463 const usePartyLabels = !!(stateKey && (t.nD > 1 || t.nR > 1)); 6464 const labD = usePartyLabels ? 'Democrats' : latestPollLastName(dName); 6465 const labR = usePartyLabels ? 'Republicans' : latestPollLastName(rName); 6466 const dListColor = (indSenList && !usePartyLabels) 6467 ? ((typeof ET.neSenateOsbornTextColor === 'function') ? ET.neSenateOsbornTextColor() : (ET.OSBORN_GOLD || ET.COLORS.IND_GOLD)) 6468 : latestPollChipColor('D'); 6469 const rows = [ 6470 { name: labD, value: t.D, color: dListColor, party: 'D' }, 6471 { name: labR, value: t.R, color: latestPollChipColor
6471('R'), party: 'R' } 6472 ].sort((a, b) => ((b.value != null && isFinite(b.value) ? b.value : 0) - (a.value != null && isFinite(a.value) ? a.value : 0))); 6473 6474 const dateStr = (typeof ET.fmtPollListDate === 'function') ? ET.fmtPollListDate(poll) : poll.date; 6475 6476 const pollsterRaw = (typeof ET !== 'undefined' && ET.safePollsterText) ? ET.safePollsterText(poll) : escapePollsterTitleET.safePollsterText(poll); 6477 html += ` 6478 <li class="flex items-center justify-between gap-2 bg-slate-800/30 rounded-xl px-3 py-2 mb-2"> 6479 <div class="min-w-0 flex-1 pr-2 overflow-hidden"> 6480 <div class="font-medium text-white truncate" title="${escapePollsterTitle(poll.pollster)}">${pollsterRaw}</div> 6481 <div class="text-[11px] text-slate-400">${dateStr} ⢠${poll.sample || 'â'}</div> 6482 </div> 6483 <div class="flex items-center gap-2 shrink-0"> 6484 ${searchPollCandsColHtml(rows, { stateKey: stateKey, raceKind: raceKind })} 6485 <div class="w-[5.5rem] flex justify-end items-center flex-shrink-0"><span style="transform:scale(1.08);transform-origin:right center;display:inline-block">${chipHtml}</span></div> 6486 </div> 6487 </li> 6488 `; 6489 }); 6490 6491 container.innerHTML = html; 6492 setSearchPollSidebarListHeight(container, sortedSeries.length); 6493 } 6494 6495 // California: top 5 + party margin (shared ET.caGovChartBundle). 6496 function createCaliforniaChart(ctx, series, opts) { 6497 opts = opts || {}; 6498 var axisTheme = pollsmaxHomeChartAxisTheme(); 6499 if (!ctx || !series || series.length === 0) return null; 6500 if (opts.blankSinglePoll && series.length === 1) { 6501 etClearSearchChartWrap(ctx); 6502 return null; 6503 } 6504 6505 const padBottom = (opts.xAxisExtraBottom != null ? opts.xAxisExtraBottom : 0); 6506 const xTicksPad = (opts.xTicksPadding != null ? opts.xTicksPadding : 2); 6507 const bundle = ET.caGovChartBundle ? ET.caGovChartBundle(series, 2) : null; 6508 if (!bundle) return null; 6509 const labels = bundle.labels; 6510 const linePartyD = bundle.linePartyD; 6511 const linePartyR = bundle.linePartyR; 6512 const entries = bundle.entries; 6513 const datasets = bundle.datasets; 6514 let yMin = bundle.yMin; 6515 let yMax = bundle.yMax; 6516 const showBottomAxisLine = Math.abs((yMin / 3) - Math.round(yMin / 3)) < 1e-9; 6517 const BLUE = ET.COLORS.BLUE, RED = ET.COLORS.RED; 6518 6519 return new Chart(ctx, { 6520 data: { labels, datasets }, 6521 options: { 6522 responsive: true, 6523 maintainAspectRatio: false, 6524 layout: { padding: { bottom: padBottom, top: (ET.SLEEK_HOME_CHART_TOP_PAD != null ? ET.SLEEK_HOME_CHART_TOP_PAD : 52), left: 0, right: 0 } }, 6525 interaction: { mode: 'index', intersect: false }, 6526 plugins: { 6527 legend: { display: false }, 6528 tooltip: { 6529 enabled: false, 6530 external: function (obj) { 6531 const c = obj.chart, tt = obj.tooltip; 6532 c._etSleekHoverLabelYOffset = 2; 6533 const ca = c.chartArea; 6534 const xs = c.scales && (c.scales.x || c.scales['x']); 6535 const tip = ET.etEnsureExternalTooltipDiv(c); 6536 if (typeof ET.sleekHoverExternalHandleHideSignal === 'function' && 6537 ET.sleekHoverExternalHandleHideSignal(c, tip, tt, ca, xs)) { 6538 return; 6539 } 6540 6541 const pick = ET.etTooltipIdxAndAnchorX(c, tt, labels); 6542 const idx = pick.idx;
6543 const anchorX = pick.anchorX; 6544 const pv = linePartyD[idx], pr = linePartyR[idx]; 6545 if (pv == null || pr == null) { 6546 tip.style.opacity = '0'; 6547 c._etCursorX = null; 6548 c._etSleekHoverLine = null; 6549 c.draw(); 6550 return; 6551 } 6552 6553 const lab = labels[idx]; 6554 const yr = +lab.slice(0, 4), mo = +lab.slice(5, 7) - 1, dy = +lab.slice(8, 10); 6555 const _etHoverDt = new Date(Date.UTC(yr, mo, dy, 12, 0, 0, 0)); 6556 const dateText = (typeof ET.fmtSleekHoverDateText === 'function') 6557 ? ET.fmtSleekHoverDateText(_etHoverDt, c) 6558 : _etHoverDt.toLocaleString('en-US', { timeZone: ET.TZ, month: 'short', day: 'numeric', year: 'numeric' }); 6559 6560 const margin = pv - pr; 6561 const lead = margin === 0 ? 'Tie' : (margin > 0 ? 'D' : 'R'); 6562 const caGovKey = (opts && opts.stateKey) ? opts.stateKey : 'CA'; 6563 const chipHtml = (lead === 'Tie') 6564 ? ET.sleekHoverChipHtml('Tie', 0) 6565 : (typeof ET.sleekHoverGovRaceChipHtml === 'function' 6566 ? ET.sleekHoverGovRaceChipHtml(lead, Math.abs(margin), caGovKey) 6567 : ET.sleekHoverChipHtml(lead, Math.abs(margin))); 6568 6569 if (typeof ET.etSleekHoverTooltipCompactStyles === 'function') ET.etSleekHoverTooltipCompactStyles(tip); 6570 if (c._etSleekHoverMatchHomeApproval && typeof ET.sleekHoverHeaderLineHtml === 'function') { 6571 tip.innerHTML = ET.sleekHoverHeaderLineHtml(dateText, chipHtml, c); 6572 } else { 6573 tip.innerHTML = ET.sleekHoverHeaderLineHtml(dateText, wrapSearchAllPollsChartHoverChip(chipHtml)); 6574 } 6575 6576 const pts = []; 6577 let lineXCa = (typeof ET.etSleekHoverLineXFromIndex === 'function') ? ET.etSleekHoverLineXFromIndex(c, idx) : null; 6578 if (lineXCa == null || isNaN(lineXCa)) lineXCa = anchorX; 6579 for (let i = 0; i < entries.length; i++) { 6580 const v = entries[i].line[idx]; 6581 if (v == null) continue; 6582 const meta = c.getDatasetMeta(i * 4 + 1); 6583 const pt = meta && meta.data && meta.data[idx] ? meta.data[idx] : null; 6584 if (pt) { 6585 if ((lineXCa == null || isNaN(lineXCa)) && typeof pt.x === 'number' && !isNaN(pt.x)) lineXCa = pt.x; 6586 pts.push({ y: pt.y, value: v, fill: entries[i].color, label: entries[i].name + ' ' + ET.oneDec(v) + '%', ds: i * 4 + 1 }); 6587 } 6588 } 6589 pts.sort((a, b) => { 6590 if (a.value != null && b.value != null) return b.value - a.value; 6591 return (a.y || 0) - (b.y || 0); 6592 }); 6593 c._etSleekHoverLine = { idx: idx, x: lineXCa, points: pts }; 6594 c._etCursorX = null; 6595 6596 tip.style.opacity = '1'; 6597 c._etSleekHoverHeaderYOffset = SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX; 6598 if (typeof ET.etPositionSleekHoverHeaderTooltip === 'function') { 6599 ET.etPositionSleekHoverHeaderTooltip(c, tip, lineXCa); 6600 } 6601 c.draw(); 6602 } 6603 } 6604 }, 6605 scales: { 6606 x: { 6607 offset: false, 6608 alignToPixels: true, 6609 grid: { 6610 display: true, 6611 drawBorder: false, 6612 drawTicks: false, 6613 drawOnChartArea: true, 6614 color: ET.xGridColorMonthStarts(labels, axisTheme.grid) 6615 }, 6616 border: { display: showBottomAxisLine, color: axisTheme.border, width: 1 }, 6617 ticks: { 6618 color: axisTheme.tick, maxTicksLimit: 12, autoSkip: false, maxRotation: 0, minRotation: 0, 6619 padding: xTicksPad, 6620 font: { family: ET.CHART_AXIS_FONT_FAMILY }, 6621 callback: function (value, index) { 6622 const label = labels[index]; 6623 if (!label) return ''; 6624 const mo = +label.slice(5, 7), day = +label.slice(8, 10); 6625 if (mo % 2 === 0 && day === 1) { 6626 return (ET.CHART_MONTH_ABBREV && ET.CHART_MONTH_ABBREV[mo - 1] 6627 ? ET.CHART_MONTH_ABBREV[mo - 1] 6628 : '') + ' ' + (+label.slice(0, 4)); 6629 } 6630 return ''; 6631 } 6632 } 6633 }, 6634 y: { 6635 alignToPixels: true, 6636 offset: false, 6637 grid: { color: axisTheme.grid, offset: false, drawBorder: false, drawTicks: false }, 6638 afterBuildTicks: ET.yAxisAfterBuildTicksFromRange(), 6639 ticks: { 6640 color: axisTheme.tick, 6641 font: { family: ET.CHART_AXIS_FONT_FAMILY }, 6642 padding: 10, 6643 precision: 0, 6644 callback: v => ET.yAxisPctTickLabel(v) 6645 }, 6646 min: yMin, 6647 max: yMax, 6648 border: { display: false } 6649 } 6650 } 6651 } 6652 }); 6653 } 6654 6655 // Michigan 3-way chart function 6656 function createMichiganChart(ctx, series, opts) { 6657 opts = opts || {}; 6658 var axisTheme = pollsmaxHomeChartAxisTheme(); 6659 if (!ctx || !series || series.length === 0) return null; 6660 if (opts.blankSinglePoll && series.length === 1) { 6661 etClearSearchChartWrap(ctx); 6662 return null; 6663 } 6664 6665 const padBottom = (opts.xAxisExtraBottom != null ? opts.xAxisExtraBottom : 0); 6666 const xTicksPad = (opts.xTicksPadding != null ? opts.xTicksPadding : 2); 6667 const labels = ET.dailyRangeToTodayET(series); 6668 var miLines = (typeof ET.govMiGovernorPollingLines === 'function') 6669 ? ET.govMiGovernorPollingLines(series, labels, {}) 6670 : null; 6671 const lineD = miLines ? miLines.lineD : ET.runningAvgOnLabels(series, 'D', labels); 6672 const lineR = miLines ? miLines.lineR : ET.runningAvgOnLabels(series, 'R', labels); 6673 const lineI = miLines && miLines.lineI 6674 ? miLines.lineI 6675 : (function () { 6676 var li = ET.runningAvgOnLabels(series, 'I', labels); 6677 return (typeof ET.govClampDugganLineAtWithdraw === 'function') 6678 ? ET.govClampDugganLineAtWithdraw(li, labels) 6679 : li; 6680 })(); 6681 6682 const vals = [];
6683 [lineD, lineR, lineI].forEach(line => { 6684 line.forEach(v => v != null && vals.push(v)); 6685 }); 6686 let yMin = (vals.length ? Math.min(...vals) : 20) - 2; 6687 let yMax = (vals.length ? Math.max(...vals) : 60) + 2; 6688 const showBottomAxisLine = Math.abs((yMin / 3) - Math.round(yMin / 3)) < 1e-9; 6689 6690 // Calculate 1% shading bands (above and below each line) 6691 const lineD_upper = lineD.map(v => v != null ? v + 1 : null); 6692 const lineD_lower = lineD.map(v => v != null ? v - 1 : null); 6693 const lineR_upper = lineR.map(v => v != null ? v + 1 : null); 6694 const lineR_lower = lineR.map(v => v != null ? v - 1 : null); 6695 const lineI_upper = lineI.map(v => v != null ? v + 1 : null); 6696 const lineI_lower = lineI.map(v => v != null ? v - 1 : null); 6697 const IG = ET.COLORS.IND_GOLD; 6698 const IG_FILL = ET.COLORS.IND_GOLD_FILL; 6699 const IG_DOT = ET.COLORS.IND_GOLD_DOT; 6700 6701 return new Chart(ctx, { 6702 data: { 6703 labels, 6704 datasets: [ 6705 // D upper band (for shading above line) 6706 { type: 'line', label: ET.govCandName('MI', 'D') + ' Upper', data: lineD_upper, borderColor: 'transparent', backgroundColor: 'rgba(12, 109, 246,0.08)', borderWidth: 0, fill: 1, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6707 // D line 6708 { type: 'line', label: ET.govCandName('MI', 'D'), data: lineD, borderColor: ET.COLORS.BLUE, backgroundColor: 'rgba(12, 109, 246,0.08)', borderWidth: 2.5, fill: 2, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 2 }, 6709 // D lower band (for shading below line) 6710 { type: 'line', label: ET.govCandName('MI', 'D') + ' Lower', data: lineD_lower, borderColor: 'transparent', backgroundColor: 'rgba(12, 109, 246,0.08)', borderWidth: 0, fill: false, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6711 // R upper band (for shading above line) 6712 { type: 'line', label: ET.govCandName('MI', 'R') + ' Upper', data: lineR_upper, borderColor: 'transparent', backgroundColor: 'rgba(244, 39, 38,0.08)', borderWidth: 0, fill: 4, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6713 // R line 6714 { type: 'line', label: ET.govCandName('MI', 'R'), data: lineR, borderColor: ET.COLORS.RED, backgroundColor: 'rgba(244, 39, 38,0.08)', borderWidth: 2.5, fill: 5, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 2 }, 6715 // R lower band (for shading below line) 6716 { type: 'line', label: ET.govCandName('MI', 'R') + ' Lower', data: lineR_lower, borderColor: 'transparent', backgroundColor: 'rgba(244, 39, 38,0.08)', borderWidth: 0, fill: false, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6717 // I upper band (for shading above line) 6718 { type: 'line', label: ET.govCandName('MI', 'I') + ' Upper', data: lineI_upper, borderColor: 'transparent', backgroundColor: IG_FILL, borderWidth: 0, fill: 7, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6719 // I line 6720 { type: 'line', label: ET.govCandName('MI', 'I'), data: lineI, borderColor: IG, backgroundColor: IG_FILL, borderWidth: 2.5, fill: 8, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 2 }, 6721 // I lower band (for shading below line) 6722 { type: 'line', label: ET.govCandName('MI', 'I') + ' Lower', data: lineI_lower, borderColor: 'transparent', backgroundColor: IG_FILL, borderWidth: 0, fill: false, tension: .35, cubicInterpolationMode: 'monotone', spanGaps: true, pointRadius: 0, pointHoverRadius: 0, order: 3 }, 6723 // Scatter: sort by poll value so higher line's dot is on top when overlapping 6724 (function () { 6725 const scatterPolls = [];
6726 series.forEach(function (p) { 6727 var row = [ 6728 { y: p.D, _dot: ET.COLORS.BLUE_DOT }, 6729 { y: p.R, _dot: ET.COLORS.RED_DOT }, 6730 { y: p.I, _dot: IG_DOT } 6731 ].filter(function (t) { return t.y != null; }); 6732 row.sort(function (a, b) { return a.y - b.y; }); 6733 row.forEach(function (t) { 6734 scatterPolls.push({ x: p.date, y: t.y, _dot: t._dot }); 6735 }); 6736 }); 6737 return { 6738 type: 'scatter', label: 'MI polls', data: scatterPolls, pointRadius: 4, 6739 pointBackgroundColor: function (ctx) { 6740 var raw = ctx.raw; 6741 return (raw && raw._dot) ? raw._dot : IG_DOT; 6742 }, 6743 showLine: false, order: 10 6744 }; 6745 })() 6746 ] 6747 }, 6748 options: { 6749 responsive: true, 6750 maintainAspectRatio: false, 6751 layout: { padding: { bottom: padBottom, top: (ET.SLEEK_HOME_CHART_TOP_PAD != null ? ET.SLEEK_HOME_CHART_TOP_PAD : 52), left: 0, right: 0 } }, 6752 interaction: { mode: 'index', intersect: false }, 6753 plugins: { 6754 legend: { display: false }, 6755 tooltip: { 6756 enabled: false, 6757 external: function (obj) { 6758 const c = obj.chart, tt = obj.tooltip; 6759 c._etSleekHoverLabelYOffset = 2; 6760 const ca = c.chartArea; 6761 const xs = c.scales && (c.scales.x || c.scales['x']); 6762 6763 const tip = ET.etEnsureExternalTooltipDiv(c); 6764 if (typeof ET.sleekHoverExternalHandleHideSignal === 'function' && 6765 ET.sleekHoverExternalHandleHideSignal(c, tip, tt, ca, xs)) { 6766 return; 6767 } 6768 6769 const pick = ET.etTooltipIdxAndAnchorX(c, tt, labels); 6770 const idx = pick.idx; 6771 const anchorX = pick.anchorX; 6772 const dv = lineD[idx], rv = lineR[idx], iv = lineI[idx]; 6773 if (dv == null && rv == null && iv == null) { 6774 tip.style.opacity = '0'; 6775 c._etCursorX = null; 6776 c._etSleekHoverLine = null; 6777 c.draw(); 6778 return; 6779 } 6780 6781 const lab = labels[idx]; 6782 const yr = +lab.slice(0, 4), mo = +lab.slice(5, 7) - 1, dy = +lab.slice(8, 10); 6783 const _etHoverDt = new Date(Date.UTC(yr, mo, dy, 12, 0, 0, 0)); 6784 const dateText = (typeof ET.fmtSleekHoverDateText === 'function') 6785 ? ET.fmtSleekHoverDateText(_etHoverDt, c) 6786 : _etHoverDt.toLocaleString('en-US', { timeZone: ET.TZ, month: 'short', day: 'numeric', year: 'numeric' }); 6787 6788 const candRows = [ 6789 { letter: 'D', name: ET.govCandName('MI', 'D'), value: dv, color: ET.COLORS.BLUE }, 6790 { letter: 'R', name: ET.govCandName('MI', 'R'), value: rv, color: ET.COLORS.RED }, 6791 { letter: 'I', name: ET.govCandName('MI', 'I'), value: iv, color: (ET.indChartAccent ? ET.indChartAccent().line : ET.COLORS.IND_GOLD) } 6792 ].filter(row => row.value != null); 6793 candRows.sort((a, b) => b.value - a.value); 6794 let chipHtml; 6795 const miGovKey = (opts && opts.stateKey) ? opts.stateKey : 'MI'; 6796 if (candRows.length < 2) { 6797 chipHtml = ET.sleekHoverChipHtml('Tie', 0); 6798 } else { 6799 const topM = candRows[0].value - candRows[1].value; 6800 const ld0 = candRows[0].letter; 6801 chipHtml = topM === 0 ? ET.sleekHoverChipHtml('Tie', 0) 6802 : (typeof ET.sleekHoverGovRaceChipHtml === 'function' 6803 ? ET.sleekHoverGovRaceChipHtml(ld0, Math.abs(topM), miGovKey) 6804 : ET.sleekHoverChipHtml(ld0, Math.abs(topM))); 6805 } 6806 6807 if (typeof ET.etSleekHoverTooltipCompactStyles === 'function') ET.etSleekHoverTooltipCompactStyles(tip); 6808 if (c._etSleekHoverMatchHomeApproval && typeof ET.sleekHoverHeaderLineHtml === 'function') { 6809 tip.innerHTML = ET.sleekHoverHeaderLineHtml(dateText, chipHtml, c); 6810 } else { 6811 tip.innerHTML = ET.sleekHoverHeaderLineHtml(dateText, wrapSearchAllPollsC
6811hartHoverChip(chipHtml)); 6812 } 6813 6814 const metaByLetter = { D: 1, R: 4, I: 7 }; 6815 const pts = []; 6816 let lineXMi = (typeof ET.etSleekHoverLineXFromIndex === 'function') ? ET.etSleekHoverLineXFromIndex(c, idx) : null; 6817 if (lineXMi == null || isNaN(lineXMi)) lineXMi = anchorX; 6818 candRows.forEach(row => { 6819 const mi = metaByLetter[row.letter]; 6820 const meta = c.getDatasetMeta(mi); 6821 const pt = meta && meta.data && meta.data[idx] ? meta.data[idx] : null; 6822 if (pt) { 6823 if ((lineXMi == null || isNaN(lineXMi)) && typeof pt.x === 'number' && !isNaN(pt.x)) lineXMi = pt.x; 6824 pts.push({ y: pt.y, value: row.value, fill: row.color, label: row.name + ' ' + ET.oneDec(row.value) + '%', ds: mi }); 6825 } 6826 }); 6827 pts.sort((a, b) => { 6828 if (a.value != null && b.value != null) return b.value - a.value; 6829 return (a.y || 0) - (b.y || 0); 6830 }); 6831 c._etSleekHoverLine = { idx: idx, x: lineXMi, points: pts }; 6832 c._etCursorX = null; 6833 6834 tip.style.opacity = '1'; 6835 c._etSleekHoverHeaderYOffset = SEARCH_ALL_POLLS_GE_HOVER_HEADER_Y_PX; 6836 if (typeof ET.etPositionSleekHoverHeaderTooltip === 'function') { 6837 ET.etPositionSleekHoverHeaderTooltip(c, tip, lineXMi); 6838 } 6839 c.draw(); 6840 } 6841 } 6842 }, 6843 scales: { 6844 x: { 6845 offset: false, 6846 alignToPixels: true, 6847 grid: { 6848 display: true, 6849 drawBorder: false, 6850 drawTicks: false, 6851 drawOnChartArea: true, 6852 color: ET.xGridColorMonthStarts(labels, axisTheme.grid) 6853 }, 6854 border: { display: showBottomAxisLine, color: axisTheme.border, width: 1 }, 6855 ticks: { 6856 color: axisTheme.tick, 6857 maxTicksLimit: 12, 6858 autoSkip: false, 6859 maxRotation: 0, 6860 minRotation: 0, 6861 padding: xTicksPad, 6862 font: { family: ET.CHART_AXIS_FONT_FAMILY }, 6863 callback: function (value, index, values) { 6864 var tickFn = ET.monthTickByInterval 6865 ? ET.monthTickByInterval(pollsmaxHomeSearchChartMonthInterval(), true) 6866 : function (l, j) { return ET.monthTick2Start(l, j, true); }; 6867 return tickFn(labels, index); 6868 } 6869 } 6870 }, 6871 y: { 6872 alignToPixels: true, 6873 offset: false, 6874 grid: { color: axisTheme.grid, offset: false, drawBorder: false, drawTicks: false }, 6875 afterBuildTicks: ET.yAxisAfterBuildTicksFromRange(), 6876 ticks: { 6877 color: axisTheme.tick, 6878 font: { family: ET.CHART_AXIS_FONT_FAMILY }, 6879 padding: 10, 6880 precision: 0, 6881 callback: v => ET.yAxisPctTickLabel(v) 6882 }, 6883 min: yMin, 6884 max: yMax, 6885 border: { display: false } 6886 } 6887 } 6888 } 6889 }); 6890 } 6891 6892 // California polls list function 6893 function createCaliforniaPollsList(container, series) { 6894 if (!container || !series || series.length === 0) { 6895 container.innerHTML = ''; 6896 setSearchPollSidebarListHeight(container, 0); 6897 return; 6898 } 6899 6900 const sortedSeries = series.slice().sort((a, b) => new Date(b.date) - new Date(a.date)); 6901 6902 let html = '';
6903 sortedSeries.forEach(poll => { 6904 const demKeys = ['D', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8']; 6905 const repKeys = ['R', 'R2']; 6906 let dSum = 0, rSum = 0, hasD = false, hasR = false; 6907 demKeys.forEach(k => { const v = poll[k]; if (typeof v === 'number' && isFinite(v)) { dSum += v; hasD = true; } }); 6908 repKeys.forEach(k => { const v = poll[k]; if (typeof v === 'number' && isFinite(v)) { rSum += v; hasR = true; } }); 6909 const margin = (hasD && hasR) ? (dSum - rSum) : 0; 6910 const lead = (!hasD || !hasR) ? 'Tie' : (margin > 0 ? 'D' : (margin < 0 ? 'R' : 'Tie')); 6911 const chipHtml = (typeof ET.sleekHoverGovRaceChipHtml === 'function') 6912 ? ET.sleekHoverGovRaceChipHtml(lead, Math.abs(margin), 'CA') 6913 : ET.sleekHoverChipHtml(lead, Math.abs(margin)); 6914 const rows = [ 6915 { name: 'Democrats', value: dSum, color: latestPollChipColor('D') }, 6916 { name: 'Republicans', value: rSum, color: latestPollChipColor('R') } 6917 ].sort((a, b) => b.value - a.value); 6918 6919 const dateStr = (typeof ET.fmtPollListDate === 'function') ? ET.fmtPollListDate(poll) : poll.date; 6920 6921 const pollsterRawCa = (typeof ET !== 'undefined' && ET.safePollsterText) ? ET.safePollsterText(poll) : escapePollsterTitleET.safePollsterText(poll); 6922 html += ` 6923 <li class="flex items-center justify-between gap-2 bg-slate-800/30 rounded-xl px-3 py-2 mb-2"> 6924 <div class="min-w-0 flex-1 pr-2 overflow-hidden"> 6925 <div class="font-medium text-white truncate" title="${escapePollsterTitle(poll.pollster)}">${pollsterRawCa}</div> 6926 <div class="text-[11px] text-slate-400">${dateStr} ⢠${poll.sample || 'â'}</div> 6927 </div> 6928 <div class="flex items-center gap-2 shrink-0"> 6929 ${searchPollCandsColHtml(rows)} 6930 <div class="w-[5.5rem] flex justify-end items-center flex-shrink-0"><span style="transform:scale(1.08);transform-origin:right center;display:inline-block">${chipHtml}</span></div> 6931 </div> 6932 </li> 6933 `; 6934 }); 6935 6936 container.innerHTML = html; 6937 setSearchPollSidebarListHeight(container, sortedSeries.length); 6938 } 6939 6940 // Michigan polls list function 6941 function createMichiganPollsList(container, series) { 6942 if (!container || !series || series.length === 0) { 6943 container.innerHTML = ''; 6944 setSearchPollSidebarListHeight(container, 0); 6945 return; 6946 } 6947 6948 const sortedSeries = series.slice().sort((a, b) => new Date(b.date) - new Date(a.date)); 6949 6950 let html = ''; 6951 sortedSeries.forEach(poll => { 6952 const rows = [ 6953 { letter: 'D', name: latestPollLastName(ET.govCandName('MI', 'D')), value: poll.D, color: latestPollChipColor('D') }, 6954 { letter: 'R', name: latestPollLastName(ET.govCandName('MI', 'R')), value: poll.R, color: latestPollChipColor('R') }, 6955 { letter: 'I', name: latestPollLastName(ET.govCandName('MI', 'I')), value: poll.I, color: latestPollChipColor('I') } 6956 ].filter(c => typeof c.value === 'number' && isFinite(c.value)); 6957 rows.sort((a, b) => b.value - a.value); 6958 let chipH; 6959 if (rows.length < 2) chipH = ET.sleekHoverChipHtml('Tie', 0); 6960 else { 6961 const margin = rows[0].value - rows[1].value; 6962 const ld = rows[0].letter; 6963 chipH = margin === 0 ? ET.sleekHoverChipHtml('Tie', 0) 6964 : (typeof ET.sleekHoverGovRaceChipHtml === 'function' 6965 ? ET.sleekHoverGovRaceChipHtml(ld, Math.abs(margin), 'MI') 6966 : ET.sleekHoverChipHtml(ld, Math.abs(margin))); 6967 } 6968 6969 const dateStr = (typeof ET.fmtPollListDate === 'function') ? ET.fmtPollListDate(poll) : poll.date; 6970 6971 const pollsterRawMi = (typeof ET !== 'undefined' && ET.safePollsterText) ? ET.safePollsterText(poll) : escapePollsterTitleET.safePollsterText(poll); 6972 html += ` 6973 <li class="flex items-center justify-between gap-2 bg-slate-800/30 rounded-xl px-3 py-2 mb-2"> 6974 <div class="min-w-0 flex-1 pr-2 overflow-hidden"> 6975 <div class="font-medium text-white truncate" title="${escapePollsterTitle(poll.pollster)}">${pollsterRawMi}</div> 6976 <div class="text-[11px] text-slate-400">${dateStr} ⢠${poll.sample || 'â'}</div> 6977 </div> 6978 <div class="flex items-center gap-2 shrink-0"> 6979 ${searchPollCandsColHtml(rows.map(function (r) { return { name: r.name, value: r.value, color: r.color }; }))} 6980 <div class="w-[5.5rem] flex justify-end items-center flex-shrink-0"><span style="transform:scale(1.08);transform-origin:right center;display:inline-block">${chipH}</span></div> 6981 </div> 6982 </li> 6983 `; 6984 }); 6985 6986 container.innerHTML = html; 6987 setSearchPollSidebarListHeight(container, sortedSeries.length); 6988 } 6989 6990 function initializeMichiganSenateSearchPreview() { 6991 /* Full search already owns the dropdown â don't wipe it back to MI-only. */ 6992 if (window.__pollsmaxFullSearchAllPollsInit === '1') return; 6993 if (window.__pollsmaxMichiganSenatePreviewInit === '1') return; 6994 window.__pollsmaxMichiganSenatePreviewInit = '1'; 6995 function run() { 6996 if (window.__pollsmaxFullSearchAllPollsInit === '1') return; 6997 if (!window.Chart || !window.ET || !ET.SENATE || !ET.SENATE.MI || typeof ET.candName !== 'function') { 6998 setTimeout(run, 50); 6999 return; 7000 } 7001 if (window.__pollsmaxFullSearchAllPollsInit === '1') return; 7002 var categorySelect = document.getElementById('categorySelect'); 7003 var entitySelect = document.getElementById('entitySelect'); 7004 var typeSelect = document.getElementById('typeSelect'); 7005 var districtSelect = document.getElementById('districtSelect'); 7006 var entityLink = document.getElementById('entityLink'); 7007 var entityArrow = document.getElementById('entityArrow'); 7008 var trendLabel = document.getElementById('trendLabel'); 7009 var ul = document.getElementById('searchTable'); 7010 var canvas = document.getElementById('searchChart'); 7011 if (!canvas || !ul) return; 7012 if (categorySelect) categorySelect.value = '2026-us-senate'; 7013 if (typeSelect) typeSelect.value = 'general-election'; 7014 if (entitySelect) { 7015 entitySelect.innerHTML = ''; 7016 var opt = document.createElement('option'); 7017 opt.value = 'MI'; 7018 opt.textContent = 'Michigan'; 7019 opt.dataset.key = 'MI'; 7020 entitySelect.appendChild(opt); 7021 entitySelect.value = 'MI'; 7022 entitySelect.disabled = false;
7023 } 7024 if (districtSelect) { 7025 districtSelect.innerHTML = ''; 7026 districtSelect.disabled = true; 7027 } 7028 if (trendLabel) { 7029 trendLabel.textContent = '2026 SENATE'; 7030 trendLabel.href = '/senate/'; 7031 } 7032 if (entityLink) { 7033 entityLink.textContent = 'Michigan'; 7034 entityLink.href = '/senate/michigan/'; 7035 } 7036 if (entityArrow) { 7037 entityArrow.href = '/senate/michigan/'; 7038 } 7039 var flagWrap = document.getElementById('searchPollFlagWrap'); 7040 var flagImg = document.getElementById('searchPollFlagImg'); 7041 if (flagWrap && flagImg) { 7042 flagWrap.classList.add('is-visible'); 7043 flagWrap.classList.remove('is-party-logo'); 7044 flagImg.src = '/images/mi.webp'; 7045 flagImg.alt = ''; 7046 } 7047 var series = ET.SENATE.MI || []; 7048 if (!series.length) { 7049 ul.innerHTML = ''; 7050 var emptyOverlay = document.getElementById('searchChartEmptyOverlay'); 7051 if (emptyOverlay) emptyOverlay.classList.remove('hidden'); 7052 return; 7053 } 7054 var existingChart = window.Chart && Chart.getChart ? Chart.getChart(canvas) : null; 7055 if (existingChart) { 7056 try { existingChart.destroy(); } catch (e) {} 7057 } 7058 if (canvas._pollsmaxChartInstance) { 7059 try { canvas._pollsmaxChartInstance.destroy(); } catch (e2) {} 7060 canvas._pollsmaxChartInstance = null; 7061 } 7062 var chart = createCustomChart( 7063 canvas, 7064 series, 7065 ET.candName('MI', 'D'), 7066 ET.candName('MI', 'R'), 7067 true, 7068 { blankSinglePoll: false, stateKey: 'MI' } 7069 ); 7070 if (chart) { 7071 canvas._pollsmaxChartInstance = chart; 7072 if (window.ET && typeof ET.applyPollsmaxHomeSearchAllPollsDesktopHoverHeader === 'function') { 7073 ET.applyPollsmaxHomeSearchAllPollsDesktopHoverHeader(chart, { layoutFlush: true }); 7074 } 7075 if (window.ET && typeof ET.scheduleSleekChartHoverAutoplay === 'function') { 7076 ET.scheduleSleekChartHoverAutoplay(chart); 7077 } 7078 } 7079 createCustomPollsList( 7080 ul, 7081 series, 7082 ET.candName('MI', 'D'), 7083 ET.candName('MI', 'R'), 7084 'MI' 7085 ); 7086 var emptyOverlay = document.getElementById('searchChartEmptyOverlay'); 7087 if (emptyOverlay) emptyOverlay.classList.add('hidden'); 7088 } 7089 run(); 7090 } 7091 7092 function setupFullSearchAllPollsLazyInit() { 7093 var section = document.getElementById('searchAllPollsSection'); 7094 if (!section) return; 7095 7096 function hasSearchUrlParams() { 7097 try { 7098 var p = new URLSearchParams(window.location.search); 7099 return !!(p.get('pm_race') || p.get('pm_entity') || p.get('pm_type') || p.get('pm_year')); 7100 } catch (e) { 7101 return false; 7102 } 7103 } 7104 7105 function runFullInit() { 7106 if (window.__pollsmaxFullSearchAllPollsInit === '1') return; 7107 window.__pollsmaxFullSearchAllPollsInit = '1'; 7108 7109 function searchUrlNeedsPrimaryDeps() { 7110 try { 7111 var p = new URLSearchParams(window.location.search); 7112 var race = p.get('pm_race') || ''; 7113 var type = p.get('pm_type') || ''; 7114 if (race === '2028-election') return true; 7115 if (type && type !== 'general-election' && type !== 'open-primary') return true; 7116 return false;
7117 } catch (e) { 7118 return false; 7119 } 7120 } 7121 7122 function startSearch() { 7123 window.__pollsmaxSearchRenderFp = ''; 7124 window.__pollsmaxSearchChartKind = ''; 7125 var canvas = document.getElementById('searchChart'); 7126 var keepMiPreview = false; 7127 try { 7128 var catEl = document.getElementById('categorySelect'); 7129 var entEl = document.getElementById('entitySelect'); 7130 var typEl = document.getElementById('typeSelect'); 7131 var catVal = catEl && catEl.value; 7132 var typVal = (typEl && typEl.value) || 'general-election'; 7133 var entKey = entEl && entEl.options[entEl.selectedIndex] && 7134 entEl.options[entEl.selectedIndex].dataset.key; 7135 keepMiPreview = !!(window.__pollsmaxMichiganSenatePreviewInit === '1' && 7136 catVal === '2026-us-senate' && entKey === 'MI' && 7137 typVal === 'general-election' && 7138 canvas && window.Chart && typeof Chart.getChart === 'function' && 7139 Chart.getChart(canvas)); 7140 } catch (eKeep) { 7141 keepMiPreview = false; 7142 } 7143 if (keepMiPreview) { 7144 window.__pollsmaxSearchRenderFp = '2026-us-senate|MI|general-election|'; 7145 window.__pollsmaxSearchChartKind = 'ge'; 7146 } else if (canvas && window.Chart && typeof Chart.getChart === 'function') { 7147 var existing = Chart.getChart(canvas); 7148 if (existing) { 7149 if (typeof ET !== 'undefined' && typeof ET.disposeSleekChartHoverChrome === 'function') { 7150 ET.disposeSleekChartHoverChrome(existing); 7151 } 7152 try { existing.destroy(); } catch (e) {} 7153 } 7154 if (canvas._pollsmaxChartInstance) { 7155 try { canvas._pollsmaxChartInstance.destroy(); } catch (e2) {} 7156 canvas._pollsmaxChartInstance = null; 7157 } 7158 canvas.dataset.pmChartNavBound = ''; 7159 } 7160 window.__pollsmaxHomeSearchPollsBound = null; 7161 initializeSearchLatestPolls(); 7162 } 7163 7164 var bootPromise; 7165 if (searchUrlNeedsPrimaryDeps() && typeof window.pollsmaxEnsureHomeSearchPrimaryDeps === 'function') { 7166 bootPromise = Promise.resolve(window.pollsmaxEnsureHomeSearchPrimaryDeps()); 7167 } else if (typeof window.pollsmaxEnsureHomeChartJs === 'function') { 7168 bootPromise = Promise.resolve(window.pollsmaxEnsureHomeChartJs()); 7169 } else { 7170 bootPromise = Promise.resolve(); 7171 } 7172 bootPromise.then(startSearch).catch(startSearch); 7173 } 7174 7175 if (hasSearchUrlParams()) { 7176 runFullInit(); 7177 return; 7178 } 7179 7180 var controls = section.querySelectorAll('select, button, a'); 7181 controls.forEach(function (el) { 7182 el.addEventListener('focus', runFullInit, { once: true }); 7183 el.addEventListener('pointerdown', runFullInit, { once: true }); 7184 el.addEventListener('touchstart', runFullInit, { once: true, passive: true }); 7185 }); 7186 7187 if ('IntersectionObserver' in window) { 7188 var sentinel = document.createElement('div'); 7189 sentinel.setAttribute('data-search-all-polls-lazy-sentinel', '1'); 7190 sentinel.style.height = '1px'; 7191 sentinel.style.width = '1px'; 7192 section.appendChild(sentinel); 7193 var obs = new IntersectionObserver(function (entries) {
7194 entries.forEach(function (entry) { 7195 if (entry.isIntersecting) { 7196 obs.disconnect(); 7197 runFullInit(); 7198 } 7199 }); 7200 }, { rootMargin: '300px 0px' }); 7201 obs.observe(sentinel); 7202 } else { 7203 setTimeout(runFullInit, 2500); 7204 } 7205 } 7206 7207 function refreshHomeHeaderLastUpdated() { 7208 if (window.ET && typeof ET.refreshHomeHeaderLastUpdated === 'function') { 7209 ET.refreshHomeHeaderLastUpdated(); 7210 } 7211 } 7212 7213 document.addEventListener('DOMContentLoaded', async () => { 7214 refreshHomeHeaderLastUpdated(); 7215 document.addEventListener('visibilitychange', function () { 7216 if (!document.hidden) refreshHomeHeaderLastUpdated(); 7217 }); 7218 7219 // Make standalone trailing-arrow spans next to links behave like the link. 7220 document.querySelectorAll('span.pm-trailing-arrow, span.search-all-polls-title-arrow, span.home-upcoming-elections__title-arrow, span.home-donate-pane__title-arrow').forEach(function (sp) { 7221 if (!sp) return; 7222 var prev = sp.previousElementSibling; 7223 if (!prev || prev.tagName !== 'A' || !prev.href) return; 7224 sp.style.cursor = 'pointer'; 7225 sp.addEventListener('click', function () { 7226 window.location.href = prev.href; 7227 }); 7228 }); 7229 7230 /* Search All Polls: Chart.js loads after first paint; MI preview boots then. */ 7231 window.pollsmaxBootHomeSearchPreview = function () { 7232 initializeMichiganSenateSearchPreview(); 7233 }; 7234 setupFullSearchAllPollsLazyInit(); 7235 7236 if (typeof ET !== 'undefined' && typeof ET.initForecastHubMidtermCountdown === 'function') { 7237 ET.initForecastHubMidtermCountdown(); 7238 } 7239 7240 // Update year if element exists 7241 var yearElement = document.getElementById('year'); 7242 if (yearElement) { 7243 yearElement.textContent = new Date().getFullYear(); 7244 } 7245 7246 // Bars (50/50) + countdown show immediately. Keep bars at preload until 7247 // senate + gov maps are ready, then fill bars and reveal maps together. 7248 // Hub-style prerendered maps: already painted; only wire interactivity + seat bars. 7249 var homeForecastRevealed = false; 7250 var HOME_HOUSE_BAR_IDS = { 7251 r: 'houseBarR', 7252 d: 'houseBarD', 7253 tie: 'houseBarTie', 7254 nr: 'houseNumR', 7255 nd: 'houseNumD', 7256 rFlip: 'houseBarRFlip', 7257 dFlip: 'houseBarDFlip' 7258 }; 7259 function homeMapIsPrerendered(svgId, attr) { 7260 var el = document.getElementById(svgId); 7261 return !!(el && el.getAttribute(attr) === '1' && ( 7262 el.querySelector('path.state') || el.querySelector('path.house-cd') 7263 )); 7264 } 7265 var homeSenatePrerendered = homeMapIsPrerendered('usMap', 'data-chamber-map-prerendered'); 7266 var homeGovPrerendered = homeMapIsPrerendered('govMap', 'data-chamber-map-prerendered'); 7267 var homeHousePrerendered = homeMapIsPrerendered('houseCdMap', 'data-house-map-prerendered'); 7268 function refreshHomeHouseForecast() { 7269 if (typeof ET === 'undefined') return; 7270 try { 7271 if (typeof ET.applyHouseHubBakedForecast === 'function') { 7272 if (!ET._houseHubBakedForecastApplied) ET.applyHouseHubBakedForecast(); 7273 } 7274 if (typeof ET.ensureHomeForecastMapUi === 'function') { 7275 ET.ensureHomeForecastMapUi('houseCdMap'); 7276 } 7277 if (typeof ET.refreshHouseHubSeatBar === 'function' && !ET.homeForecastDeferSeatBars) { 7278 ET.refreshHouseHubSeatBar(HOME_HOUSE_BAR_IDS, 'houseCdMap'); 7279 } 7280 if (typeof ET.refreshHouseCdMap === 'function') { 7281 ET.refreshHouseCdMap('houseCdMap'); 7282 } 7283 } catch (eHouse) { /* ignore */ } 7284 } 7285 function revealHomeForecast() { 7286 if (homeForecastRevealed) return; 7287 homeForecastRevealed = true; 7288 try { 7289 if (window.ET) { 7290 ET.homeForecastDeferSeatBars = false;
7291 ET.homeForecastShellBlank = false; 7292 } 7293 if (typeof ET !== 'undefined') { 7294 if (typeof ET.reapplyHomeChamberHubBakes === 'function') { 7295 ET.reapplyHomeChamberHubBakes(); 7296 } 7297 if (typeof ET.updateSeatBar === 'function') { 7298 ET.updateSeatBar({ r: 'barR', d: 'barD', tie: 'barTie', nr: 'numR', nd: 'numD', rFlip: 'barRFlip', dFlip: 'barDFlip' }); 7299 } 7300 if (typeof ET.updateGovSeatBar === 'function') { 7301 ET.updateGovSeatBar({ r: 'govBarR', d: 'govBarD', nr: 'govNumR', nd: 'govNumD', rFlip: 'govBarRFlip', dFlip: 'govBarDFlip' }); 7302 } 7303 if (typeof ET.refreshForecastHubSenateMap === 'function') { 7304 ET.refreshForecastHubSenateMap('usMap'); 7305 } 7306 if (typeof ET.refreshForecastHubGovMap === 'function') { 7307 ET.refreshForecastHubGovMap('govMap'); 7308 } 7309 refreshHomeHouseForecast(); 7310 } 7311 /* Same frame: both bars already updated; show maps with them. */ 7312 document.documentElement.classList.add('et-home-forecast-ready'); 7313 } catch (eReveal) { 7314 try { document.documentElement.classList.add('et-home-forecast-ready'); } catch (e2) { /* ignore */ } 7315 } 7316 } 7317 7318 try { 7319 if (window.ET) { 7320 /* Prerendered maps already have hub fills â don't blank them. */ 7321 ET.homeForecastShellBlank = !(homeSenatePrerendered && homeGovPrerendered); 7322 ET.homeForecastDeferSeatBars = true; 7323 } 7324 7325 async function waitForHomeForecastModel(timeoutMs) { 7326 timeoutMs = timeoutMs == null ? 4000 : timeoutMs; 7327 var done = false; 7328 function finish() { done = true; } 7329 var timedOut = new Promise(function (resolve) { 7330 setTimeout(resolve, timeoutMs); 7331 }); 7332 var ready = (async function () { 7333 /* POLLSMAX_HOME_FAST_BOOT: pull forecast-model.js if not already loaded. */ 7334 if (typeof window.pollsmaxWhenHomeForecastModelReady === 'function') { 7335 await new Promise(function (resolve) { 7336 window.pollsmaxWhenHomeForecastModelReady(resolve); 7337 }); 7338 } 7339 if (done) return; 7340 if (typeof ET.whenHomeForecastReady === 'function') { 7341 await new Promise(function (resolve) { ET.whenHomeForecastReady(resolve); }); 7342 return; 7343 } 7344 if (typeof ET.applyForecastModelRatings !== 'function') return; 7345 for (var fi = 0; fi < 80; fi++) { 7346 if (done) return; 7347 if (ET.applyForecastModelRatings()) return; 7348 await new Promise(function (r) { setTimeout(r, 50); }); 7349 } 7350 })(); 7351 await Promise.race([ready.then(finish, finish), timedOut]); 7352 } 7353 7354 function buildHomeMap(svgId, tipId, buildFn) { 7355 if (typeof ET === 'undefined' || typeof buildFn !== 'function') return Promise.resolve(); 7356 try { 7357 if (typeof ET.ensureHomeForecastMapUi === 'function') ET.ensureHomeForecastMapUi(svgId); 7358 } catch (eUi) { /* ignore */ } 7359 return Promise.resolve(buildFn.call(ET, svgId, tipId)).catch(function () { /* ignore */ }); 7360 } 7361 7362 function initHomePrerenderedChamber(chamber) { 7363 if (typeof ET === 'undefined' || typeof ET.initChamberHubPrerenderedMap !== 'function') return; 7364 try { 7365 ET.initChamberHubPrerenderedMap(chamber, { mapOnly: true }); 7366 } catch (eInit) { /* ignore */ } 7367 } 7368 7369 /* Wire Senate/Gov hover immediately â don't wait on House stack or forecast model. */ 7370 if (homeSenatePrerendered) initHomePrerenderedChamber('senate'); 7371 if (homeGovPrerendered) initHomePrerenderedChamber('gov'); 7372 /* Prerendered senate+gov: reveal fills/seat bars now â don't block on model/House. */ 7373 if (homeSenatePrerendered && homeGovPrerendered) { 7374 revealHomeForecast(); 7375 if (homeHousePrerendered) { 7376 try { document.documentElement.classList.add('et-home-house-map-ready'); } catch (eH0) { /* ignore */ } 7377 } 7378 } 7379 7380 async function wireHomeHouseWhenReady() { 7381 /* POLLSMAX_HOME_FAST_BOOT: load house stack on demand, then bind hover. */ 7382 if (typeof window.pollsmaxWhenHomeHouseStackReady === 'function') { 7383 await Promise.race([ 7384 new Promise(function (resolve) { 7385 window.pollsmaxWhenHomeHouseStackReady(resolve); 7386 }), 7387 new Promise(function (resolve) { setTimeout(resolve, 6000); }) 7388 ]); 7389 } 7390 if (homeHousePrerendered && typeof ET.bindHouseCdMapPrerenderedHover === 'function') { 7391 try { ET.bindHouseCdMapPrerenderedHover('houseCdMap', 'houseMapTip'); } catch (eHouseBind) { /* ignore */ } 7392 } 7393 } 7394 7395 var houseWirePromise = wireHomeHouseWhenReady(); 7396 7397 /* Model still warms seat-bar precision, but must not gate map reveal. */ 7398 var modelPromise = waitForHomeForecastModel(4000); 7399 7400 var houseMapPromise = Promise.all([houseWirePromise, modelPromise]).then(function () { 7401 return buildHomeMap('houseCdMap', 'houseMapTip', ET.buildHouseCdMap); 7402 }).then(function () {
7403 refreshHomeHouseForecast(); 7404 try { 7405 document.documentElement.classList.add('et-home-house-map-ready'); 7406 } catch (eHouseReady) { /* ignore */ } 7407 }); 7408 7409 if (!homeSenatePrerendered) { 7410 await modelPromise; 7411 await buildHomeMap('usMap', 'mapTip', ET.buildMap); 7412 } else { 7413 initHomePrerenderedChamber('senate'); 7414 } 7415 if (!homeGovPrerendered) { 7416 await modelPromise; 7417 await buildHomeMap('govMap', 'govMapTip', ET.buildGovMap); 7418 } else { 7419 initHomePrerenderedChamber('gov'); 7420 } 7421 7422 revealHomeForecast(); 7423 await houseMapPromise; 7424 try { 7425 document.documentElement.classList.add('et-home-house-map-ready'); 7426 } catch (eHouseReady2) { /* ignore */ } 7427 } catch (error) { 7428 revealHomeForecast(); 7429 try { 7430 document.documentElement.classList.add('et-home-house-map-ready'); 7431 } catch (eHouseReady3) { /* ignore */ } 7432 } 7433 // Safety: never leave the gate closed if something hangs. 7434 setTimeout(revealHomeForecast, 2500); 7435 7436 try { 7437 setupDailyUpdates(); 7438 } catch (error) { /* ignore */ } 7439 7440 setTimeout(function () { 7441 updateAllMargins(); 7442 }, 500); 7443 7444 if (typeof ET !== 'undefined' && typeof ET.latestAvgByName === 'function' && typeof ET.CANDIDATES !== 'undefined') { 7445 updateKeyRacesCandidates(); 7446 } else { 7447 setTimeout(function () { 7448 updateKeyRacesCandidates(); 7449 }, 500); 7450 } 7451 7452 if (typeof ET !== 'undefined' && typeof ET.govSeries === 'function' && typeof ET.govCandName === 'function') { 7453 updateGovernorRacesCandidates(); 7454 } else { 7455 setTimeout(function () { 7456 updateGovernorRacesCandidates(); 7457 }, 500); 7458 } 7459 7460 if (typeof ET !== 'undefined' && typeof ET.homeKeyHouseProminentRaceRows === 'function') { 7461 updateKeyHouseRacesCandidates(); 7462 } else { 7463 setTimeout(function () { 7464 updateKeyHouseRacesCandidates(); 7465 }, 500); 7466 } 7467 7468 setTimeout(function () { 7469 updateKeyRacesCandidates(); 7470 updateGovernorRacesCandidates(); 7471 updateKeyHouseRacesCandidates(); 7472 }, 1000); 7473 7474 // NYC mini chart canvas is not on the home page; keep call for compatibility. 7475 var nycData = [ 7476 { label: 'Mamdani', data: [25, 25.2, 25.5, 26, 26.8, 27.5, 28, 28.8, 29.5, 30, 30.8, 31.5, 32, 32.8, 33.5, 34, 34.8, 35.5, 36, 36.8, 37.5, 38, 38.8, 39.5, 40, 40.8, 41.5, 42, 42.8, 43.5, 44, 44.8, 45.5, 46, 46.8, 47.5, 48, 48.8, 49.5, 50, 50.8, 51.5, 52] }, 7477 { label: 'Cuomo', data: [39, 38.8, 38.5, 38, 37.8, 37.5, 37, 36.8, 36.5, 36, 35.8, 35.5, 35, 34.8, 34.5, 34, 33.8, 33.5, 33, 32.8, 32.5, 32, 31.8, 31.5, 31, 30.8, 30.5, 30, 29.8, 29.5, 29, 28.8, 28.5, 28, 27.8, 27.5, 27, 26.8, 26.5, 26, 25.8, 25.5, 25, 24.8, 24.5, 24, 23.8, 23.5, 23, 22.8, 22.5, 22, 21.8, 21.5, 21, 20.8, 20.5, 20, 19.8, 19.5, 19] }, 7478 { label: 'Sliwa', data: [12, 12.2, 12.5, 13, 13.2, 13.5, 14, 14.2, 14.5, 15, 15.2, 15.5, 16, 16.2, 16.5, 17, 17.2, 17.5, 18, 18.2, 18.5, 19, 19.2, 19.5, 20, 19.8, 19.5, 19, 18.8, 18.5, 18, 17.8, 17.5, 17, 16.8, 16.5, 16, 15.8, 15.5, 15, 14.8, 14.5, 14] }, 7479 { label: 'Adams', data: [10, 10.2, 10.5, 11, 11.2, 11.5, 12, 12.2, 12.5, 13, 13.2, 13.5, 14, 14.2, 14.5, 15, 15.2, 15.5, 16, 15.8, 15.5, 15, 14.8, 14.5, 14, 13.8, 13.5, 13, 12.8, 12.5, 12, 11.8, 11.5, 11] } 7480 ]; 7481 var nycColors = ['#0c6df6', '#ffd700', '#f42726', '#64748b']; 7482 var nycLabels = Array.from({ length: 43 }, function (_, i) { return 'D' + (i + 1); }); 7483 renderMiniChart('nycChart', nycData, nycColors, nycLabels); 7484 }); 7485 7486 </script>
7486 7487 7488<!-- Footer --> 7489 <footer class="border-t border-slate-700 mt-32" data-et-site-footer="1"> 7490 <div class="home-footer-inner w-full max-w-none px-4 sm:px-6 lg:px-10 xl:px-14 pt-8 pb-5"> 7491 <div class="home-footer-top lg:overflow-visible"> 7492 <div class="home-footer-brand flex flex-col shrink-0 relative"> 7493 <a href="/" class="inline-block mb-4 self-start"> 7494 <img src="/images/logo.webp" alt="Pollsmax" class="h-24 w-auto" /> 7495 </a> 7496 <div class="home-footer-brand-meta mt-[13px] space-y-2 text-left max-w-full overflow-visible"> 7497 <a href="https://x.com/Pollsmax" target="_blank" rel="noopener noreferrer" 7498 class="hover:opacity-70 transition-opacity inline-block self-start"> 7499 <img src="/images/twitter.svg" alt="Pollsmax on X" class="h-6 w-6" /> 7500 </a> 7501 <p class="site-footer-tagline text-slate-400 text-sm leading-relaxed lg:whitespace-nowrap" 7502 data-et-tagline-desktop="Only the facts, no opinions. Pollsmax is the #1 site for political polls."> 7503 Only the facts, no opinions.<br class="md:hidden"> Pollsmax is the #1 site for political polls. 7504 </p> 7505 <p class="site-footer-copyright text-slate-500 text-sm"> 7506 © 2026 Pollsmax. All rights reserved. 7507 </p> 7508 </div> 7509 </div> 7510 7511 <div class="home-footer-mobile-nav site-footer-links-col min-w-0"> 7512 <div class="site-footer-primary-nav flex flex-wrap items-baseline gap-x-[40px] gap-y-2"> 7513 <a href="/" 7514 class="text-white font-medium text-base tracking-wide hover:text-slate-200 transition-colors whitespace-nowrap">Home</a> 7515 <a href="/senate/" 7516 class="text-white font-medium text-base tracking-wide hover:text-slate-200 transition-colors whitespace-nowrap">2026 7517 Senate</a> 7518 <a href="/2026-us-house/" 7519 class="text-white font-medium text-base tracking-wide hover:text-slate-200 transition-colors whitespace-nowrap">2026 7520 House</a> 7521 <a href="/governor/" 7522 class="text-white font-medium text-base tracking-wide hover:text-slate-200 transition-colors whitespace-nowrap">2026 7523 Governors</a> 7524 <a href="/2028-president/" 7525 class="text-white font-medium text-base tracking-wide hover:text-slate-200 transition-colors whitespace-nowrap">2028 7526 President</a> 7527 </div> 7528 <div class="site-footer-secondary-nav flex flex-wrap items-baseline gap-x-[40px] gap-y-2 mt-3"> 7529 <a href="/latest-polls/" 7530 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">Latest 7531 Polls</a> 7532 <a href="/upcoming-elections/" 7533 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">Primary 7534 Calendar</a> 7535 <a href="/approval/trump/" 7536 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">Trump 7537 Approval</a> 7538 <a href="/approval/generic-ballot/" 7539 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">Generic 7540 Ballot</a> 7541 <a href="/2028-democratic-primary/" 7542 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">2028 7543 Democratic Primary</a> 7544 <a href="/2028-republican-primary/" 7545 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">2028 7546 Republican Primary</a> 7547 <a href="/electoral-history/" 7548 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">Electoral 7549 History</a> 7550 <a href="/election-map/fillable-maps/" 7551 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">Fillable Maps</a> 7552 </div> 7553 7554 <hr class="site-footer-divider border-slate-700/80 mt-6 mb-6" /> 7555 7556 <div class="home-footer-cols"> 7557 <div class="min-w-0"> 7558 <h3 class="text-white font-semibold mb-[13px] text-base tracking-wide whitespace-nowrap">Key Senate Races</h3> 7559 <div class="home-footer-states-grid"> 7560 <a href="/senate/alaska/" 7561 class="text-slate-400 hover:text-white text-sm transition-colors">Alaska</a> 7562 <a href="/senate/georgia/" 7563 class="text-slate-400 hover:text-white text-sm transition-colors">Georgia</a> 7564 <a href="/senate/iowa/" 7565 class="text-slate-400 hover:text-white text-sm transition-colors">Iowa</a> 7566 <a href="/senate/maine/" 7567 class="text-slate-400 hover:text-white text-sm transition-colors">Maine</a> 7568 <a href="/senate/michigan/" 7569 class="text-slate-400 hover:text-white text-sm transition-colors">Michigan</a> 7570 <a href="/senate/nebraska/" 7571 class="text-slate-400 hover:text-white text-sm transition-colors">Nebraska</a> 7572 <a href="/senate/new-hampshire/" 7573 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">New 7574 Hampshire</a> 7575 <a href="/senate/north-carolina/" 7576 class="text-slate-400 hover:text-white text-sm transition-colors whitespace-nowrap">North 7577 Carolina</a> 7578 <a href="/senate/ohio/" 7579 class="text-slate-400 hover:text-white text-sm transition-colors">Ohio</a> 7580 <a href="/senate/texas/" 7581 class="text-slate-400 hover:text-white text-sm transition-colors">Texas</a> 7582 </div> 7583 </div> 7584 7585 <div class="min-w-0 sm:ml-[75px]"> 7586 <h3 class="text-white font-semibold mb-[13px] text-base tracking-wide whitespace-nowrap">Key 7587 Governor Races</h3> 7588 <div class="home-footer-states-grid"> 7589 <a href="/governor/arizona/" 7590 class="text-slate-400 hover:text-white text-sm transition-colors">Arizona</a> 7591 <a href="/governor/california/" 7592 class="text-slate-400 hover:text-white text-sm transition-colors">California</a> 7593 <a href="/governor/florida/" 7594 class="text-slate-400 hover:text-white text-sm transition-colors">Florida</a> 7595 <a href="/governor/georgia/" 7596 class="text-slate-400 hover:text-white text-sm transition-colors">Georgia</a> 7597 <a href="/governor/iowa/" 7598 class="text-slate-400 hover:text-white text-sm transition-colors">Iowa</a> 7599 <a href="/governor/kansas/democratic-primary/" 7600 class="text-slate-400 hover:text-white text-sm transition-colors">Kansas</a> 7601 <a href="/governor/michigan/" 7602 class="text-slate-400 hover:text-white text-sm transition-colors">Michigan</a> 7603 <a href="/governor/nevada/" 7604 class="text-slate-400 hover:text-white text-sm transition-colors">Nevada</a> 7605 <a href="/governor/ohio/" 7606 class="text-slate-400 hover:text-white text-sm transition-colors">Ohio</a> 7607 <a href="/governor/wisconsin/" 7608 class="text-slate-400 hover:text-white text-sm transition-colors">Wisconsin</a> 7609 </div> 7610 </div> 7611 </div> 7612 </div> 7613 7614 <nav class="home-footer-pc-cols" aria-label="Footer"> 7615 <div class="home-footer-col" data-home-footer-hide="6"> 7616 <a class="home-footer-col__title" href="/senate/">2026 Senate</a> 7617 <ul class="home-footer-col__list"> 7618 <li><a href="/senate/alaska/forecast/">Alaska Senate</a></li> 7619 <li><a href="/senate/maine/forecast/">Maine Senate</a></li> 7620 <li><a href="/senate/michigan/forecast/">Michigan Senate</a></li> 7621 <li><a href="/senate/ohio/forecast/">Ohio Senate</a></li> 7622 <li><a href="/senate/texas/forecast/">Texas Senate</a></li> 7623 </ul> 7624 </div> 7625 <div class="home-footer-col" data-home-footer-hide="5"> 7626 <a class="home-footer-col__title" href="/2026-us-house/">
76262026 House</a> 7627 <ul class="home-footer-col__list"> 7628 <li><a href="/2026-us-house/iowa-3/forecast/">IA-3 House</a></li> 7629 <li><a href="/2026-us-house/maine-2/forecast/">ME-2 House</a></li> 7630 <li><a href="/2026-us-house/new-jersey-7/forecast/">NJ-7 House</a></li> 7631 <li><a href="/2026-us-house/new-york-17/forecast/">NY-17 House</a></li> 7632 <li><a href="/2026-us-house/pennsylvania-7/forecast/">PA-7 House</a></li> 7633 </ul> 7634 </div> 7635 <div class="home-footer-col" data-home-footer-hide="4"> 7636 <a class="home-footer-col__title" href="/governor/">2026 Governors</a> 7637 <ul class="home-footer-col__list"> 7638 <li><a href="/governor/georgia/forecast/">Georgia Governor</a></li> 7639 <li><a href="/governor/iowa/forecast/">Iowa Governor</a></li> 7640 <li><a href="/governor/nevada/forecast/">Nevada Governor</a></li> 7641 <li><a href="/governor/ohio/forecast/">Ohio Governor</a></li> 7642 <li><a href="/governor/wisconsin/forecast/">Wisconsin Governor</a></li> 7643 </ul> 7644 </div> 7645 <div class="home-footer-col" data-home-footer-hide="3"> 7646 <a class="home-footer-col__title" href="/latest-polls/">Polling Data</a> 7647 <ul class="home-footer-col__list"> 7648 <li><a href="/latest-polls/?year=2026&race=senate">Senate Polls</a></li> 7649 <li><a href="/latest-polls/?year=2026&race=house">House Polls</a></li> 7650 <li><a href="/latest-polls/?year=2026&race=governor">Governor Polls</a></li> 7651 <li><a href="/approval/trump/">Trump Approval</a></li> 7652 <li><a href="/approval/generic-ballot/">Generic Ballot</a></li> 7653 </ul> 7654 </div> 7655 <div class="home-footer-col" data-home-footer-hide="2"> 7656 <a class="home-footer-col__title" href="/2028-president/">2028 President</a> 7657 <ul class="home-footer-col__list"> 7658 <li><a href="/2028-democratic-primary/">Democratic Primary</a></li> 7659 <li><a href="/2028-republican-primary/">Republican Primary</a></li> 7660 </ul> 7661 </div> 7662 <div class="home-footer-col" data-home-footer-hide="1"> 7663 <a class="home-footer-col__title" href="/election-map/fillable-maps/">Fillable Maps</a> 7664 <ul class="home-footer-col__list"> 7665 <li><a href="/election-map/new-president-map/">2028 President</a></li> 7666 <li><a href="/election-map/new-senate-map/">2026 Senate</a></li> 7667 <li><a href="/election-map/new-house-map/">
76672026 House</a></li> 7668 <li><a href="/election-map/new-governor-map/">2026 Governors</a></li> 7669 </ul> 7670 </div> 7671 </nav> 7672 </div> 7673 7674 <hr class="home-footer-pc-rule" /> 7675 7676 <div class="home-footer-pc-bottom"> 7677 <p class="site-footer-copyright"> 7678 © 2026 <span class="relative inline-block">Pollsmax<button type="button" tabindex="-1" 7679 id="pollsmaxFooterHeaderToggle" 7680 class="absolute inset-0 z-[1] opacity-0 cursor-pointer border-0 p-0 m-0 bg-transparent" 7681 aria-hidden="true"></button></span>. All rights reserved. 7682 </p> 7683 <nav class="home-footer-pc-legal" aria-label="Methodology and legal"> 7684 <a href="/about/">About</a> 7685 <a href="/forecast-methodology/">Forecast Methodology</a> 7686 <a href="/polling-methodology/">Polling Methodology</a> 7687 <a href="/contact/">Contact</a> 7688 <a href="/privacy-policy/">Privacy Policy</a> 7689 <a href="/terms-and-conditions/">Terms & Conditions</a> 7690 </nav> 7691 </div> 7692 </div> 7693 </footer> 7694 7695 7696
7696<script> 7697 (function fitHomeFooterPcCols() { 7698 var footer, top, brand, colsNav, tagline; 7699 var hideOrder = ['1', '2', '3', '4', '5', '6']; 7700 var ticking = false; 7701 7702 function els() { 7703 footer = document.querySelector('body.pollsmax-home-page footer[data-et-site-footer="1"]'); 7704 if (!footer) return false; 7705 top = footer.querySelector('.home-footer-top'); 7706 brand = footer.querySelector('.home-footer-brand'); 7707 colsNav = footer.querySelector('.home-footer-pc-cols'); 7708 tagline = footer.querySelector('.home-footer-brand .site-footer-tagline'); 7709 return !!(top && brand && colsNav); 7710 } 7711 7712 function isPc() { 7713 try { 7714 return !!(window.matchMedia && window.matchMedia('(min-width: 1024px)').matches); 7715 } catch (e) { 7716 return false; 7717 } 7718 } 7719 7720 function cols() { 7721 return colsNav ? colsNav.querySelectorAll('.home-footer-col') : []; 7722 } 7723 7724 function reset() { 7725 var list = cols(); 7726 var i; 7727 for (i = 0; i < list.length; i++) list[i].classList.remove('home-footer-col--omit'); 7728 } 7729 7730 function gapPx(el, fallback) { 7731 if (!el) return fallback; 7732 var cs = window.getComputedStyle(el); 7733 var g = parseFloat(cs.columnGap); 7734 if (!isFinite(g) || g <= 0) g = parseFloat(cs.gap); 7735 return (isFinite(g) && g > 0) ? g : fallback; 7736 } 7737 7738 function measureNowrap(el) { 7739 if (!el) return 0; 7740 return Math.ceil(Math.max(el.scrollWidth, el.getBoundingClientRect().width)); 7741 } 7742 7743 function brandWidth() { 7744 var w = brand ? brand.getBoundingClientRect().width : 0; 7745 var logo; 7746 var meta; 7747 if (brand) { 7748 logo = brand.querySelector('a'); 7749 meta = brand.querySelector('.home-footer-brand-meta'); 7750 if (logo) w = Math.max(w, logo.getBoundingClientRect().width); 7751 if (meta) w = Math.max(w, meta.getBoundingClientRect().width); 7752 } 7753 if (tagline) w = Math.max(w, measureNowrap(tagline)); 7754 return w; 7755 } 7756 7757 function visibleWidth() { 7758 var list = cols(); 7759 var w = 0; 7760 var n = 0; 7761 var i; 7762 for (i = 0; i < list.length; i++) { 7763 if (list[i].classList.contains('home-footer-col--omit')) continue; 7764 w += list[i].offsetWidth; 7765 n++; 7766 } 7767 if (n > 1) w += gapPx(colsNav, 40) * (n - 1); 7768 return w; 7769 } 7770 7771 function overflowing(avail) { 7772 var colAvail = colsNav ? colsNav.clientWidth : avail; 7773 if (visibleWidth() > colAvail - 4) return true; 7774 if (top.scrollWidth > avail + 1) return true; 7775 return false; 7776 } 7777 7778 function fit() { 7779 if (!els()) return; 7780 reset(); 7781 if (!isPc()) return; 7782 var avail = top.clientWidth; 7783 if (avail <= 0) return; 7784 var i; 7785 var key; 7786 var list; 7787 var j; 7788 for (i = 0; i < hideOrder.length; i++) { 7789 if (!overflowing(avail)) return; 7790 key = hideOrder[i]; 7791 list = cols(); 7792 for (j = 0; j < list.length; j++) { 7793 if (list[j].getAttribute('data-home-footer-hide') === key) { 7794 list[j].classList.add('home-footer-col--omit'); 7795 } 7796 } 7797 } 7798 } 7799 7800 function schedule() { 7801 if (ticking) return; 7802 ticking = true; 7803 window.requestAnimationFrame(function () { 7804 ticking = false; 7805 fit(); 7806 }); 7807 } 7808 7809 function boot() { 7810 fit(); 7811 window.addEventListener('resize', schedule); 7812 if (document.fonts && document.fonts.ready && typeof document.fonts.ready.then === 'function') { 7813 document.fonts.ready.then(schedule); 7814 } 7815 window.setTimeout(fit, 120); 7816 window.setTimeout(fit, 600); 7817 } 7818 7819 if (document.readyState === 'loading') { 7820 document.addEventListener('DOMContentLoaded', boot, { once: true }); 7821 } else { 7822 boot(); 7823 } 7824 })(); 7825 </script>
7825 7826
7826<script defer src="/assets/home-ads-20260901c.js"></script>
7826 7827</body> 7828 7829</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.