PageSourceSearch

https://nfldrafthq.com/assets/NFLOddsCalculatorHTML-BFOQomYk.js

js nfldrafthq.com collected 2026-10-05 19:58:13 UTC 82,018 bytes, 2,017 lines download raw bytes

1import{r as n,s,j as t,P as l,b as d}from"./index-Ba4BgsO5.js";function c(){return n.useEffect(()=>{s(d.ODDS_CALCULATOR)},[]),n.useEffect(()=>{const r=`<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <title>NFL Point Spread Calculator | WQI Power Rankings Odds | NFL Draft HQ</title>
7    <meta name="description" content="Calculate NFL point spreads using our proprietary WQI (Win Quality Index) system. Drag-and-drop power rankings to predict matchup odds. AI-powered odds analyzer for NFL games.">
8    <meta name="keywords" content="NFL point spread calculator, NFL odds calculator, power rankings, WQI calculator, NFL matchup predictor, Vegas odds comparison, NFL predictions, point spread odds">
9    <meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">
10    <meta name="language" content="English">
11    <meta name="revisit-after" content="7 days">
12    <link rel="canonical" href="https://nfldrafthq.com/nfl-odds-calculator">
13    <meta name="theme-color" content="#2563eb">
14    <link rel="apple-touch-icon" href="https://nfldrafthq.com/public/favicon-64.png">
15    
16    <!-- Open Graph Tags for Social Sharing -->
17    <meta property="og:title" content="NFL Point Spread Calculator | WQI Power Rankings | NFL Draft HQ">
18    <meta property="og:description" content="Calculate NFL point spreads using our proprietary WQI (Win Quality Index) system. Drag-and-drop power rankings to predict matchup odds. AI-powered odds analyzer for NFL games.">
19    <meta property="og:url" content="https://nfldrafthq.com/nfl-odds-calculator">
20    <meta property="og:type" content="website">
21    <meta property="og:image" content="https://nfldrafthq.com/public/og-image-nfl-calculator.png">
22    <meta property="og:image:width" content="1200">
23    <meta property="og:image:height" content="630">
24    <meta property="og:site_name" content="NFL Draft HQ">
25    <meta property="og:locale" content="en_US">
26    
27    <!-- Twitter Card Tags -->
28    <meta name="twitter:card" content="summary_large_image">
29    <meta name="twitter:title" content="NFL Point Spread Calculator | WQI Power Rankings">
30    <meta name="twitter:description" content="Calculate NFL point spreads using our proprietary WQI system. Drag-and-drop power rankings to predict odds.">
31    <meta name="twitter:image" content="https://nfldrafthq.com/public/og-image-nfl-calculator.png">
32    <meta name="twitter:creator" content="@NFLDraftHQ">
33    <meta name="twitter:site" content="@NFLDraftHQ">
34    
35    <!-- JSON-LD Tool Schema -->
36    <script type="application/ld+json">
37    {
38      "@context": "https://schema.org",
39      "@type": "Tool",
40      "name": "NFL Point Spread Calculator",
41      "description": "Calculate NFL point spreads using our proprietary WQI (Win Quality Index) system. Drag-and-drop power rankings to predict matchup odds.",
42      "url": "https://nfldrafthq.com/nfl-odds-calculator",
43      "applicationCategory": "UtilityApplication",
44      "offers": {
45        "@type": "Offer",
46        "price": "0",
47        "priceCurrency": "USD"
48      },
49      "publisher": {
50        "@type": "Organization",
51        "name": "NFL Draft HQ",
52        "url": "https://nfldrafthq.com"
53      }
54    }
55    <\/script>
56    
57    <!-- JSON-LD FAQPage Schema -->
58    <script type="application/ld+json">
59    {
60      "@context": "https://schema.org",
61      "@type": "FAQPage",
62      "mainEntity": [
63        {
64          "@type": "Question",
65          "name": "How does the NFL Point Spread Calculator work?",
66          "acceptedAnswer": {
67            "@type": "Answer",
68            "text": "Our calculator uses the Win Quality Index (WQI), a proprietary system that ranks NFL teams based on performance. You drag-and-drop teams to create custom power rankings, select an away and home team, and our algorithm calculates the predicted point spread for that matchup."
69          }
70        },
71        {
72          "@type": "Question",
73          "name": "What is the WQI (Win Quality Index)?",
74          "acceptedAnswer": {
75            "@type": "Answer",
76            "text": "The Win Quality Index (WQI) is our proprietary AI-powered metric that evaluates NFL team performance by analyzing the strength and quality of wins and losses throughout the season, providing more accurate power rankings than traditional metrics."
77          }
78        },
79        {
80          "@type": "Question",
81          "name": "Can I create custom power rankings?",
82          "acceptedAnswer": {
83            "@type": "Answer",
84            "text": "Yes! You have full control to customize power rankings by dragging and dropping team cards into your preferred order. Your custom arrangement will be used to calculate point spreads for any matchup."
85          }
86        },
87        {
88          "@type": "Question",
89          "name": "How does the neutral site option work?",
90          "acceptedAnswer": {
91            "@type": "Answer",
92            "text": "When you toggle the 'Neutral Site' option, the calculator removes the home-field advantage bonus from the point spread calculation, giving you odds as if the game were played at a neutral location."
93          }
94        },
95        {
96          "@type": "Question",
97          "name": "Are these spreads accurate predictions of Vegas odds?",
98          "acceptedAnswer": {
99            "@type": "Answer",
100            "text": "Our spreads are for entertainment purposes only and are generated by our proprietary WQI algorithm. They provide an alternative perspective to Vegas spreads but should not be used as betting advice."
101          }
102        }
103      ]
104    }
105    <\/script>
106    
107    <!-- JSON-LD BreadcrumbList Schema -->
108    <script type="application/ld+json">
109    {
110      "@context": "https://schema.org",
111      "@type": "BreadcrumbList",
112      "itemListElement": [
113        {
114          "@type": "ListItem",
115          "position": 1,
116          "name": "Home",
117          "item": "https://nfldrafthq.com/"
118        },
119        {
120          "@type": "ListItem",
121          "position": 2,
122          "name": "NFL Odds Calculator",
123          "item": "https://nfldrafthq.com/nfl-odds-calculator"
124        }
125      ]
126    }
127    <\/script>
128    
129    <style>
130        /* Hide embedded navigation - use PageHeader component instead */
131        .main-header {
132            display: none !important;
133        }
134        body { 
135            font-family: Arial, sans-serif; 
136            padding: 0; 
137            margin: 0;
138            background: #f0f0f0;
139            -webkit-font-smoothing: antialiased;
140            -moz-osx-font-smoothing: grayscale;
141        }
142        h1, h2 {
143            text-align: center;
144            color: #333;
145            text-rendering: optimizeLegibility;
146        }
147        .content {
148            max-width: 1200px;
149            margin: auto;
150        }
151        .container { 
152            display: flex; 
153            gap: 20px; 
154            flex-wrap: wrap;
155            justify-content: center;
156            align-items: center;
157        }
158        .grid { 
159            display: grid; 
160            grid-template-columns: repeat(8, 1fr);
161            gap: 10px; 
162            width: 100%;
163            max-width: 800px;
164            margin-top: 20px;
165        }
166        @media (max-width: 768px) {
167            body {
168                overflow-x: hidden;
169                overflow-y: visible !important;
170                height: auto !important;
171                min-height: auto !important;
172                padding-bottom: 0 !important;
173            }
174            html {
175                overflow-y: visible !important;
176                height: auto !important;
177                min-height: auto !important;
178            }
179            .content {
180                padding: 10px !important;
181            }
182            .grid {
183                grid-template-columns: repeat(4, 1fr);
184                gap: 5px;
185                margin-top: -65px !important;
186                width: calc(100vw - 20px);
187                max-width: calc(100vw - 20px);
188            }
189            .container {
190                flex-direction: column-reverse !important;
191                gap: 3px;
192                overflow-y: visible !important;
193            }
194            .content {
195                height: auto !important;
196                overflow: visible !important;
197            }
198            #wqi-description {
199                margin: 5px auto 5px !important;
200                padding-bottom: 0 !important;
201            }
202            .copyright {
203                display: none !important;
204            }
205            /* Hide the footer inside the iframe on mobile */
206            footer, .footer {
207                display: none !important;
208            }
209            .controls {
210                width: calc(100vw - 24px);
211                max-width: calc(100vw - 24px);
212                margin-bottom: 0px;
213                padding: 12px;
214                box-sizing: border-box;
215                position: relative !important;
216                top: 0px !important;
217                transform: scale(0.8);
218                transform-origin: top center;
219            }
220            .controls button {
221                transform: scale(0.8);
222            }
223            .mobile-header-container {
224                border-bottom: none !important;
225            }
226            .team-btn, .selected-team {
227                min-height: 45px;
228                min-width: 45px;
229                padding: 4px;
230                font-size: 11px;
231            }
232            .selected-team {
233                width: 81px !important;
234                height: 81px !important;
235                min-height: 81px !important;
236                min-width: 81px !important;
237                flex: 1 !important;
238                padding: 4px !important;
239                display: flex !important;
240                align-items: center !important;
241                justify-content: center !important;
242            }
243            .team-container {
244                gap: 10px;
245                width: 100%;
246            }
247            .at-sign {
248                font-size: 16px;
249            }
250            .team-btn small {
251                font-size: 9px !important;
252                margin-top: 1px;
253            }
254            h2 {
255                font-size: 14px !important;
256                margin: 4px 0 !important;
257                white-space: nowrap;
258            }
259            .neutral-check {
260                flex-direction: column;
261            }
262            .how-it-works-btn {
263                margin-left: 0;
264                margin-top: 8px;
265                width: 100%;
266            }
267        }
268        .team-btn, .selected-team {
269            padding: 10px;
270            border: 1px solid #1d4ed8;
271            border-radius: 5px;
272            cursor: move;
273            font-weight: bold;
274            text-align: center;
275            transition: transform 0.2s;
276            min-height: 80px;
277            min-width: 80px;
278            display: flex;
279            flex-direction: column;
280            justify-content: center;
281            box-sizing: border-box;
282            text-rendering: geometricPrecision;
283            background: #2563eb;
284            color: white;
285            box-shadow: 6px 6px 12px rgba(59, 130, 246, 0.5), inset -3px -3px 6px rgba(59, 130, 246, 0.4), inset 3px 3px 6px rgba(255, 255, 255, 0.8);
286            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
287        }
288        .team-btn small {
289            margin-top: 4px;
290            display: block;
291            font-weight: normal;
292            font-size: 13px !important;
293        }
294        .rank-separator {
295            width: 50%;
296            border: 0.5px solid rgba(255,255,255,0.3);
297            margin: 4px auto;
298        }
299        .selected-team {
300            background: #666;
301            border: 1px solid #1d4ed8;
302            min-height: 40px;
303            min-width: 40px;
304            height: 60px;
305            flex: 1;
306            color: white;
307            box-shadow: 6px 6px 12px rgba(59, 130, 246, 0.5), inset -3px -3px 6px rgba(59, 130, 246, 0.4), inset 3px 3px 6px rgba(255, 255, 255, 0.8);
308            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
309        }
310        .controls { 
311            width: 100%;
312            max-width: 300px; 
313            background: white;
314            padding: 20px;
315            border-radius: 10px;
316            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
317            border: 2px solid #000;
318            position: relative;
319            top: -30px;
320        }
321        button { 
322            padding: 10px 20px; 
323            margin: 5px; 
324            cursor: pointer;
325            background: #2563eb;
326            color: white;
327            border: 1px solid #1d4ed8;
328            border-radius: 5px;
329            box-shadow: 6px 6px 12px rgba(59, 130, 246, 0.5), inset -3px -3px 6px rgba(59, 130, 246, 0.4), inset 3px 3px 6px rgba(255, 255, 255, 0.8);
330            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
331            font-weight: bold;
332            transition: transform 0.2s;
333        }
334        button:hover {
335            background: #1d4ed8;
336            transform: scale(1.05);
337        }
338        button:disabled {
339            background: #6c757d;
340            cursor: not-allowed;
341            opacity: 0.65;
342            box-shadow: none;
343        }
344        .how-it-works-btn {
345            padding: 8px 16px;
346            background: #2563eb;
347            border: 1px solid #1d4ed8;
348            color: white;
349            border-radius: 5px;
350            cursor: pointer;
351            font-size: 14px;
352            margin-left: 10px;
353            box-shadow: 6px 6px 12px rgba(59, 130, 246, 0.5), inset -3px -3px 6px rgba(59, 130, 246, 0.4), inset 3px 3px 6px rgba(255, 255, 255, 0.8);
354            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
355            font-weight: bold;
356        }
357        .how-it-works-btn:hover {
358            background: #1d4ed8;
359            transform: scale(1.05);
360        }
361        .modal {
362            display: none;
363            position: fixed;
364            z-index: 1000;
365            left: 0;
366            top: 0;
367            width: 100%;
368            height: 100%;
369            background-color: rgba(0,0,0,0.5);
370        }
371        .modal-content {
372            background-color: white;
373            margin: 3% auto;
374            padding: 30px;
375            padding-right: 50px;
376            border-radius: 10px;
377            max-width: 500px;
378            max-height: 80vh;
379            overflow-y: auto;
380            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
381            position: relative;
382        }
383        .close-modal {
384            float: right;
385            font-size: 28px;
386            font-weight: bold;
387            cursor: pointer;
388            color: #666;
389        }
390        .close-modal:hover {
391            color: #000;
392        }
393        .modal h2 {
394            margin-top: 0;
395            color: #007bff;
396        }
397        .modal p {
398            line-height: 1.6;
399            color: #333;
400            margin: 15px 0;
401        }
402        .modal ul {
403            line-height: 1.8;
404            color: #333;
405        }
406        #result { 
407            margin-top: 20px; 
408            font-size: 1.2em; 
409            padding: 10px;
410            border-radius: 5px;
411            min-height: 40px;
412        }
413        .neutral-check, .injury-check {
414            margin: 10px 0;
415        }
416        #clearBtn {
417            background: #dc3545;
418        }
419        #clearBtn:disabled {
420            background: #6c757d;
421            cursor: not-allowed;
422            opacity: 0.65;
423        }
424        .team-display {
425            pointer-events: none;
426            height: 100%;
427            display: flex;
428            align-items: center;
429            justify-content: center;
430        }
431        .team-container {
432            display: flex;
433            align-items: center;
434            gap: 10px;
435            margin: 15px 0;
436        }
437        .at-sign {
438            font-size: 20px;
439            font-weight: bold;
440        }
441        .copyright {
442            text-align: center;
443            margin-top: 25px;
444            color: #666;
445            font-size: 0.9em;
446        }
447        @keyframes neon-flash {
448            0%, 100% { box-shadow: 0 0 5px #ff0000, 0 0 10px #ff0000, 0 0 15px #ff0000; }
449            50% { box-shadow: 0 0 10px #ff0000, 0 0 20px #ff0000, 0 0 30px #ff0000; }
450        }
451        .flash-border {
452            animation: neon-flash 3s ease-in-out infinite;
453            border-radius: 8px;
454            padding: 8px;
455        }
456        .instruction-text {
457            font-size: 14px;
458            margin: 4px 0;
459            color: #0066cc;
460            font-weight: 600;
461        }
462        .scroll-elevator {
463            position: fixed;
464            right: 20px;
465            display: flex;
466            flex-direction: column;
467            gap: 5px;
468            z-index: 1001;
469        }
470        .scroll-btn {
471            width: 40px;
472            height: 40px;
473            background: #2563eb;
474            border: 1px solid #1d4ed8;
475            border-radius: 5px;
476            color: white;
477            cursor: pointer;
478            display: flex;
479            align-items: center;
480            justify-content: center;
481            font-size: 20px;
482            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
483            transition: all 0.2s;
484        }
485        .scroll-btn:hover {
486            background: #1d4ed8;
487            transform: scale(1.1);
488        }
489        .scroll-btn:active {
490            transform: scale(0.95);
491        }
492    </style>
493</head>
494<body>
495    <!-- Combined Header with Logo and Navigation -->
496    <nav class="main-header">
497      <div class="header-wrapper">
498        <!-- Desktop Layout: Logo left, centered nav -->
499        <div class="header-row-desktop">
500          <a href="/" class="logo-link">
501            <div class="logo-section">
502              <img src="/hq-logo.png" alt="HQ Logo" class="header-logo" style="height: 52px; width: auto;">
503              <span class="header-brand">NFL Draft HQ</span>
504            </div>
505          </a>
506          
507          <div class="nav-center">
508            <div class="nav-dropdown" data-testid="nav-draft-dropdown">
509              <button class="nav-link dropdown-trigger" data-testid="nav-draft-btn">
510                Draft <span class="dropdown-arrow">▼</span>
511              </button>
512              <div class="dropdown-menu" data-testid="dropdown-menu-draft">
513                <a href="/current-mock" class="dropdown-item" target="_blank" rel="noopener noreferrer" onclick="new Audio('/nfl-draft-chime.mp3').play().catch(() => {})">HQ's 2027 Mock Draft</a>
514                <a href="/draft-sim-classic" class="dropdown-item" target="_blank" rel="noopener noreferrer">
5143-Round Classic Simulator</a>
515                <a href="/draft-sim-custom" class="dropdown-item" onclick="window.top.location.href='/draft-sim-custom'; return false;">7-Round Customizable Sim</a>
516                <a href="/Prospect-Rankings" class="dropdown-item" onclick="window.top.location.href='/Prospect-Rankings'; return false;">Prospect Rankings</a>
517                <a href="/team-needs" class="dropdown-item" onclick="window.top.location.href='/team-needs'; return false;">Team Needs</a>
518                <a href="/full-draft-order" class="dropdown-item" onclick="window.top.location.href='/full-draft-order'; return false;">Full Draft Order</a>
519              </div>
520            </div>
521            <div class="nav-dropdown" data-testid="nav-odds-dropdown">
522              <button class="nav-link dropdown-trigger" data-testid="nav-odds-btn">
523                Odds/Bets <span class="dropdown-arrow">▼</span>
524              </button>
525              <div class="dropdown-menu" data-testid="dropdown-menu-odds">
526                <a href="/nfl-od
526ds-calculator" class="dropdown-item" onclick="window.top.location.href='/nfl-odds-calculator'; return false;">Point Spread Calculator</a>
527              </div>
528            </div>
529            <a href="/nfl-report" class="nav-link" data-testid="nav-nfl-news" target="_blank" style="font-weight: bold;">NFL/Draft/Fantasy News</a>
530            <div class="nav-dropdown" data-testid="nav-more-dropdown">
531              <button class="nav-link dropdown-trigger" data-testid="nav-more-btn">
532                More <span class="dropdown-arrow">▼</span>
533              </button>
534              <div class="dropdown-menu" data-testid="dropdown-menu-more">
535                <a href="/team-picker-wheel.html" class="dropdown-item" target="_blank" rel="noopener noreferrer">Team Picker Wheel</a>
536                <a href="/ai-game" class="dropdown-item" onclick="window.top.location.href='/ai-game'; return false;">AI Game Simulator</a>
537                <a href="https://www.nfltriviablitz.com/" class="dropdown-item" target="_blank">2000's NFL Trivia</a>
538                <a href="#contact" class="dropdown-item">Contact Us</a>
539              </div>
540            </div>
541          </div>
542        </div>
543
544        <!-- Mobile Layout: Logo | Draft | Odds & Bets | More -->
545        <div class="header-row-mobile">
546          <a href="/" class="mobile-logo-link" data-testid="mobile-logo-link">
547            <img src="/hq-logo.png" alt="" class="mobile-header-logo" style="display: block; width: auto;">
548          </a>
549          <div class="mobile-nav-dropdown" data-testid="mobile-draft-dropdown">
550            <button class="mobile-nav-link mobile-dropdown-trigger" data-testid="mobile-draft-btn">
551              Draft <span class="mobile-dropdown-arrow">▼</span>
552            </button>
553            <div class="mobile-dropdown-menu" data-testid="mobile-dropdown-menu-draft">
554              <a href="/current-mock" class="mobile-dropdown-item" target="_blank" rel="noopener noreferrer" onclick="new Audio('/nfl-draft-chime.mp3').play().catch(() => {})">HQ's 2027 Mock Draft</a>
555              <a href="/draft-sim-custom" class="mobile-dropdown-item" onclick="window.top.location.href='/draft-sim-custom'; return false;">7-Round Customizable Sim</a>
556              <a href="/draft-sim-classic" class="mobile-dropdown-item" target="_blank" rel="noopener noreferrer">3-Round Classic Simulator</a>
557              <a href="/Prospect-Rankings" class="mobile-dropdown-item" onclick="window.top.location.href='/Prospect-Rankings'; return false;">Prospect Rankings</a>
558              <a href="/team-needs" class="mobile-dropdown-item" onclick="window.top.location.href='/team-needs'; return false;">Team Needs</a>
559              <a href="/full-draft-order" class="mobile-dropdown-item" onclick="window.top.location.href='/full-draft-order'; return false;">Full Draft Order</a>
560              <a href="https://spinwheelai.com" class="mobile-dropdown-item" target="_blank">
560Picker Wheel Random Draft</a>
561            </div>
562          </div>
563          <div class="mobile-nav-dropdown" data-testid="mobile-odds-dropdown">
564            <button class="mobile-nav-link mobile-dropdown-trigger" data-testid="mobile-odds-btn">
565              Odds/Bets <span class="mobile-dropdown-arrow">▼</span>
566            </button>
567            <div class="mobile-dropdown-menu" data-testid="mobile-dropdown-menu-odds">
568              <a href="/nfl-odds-calculator" class="mobile-dropdown-item" onclick="window.top.location.href='/nfl-odds-calculator'; return false;">Point Spread Calculator</a>
569            </div>
570          </div>
571          <a href="/nfl-report" class="mobile-nav-link" data-testid="mobile-nfl-news" style="font-weight: bold;">NFL News</a>
572          <div class="mobile-nav-dropdown" data-testid="mobile-more-dropdown">
573            <button class="mobile-nav-link mobile-dropdown-trigger" data-testid="mobile-more-btn">
574              More <span class="mobile-dropdown-arrow">▼</span>
575            </button>
576            <div class="mobile-dropdown-menu" data-testid="mobile-dropdown-menu-more">
577              <a href="/team-picker-wheel.html" class="mobile-dropdown-item" target="_blank" rel="noopener noreferrer">Team Picker Wheel</a>
578              <a href="/ai-game" class="mobile-dropdown-item" onclick="window.top.location.href='/ai-game'; return false;">AI Game Simulator</a>
579              <a href="https://www.nfltriviablitz.com/" class="mobile-dropdown-item" target="_blank">2000's NFL Trivia</a>
580              <a href="#contact" class="mobile-dropdown-item">Contact Us</a>
581            </div>
582          </div>
583        </div>
584      </div>
585
586      <style>
587        .main-header {
588          background: white;
589          border-bottom: 3px solid #dc2626;
590          position: sticky;
591          top: 0;
592          z-index: 1000;
593          box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
594        }
595
596        .header-wrapper {
597          max-width: 1400px;
598          margin: 0 auto;
599          padding: 0 1rem;
600        }
601
602        /* Desktop Layout */
603        .header-row-desktop {
604          display: flex;
605          align-items: center;
606          padding: 0.75rem 0;
607          position: relative;
608        }
609
610        .logo-link {
611          display: flex;
612          align-items: center;
613          text-decoration: none;
614          flex-shrink: 0;
615        }
616
617        .logo-section {
618          display: flex;
619          align-items: center;
620          gap: 0.5rem;
621          flex-shrink: 0;
622        }
623
624        .header-logo {
625          height: 52px;
626          width: auto;
627          display: block;
628        }
629
630        .header-brand {
631          font-family: 'Courier New', Courier, monospace;
632          font-size: 16px;
633          font-weight: 900;
634          background: linear-gradient(135deg, #dc2626 0%, #991b1b 50%, #7f1d1d 100%);
635          -webkit-background-clip: text;
636          -webkit-text-fill-color: transparent;
637          background-clip: text;
638          white-space: nowrap;
639          letter-spacing: 0.08em;
640          text-transform: uppercase;
641          text-shadow: 2px 2px 0px rgba(220, 38, 38, 0.2);
642          filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.1));
643        }
644
645        /* Centered Navigation */
646        .nav-center {
647          position: absolute;
648          left: 50%;
649          transform: translateX(-50%);
650          display: flex;
651          align-items: center;
652          gap: 1.5rem;
653        }
654
655        .nav-link {
656          font-family: 'Comic Sans MS', 'Comic Sans', cursive;
657          font-size: 14px;
658          color: #374151;
659          text-decoration: none;
660          letter-spacing: 0.08em;
661          padding: 0.3rem 0;
662          transition: all 0.2s ease;
663          white-space: nowrap;
664          border: none;
665          background: none !important;
666          cursor: pointer;
667          position: relative;
668          box-shadow: none !important;
669          text-shadow: none !important;
670        }
671
672        .nav-link:hover {
673          color: #dc2626;
674          background: none !important;
675          box-shadow: none !important;
676        }
677
678        .nav-link.active {
679          color: #dc2626;
680          background: none !important;
681          box-shadow: none !important;
682        }
683
684        .nav-link.active::after {
685          content: '';
686          position: absolute;
687          bottom: 0;
688          left: 0;
689          right: 0;
690          height: 2px;
691          background-color: #dc2626;
692        }
693
694        /* Dropdown */
695        .nav-dropdown {
696          position: relative;
697        }
698
699        .dropdown-trigger {
700          display: flex;
701          align-items: center;
702          gap: 0.3rem;
703        }
704
705        .dropdown-arrow {
706          font-size: 8px;
707          color: #000;
708        }
709
710        .dropdown-menu {
711          display: none;
712          position: absolute;
713          top: 100%;
714          left: 50%;
715          transform: translateX(-50%);
716          background: white;
717          border: 1px solid #e5e7eb;
718          border-radius: 6px;
719          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
720          min-width: 220px;
721          padding: 0.5rem 0;
722          z-index: 1001;
723          margin-top: 0;
724          pointer-events: auto;
725        }
726
727        .nav-dropdown:hover .dropdown-menu,
728        .nav-dropdown .dropdown-menu.show {
729          display: block;
730        }
731
732        .dropdown-item {
733          display: block;
734          font-family: 'Comic Sans MS', 'Comic Sans', cursive;
735          font-size: 14px;
736          color: #374151;
737          text-decoration: none;
738          padding: 0.6rem 1rem;
739          letter-spacing: 0.08em;
740          transition: all 0.2s ease;
741          border-bottom: 1px solid #e5e7eb;
742        }
743
744        .dropdown-item:last-child {
745          border-bottom: none;
746        }
747
748        .dropdown-item:hover {
749          background-color: #f9fafb;
750          color: #dc2626;
751        }
752
753        .dropdown-item.active {
754          color: #dc2626;
755        }
756
757        /* Mobile Layout */
758        .header-row-mobile {
759          display: none;
760          flex-direction: row;
761          align-items: center;
762          justify-content: space-between;
763          gap: 0.5rem;
764          padding: 1.5rem 1rem;
765        }
766
767        .mobile-logo-link {
768          display: flex;
769          align-items: center;
770          justify-content: center;
771          text-decoration: none;
772          cursor: pointer;
773          flex-shrink: 0;
774        }
775
776        .mobile-header-logo {
777          height: 64px;
778          width: auto;
779          display: block;
780        }
781
782        .mobile-nav-link {
783          font-family: 'Comic Sans MS', 'Comic Sans', cursive;
784          font-size: 22px;
785          color: #374151;
786          text-decoration: none;
787          letter-spacing: 0.05em;
788          padding: 0.5rem 0;
789          transition: all 0.2s ease;
790          white-space: nowrap;
791          border: none !important;
792          background: none !important;
793          background-color: transparent !important;
794          box-shadow: none !important;
795          outline: none !important;
796          cursor: pointer;
797          position: relative;
798          -webkit-appearance: none;
799          -moz-appearance: none;
800          appearance: none;
801        }
802
803        .mobile-nav-link:hover {
804          color: #dc2626;
805          background: none !important;
806          background-color: transparent !important;
807        }
808
809        .mobile-nav-link:focus {
810          background: none !important;
811          background-color: transparent !important;
812          box-shadow: none !important;
813          outline: none !important;
814        }
815
816        .mobile-nav-link.active {
817          color: #dc2626;
818          text-decoration: underline;
819          text-underline-offset: 3px;
820        }
821
822        /* Mobile Dropdown */
823        .mobile-nav-dropdown {
824          position: relative;
825        }
826
827        .mobile-dropdown-trigger {
828          display: flex;
829          align-items: center;
830          gap: 0.2rem;
831        }
832
833        .mobile-dropdown-arrow {
834          font-size: 14px;
835          color: #00338D;
836        }
837
838        .mobile-dropdown-menu {
839          display: none;
840          position: absolute;
841          top: 100%;
842          left: 0;
843          background: white;
844          border: 1px solid #e5e7eb;
845          border-radius: 6px;
846          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
847          min-width: 240px;
848          max-width: none;
849          width: auto;
850          padding: 0.5rem 0;
851          z-index: 1001;
852          margin-top: 0;
853          pointer-events: auto;
854        }
855
856        .mobile-nav-dropdown:last-child .mobile-dropdown-menu {
857          left: auto;
858          right: 0;
859        }
860
861        .mobile-nav-dropdown:hover .mobile-dropdown-menu,
862        .mobile-nav-dropdown:focus-within .mobile-dropdown-menu {
863          display: block;
864        }
865
866        .mobile-dropdown-item {
867          display: block;
868          font-family: 'Comic Sans MS', 'Comic Sans', cursive;
869          font-size: 15px;
870          color: #374151;
871          text-decoration: none;
872          padding: 0.75rem 1.25rem;
873          letter-spacing: 0.05em;
874          transition: all 0.2s ease;
875          border-bottom: 1px solid #e5e7eb;
876          white-space: nowrap;
877        }
878
879        .mobile-dropdown-item:last-child {
880          border-bottom: none;
881        }
882
883        .mobile-dropdown-item:hover {
884          background-color: #f9fafb;
885          color: #dc2626;
886        }
887
888        .mobile-dropdown-menu .mobile-dropdown-item {
889          color: #00338D;
890        }
891
892        .mobile-nav-dropdown[data-testid="mobile-odds-dropdown"] .mobile-dropdown-item:first-child {
893          color: #dc2626;
894          font-weight: bold;
895        }
896
897        .mobile-dropdown-divider-thick {
898          height: 3px;
899          background-color: #000;
900          margin: 0;
901        }
902
903        /* Tablet and Mobile */
904        @media (max-width: 1024px) {
905          .header-logo {
906            height: 32px;
907          }
908
909          .header-brand {
910            font-size: 13px;
911          }
912
913          .nav-link {
914            font-size: 12px;
915          }
916
917          .nav-center {
918            gap: 1rem;
919          }
920        }
921
922        @media (max-width: 768px) {
923          .header-row-desktop {
924            display: none;
925          }
926
927          .header-row-mobile {
928            display: flex;
929            gap: 0.5rem;
930            padding: 1.25rem 0.75rem;
931            justify-content: space-between;
932          }
933
934          .mobile-header-logo {
935            height: 48px;
936          }
937
938          .mobile-nav-link {
939            font-size: 18px;
940          }
941        }
942
943        @media (max-width: 480px) {
944          .header-wrapper {
945            padding: 0 0.5rem;
946          }
947
948          .header-row-mobile {
949            gap: 0.4rem;
950            padding: 1rem 0.5rem;
951            justify-content: space-between;
952          }
953
954          .mobile-header-logo {
955            height: 40px;
956          }
957
958          .mobile-nav-link {
959            font-size: 14px;
960            letter-spacing: 0.02em;
961          }
962
963          .mobile-dropdown-arrow {
964            font-size: 10px;
965          }
966
967          .mobile-dropdown-item {
968            font-size: 14px;
969            padding: 0.7rem 1.1rem;
970            white-space: nowrap;
971          }
972        }
973      </style>
974    </nav>
975
976    <script>
977      // Dropdown behavior: stay open on hover, close on mouseleave
978      document.querySelectorAll('.nav-dropdown').forEach(dropdown => {
979        const trigger = dropdown.querySelector('.dropdown-trigger');
980        const menu = dropdown.querySelector('.dropdown-menu');
981        
982        if (!menu) return;
983        
984        // Show menu on hover over dropdown
985        dropdown.addEventListener('mouseenter', () => {
986          menu.style.display = 'block';
987        });
988        
989        // Hide menu when mouse leaves dropdown
990        dropdown.addEventListener('mouseleave', () => {
991          menu.style.display = 'none';
992        });
993      });
994      
995      // Mobile dropdown behavior
996      document.querySelectorAll('.mobile-nav-dropdown').forEach(dropdown => {
997        const trigger = dropdown.querySelector('.mobile-dropdown-trigger');
998        const menu = dropdown.querySelector('.mobile-dropdown-menu');
999        
1000        if (!menu) return;
1001        
1002        dropdown.addEventListener('mouseenter', () => {
1003          menu.style.display = 'block';
1004        });
1005        
1006        dropdown.addEventListener('mouseleave', () => {
1007          menu.style.display = 'none';
1008        });
1009      });
1010    <\/script>
1011    
1012    <style>
1013        /* Additional page styles follow */
1014
1015        .header-link-mobile.active {
1016          color: #dc2626;
1017          font-weight: 600;
1018        }
1019
1020        .pipe-divider-mobile {
1021          color: #d1d5db;
1022          font-weight: 300;
1023          margin: 0 0.15rem;
1024          flex-shrink: 0;
1025        }
1026
1027        /* Tablet and Mobile */
1028        @media (max-width: 1024px) {
1029          .header-logo {
1030            height: 32px;
1031          }
1032
1033          .header-brand {
1034            font-size: 13px;
1035          }
1036
1037          .header-link {
1038            font-size: 11px;
1039          }
1040
1041          .pipe-divider {
1042            margin: 0 0.15rem;
1043          }
1044        }
1045
1046        @media (max-width: 768px) {
1047          .header-row-desktop {
1048            display: none;
1049          }
1050
1051          .header-row-mobile {
1052            display: flex;
1053          }
1054
1055          .mobile-logo-section {
1056            display: flex;
1057          }
1058
1059          .mobile-header-logo {
1060            height: 28px;
1061          }
1062
1063          .mobile-header-brand {
1064            font-size: 12px;
1065            font-weight: 900;
1066            letter-spacing: 0.08em;
1067          }
1068
1069          .header-link-mobile {
1070            font-size: 11px;
1071          }
1072
1073          .pipe-divider-mobile {
1074            margin: 0 0.1rem;
1075          }
1076        }
1077
1078        @media (max-width: 480px) {
1079          .header-wrapper {
1080            padding: 0 0.5rem;
1081          }
1082
1083          .mobile-header-logo {
1084            height: 24px;
1085          }
1086
1087          .mobile-header-brand {
1088            font-size: 11px;
1089            font-weight: 900;
1090            letter-spacing: 0.08em;
1091          }
1092
1093          .header-link-mobile {
1094            font-size: 10px;
1095          }
1096
1097          .pipe-divider-mobile {
1098            font-size: 10px;
1099            margin: 0 0.08rem;
1100          }
1101
1102          .mobile-line {
1103            gap: 0.2rem;
1104          }
1105        }
1106      </style>
1107    </nav>
1108
1109    <!-- Current NFL Power Rankings - January 17, 2027 -->
1110    <div aria-hidden="true" style="display: none;">
1111        <h2>Current NFL Power Rankings 2025</h2>
1112        <p>This page contains the current NFL power rankings updated weekly using our proprietary Win Quality Index (WQI) system. Teams are ranked 1-32 based on performance and strength of schedule.</p>
1113        <ul>
1114            <li>1. Seahawks</li>
1115            <li>2. Jaguars</li>
1116            <li>3. Texans</li>
1117            <li>4. Rams</li>
1118            <li>5. Broncos</li>
1119            <li>6. Patriots</li>
1120            <li>7. Bills</li>
1121            <li>8. 49ers</li>
1122            <li>9. Eagles</li>
1123            <li>10. Steelers</li>
1124            <li>11. Vikings</li>
1125            <li>12. Chargers</li>
1126            <li>13. Panthers</li>
1127            <li>14. Buccaneers</li>
1128            <li>15. Bears</li>
1129            <li>16. Colts</li>
1130            <li>17. Falcons</li>
1131            <li>18. Lions</li>
1132            <li>19. Packers</li>
1133            <li>20. Ravens</li>
1134            <li>21. Saints</li>
1135            <li>22. Dolphins</li>
1136            <li>23. Cowboys</li>
1137            <li>24. Bengals</li>
1138            <li>25. Titans</li>
1139            <li>26. Chiefs</li>
1140            <li>27. Browns</li>
1141            <li>28. Giants</li>
1142            <li>29. Cardinals</li>
1143            <li>30. Raiders</li>
1144            <li>31. Jets</li>
1145            <li>32. Commanders</li>
1146        </ul>
1147    </div>
1148    <!-- END: Current NFL Power Rankings -->
1149
1150    <div class="content" style="padding: 0; margin-top: 0;">
1151        <div class="container">
1152            <div style="width: 100%; max-width: 800px;">
1153                <div class="grid" id="teamGrid"></div>
1154                <div id="wqi-description" style="text-align: center; max-width: 800px; margin: 20px auto 20px; font-size: 0.88rem; color: #555; line-height: 1.6; padding: 0 20px;">
1155                    <p>Our proprietary <strong>Win Quality Index (WQI)</strong> calculates NFL point spreads and powers our WQI analysis. Drag teams to customize rankings & calculate spreads for any matchup. Rankings are updated 12 hours before game time.</p>
1156                </div>
1157                <div class="copyright" style="margin-top: 20px; padding-top: 20px;
1157 border-top: 4px solid #000;">
1158                    © 2025 <a href="https://nfldrafthq.com" target="_blank">NFLDraftHQ.com</a> · Point spreads are for entertainment purposes only
1159                </div>
1160            </div>
1161            <div class="controls">
1162                <div id="instructionContainer" style="text-align: center; margin-bottom: 20px;">
1163                    <h3 id="instructionText" class="instruction-text flash-border">Click/Drag or Double Click<br>the teams to calculate odds</h3>
1164                </div>
1165                <div class="team-container">
1166                    <div class="selected-team" id="awayDrop">
1167                        <div class="default-text"><strong>Away</strong></div>
1168                    </div>
1169                    <div class="at-sign">@</div>
1170                    <div class="selected-team" id="homeDrop">
1171                        <div class="default-text"><strong>Home</strong></div>
1172                    </div>
1173                </div>
1174                <div style="display: flex; gap: 10px; margin-bottom: 15px;">
1175                    <button id="calculateBtn" onclick="calculateOdds()" disabled style="flex: 1; padding: 8px 16px; font-size: 0.8em;">Calculate Spread</button>
1176                    <button id="clearBtn" onclick="clearTeams()" disabled style="flex: 1; padding: 8px 16px; font-size: 0.8em;">Clear Teams</button>
1177                </div>
1178                <div id="result" style="margin-bottom: 15px; min-height: 30px;"></div>
1179                <div class="neutral-check" style="display: flex; align-items: center; justify-content: space-between;">
1180                    <label><input type="checkbox" id="neutralSite"> Neutral Site</label>
1181                    <button class="how-it-works-btn" onclick="showHowItWorks()">How it Works</button>
1182                </div>
1183                <!-- Commented out for potential future restoration
1184                <div class="injury-check">
1185                    <label id="homeInjuryLabel"><input type="checkbox" id="homeInjury"> Home team injury concerns</label>
1186                </div>
1187                <div class="injury-check">
1188                    <label id="awayInjuryLabel"><input type="checkbox" id="awayInjury"> Away team injury concerns</label>
1189                </div>
1190                <div class="injury-check">
1191                    <label id="positiveHomeMomentumLabel"><input type="checkbox" id="positiveHomeMomentum"> Positive Home team momentum</label>
1192                </div>
1193                <div class="injury-check">
1194                    <label id="positiveAwayMomentumLabel"><input type="checkbox" id="positiveAwayMomentum"> Positive Away team momentum</label>
1195                </div>
1196                <div class="injury-check">
1197                    <label id="negativeHomeMomentumLabel"><input type="checkbox" id="negativeHomeMomentum"> Negative Home team momentum</label>
1198                </div>
1199                <div class="injury-check">
1200                    <label id="negativeAwayMomentumLabel"><input type="checkbox" id="negativeAwayMomentum"> Negative Away team momentum</label>
1201                </div>
1202                -->
1203            </div>
1204        </div>
1205    </div>
1206
1207    <!-- How it Works Modal -->
1208    <div id="howItWorksModal" class="modal">
1209        <div class="modal-content" id="modalContent">
1210            <span class="close-modal" onclick="closeHowItWorks()">&times;</span>
1211            <div class="scroll-elevator" id="scrollElevator" style="display: none;">
1212                <button class="scroll-btn" onclick="scrollModalUp()" title="Scroll Up">▲</button>
1213                <button class="scroll-btn" onclick="scrollModalDown()" title="Scroll Down">▼</button>
1214            </div>
1215            <h2>How the NFL Odds Calculator Works</h2>
1216            
1217            <p><strong>Power Rankings System:</strong></p>
1218            <ul>
1219                <li><strong>HQ Power Rankings:</strong> Our default rankings are dynamically updated based on the Win Quality Index (WQI), a proprietary metric that evaluates team performance by analyzing the strength and quality of wins/losses throughout the season.</li>
1220                <li><strong>Custom Rankings:</strong> You have full control to create your own power rankings by simply dragging and dropping team cards into your preferred order. Your custom arrangement will be used to calculate point spreads.</li>
1221            </ul>
1222            
1223            <p><strong>Calculating Odds:</strong></p>
1224            <p>To generate a point spread prediction:</p>
1225            <ul>
1226                <li>Select an away team and a home team by dragging or double-clicking the team cards</li>
1227                <li>Click "Calculate Spread" to view the predicted point spread</li>
1228                <li>Toggle "Neutral Site" if the game is played at a neutral location</li>
1229            </ul>
1230            
1231            <p><strong>Win Quality Index (WQI):</strong></p>
1232            <p>The WQI is a sophisticated algorithm that weights wins/losses based on opponent strength. HQ rankings are automatically refreshed to reflect the most current team performance.</p>
1233            
1234            <p style="font-style: italic; color: #666; margin-top: 20px;">Note: Point spreads are for entertainment purposes only.</p>
1235        </div>
1236    </div>
1237
1238    <script>
1239        function showHowItWorks() {
1240            const modal = document.getElementById('howItWorksModal');
1241            const modalContent = document.getElementById('modalContent');
1242            const scrollElevator = document.getElementById('scrollElevator');
1243            
1244            modal.style.display = 'block';
1245            
1246            // Check if modal content is scrollable and show/hide elevator
1247            setTimeout(() => {
1248                if (modalContent.scrollHeight > modalContent.clientHeight) {
1249                    scrollElevator.style.display = 'flex';
1250                    updateScrollElevatorPosition();
1251                } else {
1252                    scrollElevator.style.display = 'none';
1253                }
1254            }, 100);
1255            
1256            // Add scroll listener to update elevator position
1257            modalContent.addEventListener('scroll', updateScrollElevatorPosition);
1258        }
1259        
1260        function closeHowItWorks() {
1261            const modal = document.getElementById('howItWorksModal');
1262            const modalContent = document.getElementById('modalContent');
1263            const scrollElevator = document.getElementById('scrollElevator');
1264            
1265            modal.style.display = 'none';
1266            scrollElevator.style.display = 'none';
1267            modalContent.scrollTop = 0;
1268            modalContent.removeEventListener('scroll', updateScrollElevatorPosition);
1269        }
1270        
1271        function scrollModalUp() {
1272            const modalContent = document.getElementById('modalContent');
1273            modalContent.scrollBy({ top: -100, behavior: 'smooth' });
1274        }
1275        
1276        function scrollModalDown() {
1277            const modalContent = document.getElementById('modalContent');
1278            modalContent.scrollBy({ top: 100, behavior: 'smooth' });
1279        }
1280        
1281        function updateScrollElevatorPosition() {
1282            const modalContent = document.getElementById('modalContent');
1283            const scrollElevator = document.getElementById('scrollElevator');
1284            const modalRect = modalContent.getBoundingClientRect();
1285            
1286            // Position the elevator on the right side of the modal, vertically centered
1287            const centerY = modalRect.top + (modalRect.height / 2) - 50;
1288            scrollElevator.style.top = centerY + 'px';
1289        }
1290        
1291        // Close modal when clicking outside of it
1292        window.onclick = function(event) {
1293            const modal = document.getElementById('howItWorksModal');
1294            if (event.target === modal) {
1295                closeHowItWorks();
1296            }
1297        }
1298                                                                                                                                                                                                                                const teams = [
1299            { name: 'Seahawks', primary: '#002244', secondary: '#69BE28' },
1300            { name: 'Jaguars', primary: '#006778', secondary: '#D7A22A' },
1301            { name: 'Texans', primary: '#03202F', secondary: '#A71930' },
1302            { name: 'Rams', primary: '#003594', secondary: '#FFA300' },
1303            { name: 'Broncos', primary: '#FB4F14', secondary: '#002244' },
1304            { name: 'Patriots', primary: '#002244', secondary: '#C60C30' },
1305            { name: 'Bills', primary: '#00338D', secondary: '#C60C30' },
1306            { name: '49ers', primary: '#AA0000', secondary: '#B3995D' },
1307            { name: 'Eagles', primary: '#004C54', secondary: '#A5ACAF' },
1308            { name: 'Steelers', primary: '#FFB612', secondary: '#000000' },
1309            { name: 'Vikings', primary: '#4F2683', secondary: '#FFC62F' },
1310            { name: 'Chargers', primary: '#0080C6', secondary: '#FFC20E' },
1311            { name: 'Panthers', primary: '#0085CA', secondary: '#101820' },
1312            { name: 'Buccaneers', primary: '#D50A0A', secondary: '#FF7900' },
1313            { name: 'Bears', primary: '#0B162A', secondary: '#C83803' },
1314            { name: 'Colts', primary: '#002C5F', secondary: '#A2AAAD' },
1315            { name: 'Falcons', primary: '#A71930', secondary: '#000000' },
1316            { name: 'Lions', primary: '#0076B6', secondary: '#B0B7BC' },
1317            { name: 'Packers', primary: '#203731', secondary: '#FFB612' },
1318            { name: 'Ravens', primary: '#241773', secondary: '#9E7C0C' },
1319            { name: 'Saints', primary: '#D3BC8D', secondary: '#101820' },
1320            { name: 'Dolphins', primary: '#008E97', secondary: '#FC4C02' },
1321            { name: 'Cowboys', primary: '#041E42', secondary: '#869397' },
1322            { name: 'Bengals', primary: '#FB4F14', secondary: '#000000' },
1323            { name: 'Titans', primary: '#0C2340', secondary: '#4B92DB' },
1324            { name: 'Chiefs', primary: '#E31837', secondary: '#FFB81C' },
1325            { name: 'Browns', primary: '#311D00', secondary: '#FF3C00' },
1326            { name: 'Giants', primary: '#0B2265', secondary: '#A71930' },
1327            { name: 'Cardinals', primary: '#97233F', secondary: '#000000' },
1328            { name: 'Raiders', primary: '#000000', secondary: '#A5ACAF' },
1329            { name: 'Jets', primary: '#125740', secondary: '#000000' },
1330            { name: 'Commanders', primary: '#5A1414', secondary: '#FFB612' },
1331        ];
1332
1333        let draggedItem = null;
1334        let awayTeam = null;
1335        let homeTeam = null;
1336        let offenseRanks = {};
1337        let defenseRanks = {};
1338        const darkColors = ['#000000', '#041E42', '#002244', '#101820', '#03202F', '#0B162A', '#0C2340', '#311D00', '#002C5F', '#125740', '#4F2683', '#241773', '#203731', '#006778', '#004C54'];
1339
1340        // Load live power rankings from Google Sheets API
1341        async function loadLivePowerRankings() {
1342            // Show loading state
1343            const grid = document.getElementById('teamGrid');
1344            grid.innerHTML = '<div style="text-align: center; padding: 40px; color: #666; font-size: 18px;">Loading Power Rankings...</div>';
1345            
1346            try {
1347                // Get the base URL for the parent window
1348                const baseUrl = window.parent.location.origin;
1349                
1350                // Fetch live power rankings from our API with cache busting
1351                const response = await fetch(\`\${baseUrl}/api/power-rankings?t=\${Date.now()}\`, {
1352                    cache: 'no-store',
1353                    headers: {
1354                        'Cache-Control': 'no-cache',
1355                        'Pragma': 'no-cache'
1356                    }
1357                });
1358                
1359                if (!response.ok) {
1360                    throw new Error(\`Failed to fetch power rankings: \${response.status}\`);
1361                }
1362                
1363                const powerRankings = await response.json();
1364                
1365                console.log('Live power rankings fetched:', powerRankings.length, 'teams');
1366                
1367                if (powerRankings && powerRankings.length > 0) {
1368                    // Update team order based on live power rankings
1369                    updateTeamOrderFromPowerRankings(powerRankings);
1370                    // Also load offense/defense rankings separately for odds calculations
1371                    loadOffenseDefenseRankings();
1372                } else {
1373                    throw new Error('No power rankings data received');
1374                }
1375            } catch (error) {
1376                console.error('Error loading live power rankings:', error);
1377                // Show error message instead of fallback grid
1378                grid.innerHTML = \`
1379                    <div style="text-align: center; padding: 40px; color: #d32f2f;">
1380                        <div style="font-size: 18px; margin-bottom: 10px;">⚠️ Failed to load Power Rankings</div>
1381                        <div style="font-size: 14px; margin-bottom: 20px;">Unable to fetch live data from Google Sheets</div>
1382                        <button onclick="location.reload()" style="padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;">
1383                            Retry
1384                        </button>
1385                    </div>
1386                \`;
1387                // Still attempt to load offense/defense rankings for calculations
1388                loadOffenseDefenseRankings();
1389            }
1390        }
1391        
1392        // Update team order based on power rankings
1393        function updateTeamOrderFromPowerRankings(powerRankings) {
1394            // Create a mapping from team name to rank
1395            const rankMap = {};
1396            powerRankings.forEach(ranking => {
1397                // API already returns short names, use them directly
1398                rankMap[ranking.team] = ranking.rank;
1399            });
1400            
1401            console.log('Rank mapping:', rankMap);
1402            
1403            // Sort teams array based on power rankings
1404            teams.sort((a, b) => {
1405                const rankA = rankMap[a.name] || 99;
1406                const rankB = rankMap[b.name] || 99;
1407                return rankA - rankB;
1408            });
1409            
1410            console.log('Teams reordered by power rankings');
1411            // Refresh the grid display
1412            initializeGrid();
1413        }
1414        
1415        // Convert full team names to short names used in the interface
1416        function getShortTeamName(fullName) {
1417            const nameMap = {
1418                'Philadelphia Eagles': 'Eagles',
1419                'Kansas City Chiefs': 'Chiefs',
1420                'Baltimore Ravens': 'Ravens',
1421                'Buffalo Bills': 'Bills',
1422                'Detroit Lions': 'Lions',
1423                'Washington Commanders': 'Commanders',
1424                'Los Angeles Rams': 'Rams',
1425                'San Francisco 49ers': '49ers',
1426                'Green Bay Packers': 'Packers',
1427                'Minnesota Vikings': 'Vikings',
1428                'Los Angeles Chargers': 'Chargers',
1429                'Cincinnati Bengals': 'Bengals',
1430                'Tampa Bay Buccaneers': 'Buccaneers',
1431                'Denver Broncos': 'Broncos',
1432                'Dallas Cowboys': 'Cowboys',
1433                'Houston Texans': 'Texans',
1434                'Chicago Bears': 'Bears',
1435                'Pittsburgh Steelers': 'Steelers',
1436                'Seattle Seahawks': 'Seahawks',
1437                'Arizona Cardinals': 'Cardinals',
1438                'Miami Dolphins': 'Dolphins',
1439                'New Orleans Saints': 'Saints',
1440                'Tennessee Titans': 'Titans',
1441                'New York Jets': 'Jets',
1442                'New England Patriots': 'Patriots',
1443                'Indianapolis Colts': 'Colts',
1444                'Jacksonville Jaguars': 'Jaguars',
1445                'Las Vegas Raiders': 'Raiders',
1446                'Atlanta Falcons': 'Falcons',
1447                'Cleveland Browns': 'Browns',
1448                'Carolina Panthers': 'Panthers',
1449                'New York Giants': 'Giants'
1450            };
1451            return nameMap[fullName] || null;
1452        }
1453        
1454        // Load team offense and defense rankings for odds calculations
1455        async function loadOffenseDefenseRankings() {
1456            try {
1457                // Get the base URL for the parent window
1458                const baseUrl = window.parent.location.origin;
1459                
1460                // Load offense rankings from CSV (keep this for now)
1461                const offenseResponse = await fetch(\`\${baseUrl}/team-offense-ranks.csv\`);
1462                const offenseText = await offenseResponse.text();
1463                const offenseLines = offenseText.split('\\n').slice(1); // Skip header
1464                offenseLines.forEach(line => {
1465                    const [rank, team] = line.split(',');
1466                    if (rank && team) {
1467                        offenseRanks[team.trim()] = parseInt(rank);
1468                    }
1469                });
1470
1471                // Load defense rankings from CSV (keep this for now)
1472                const defenseResponse = await fetch(\`\${baseUrl}/team-defense-ranks.csv\`);
1473                const defenseText = await defenseResponse.text();
1474                const defenseLines = defenseText.split('\\n').slice(1); // Skip header
1475                defenseLines.forEach(line => {
1476                    const [rank, team] = line.split(',');
1477                    if (rank && team) {
1478                        defenseRanks[team.trim()] = parseInt(rank);
1479                    }
1480                });
1481                
1482                console.log('Offense rankings loaded:', Object.keys(offenseRanks).length, 'teams');
1483                console.log('Defense rankings loaded:', Object.keys(defenseRanks).length, 'teams');
1484            } catch (error) {
1485                console.error('Error loading offense/defense rankings:', error);
1486                console.log('Failed to load offense/defense rankings - will use empty data until available');
1487                // Removed hardcoded fallback - only use Google Sheets data
1488            }
1489        }
1490        
1491
1492
1493        function validateSelections() {
1494            const calculateBtn = document.getElementById('calculateBtn');
1495            calculateBtn.disabled = !(awayTeam && homeTeam && awayTeam !== homeTeam);
1496        }
1497
1498        function updateCheckboxColors() {
1499            const instructionText = document.getElementById('instructionText');
1500            
1501            // Home team label IDs
1502            const homeLabels = ['homeInjuryLabel', 'positiveHomeMomentumLabel', 'negativeHomeMomentumLabel'];
1503            
1504            // Update home team label colors using primary color
1505            if (homeTeam) {
1506                const homeTeamData = teams.find(t => t.name === homeTeam);
1507                if (homeTeamData) {
1508                    homeLabels.forEach(labelId => {
1509                        const label = document.getElementById(labelId);
1510                        if (label) {
1511                            label.style.color = homeTeamData.primary;
1512                            label.style.fontWeight = 'bold';
1513                        }
1514                    });
1515                }
1516            } else {
1517                homeLabels.forEach(labelId => {
1518                    const label = document.getElementById(labelId);
1519                    if (label) {
1520                        label.style.color = '';
1521                        label.style.fontWeight = '';
1522                    }
1523                });
1524            }
1525            
1526            // Away team label IDs
1527            const awayLabels = ['awayInjuryLabel', 'positiveAwayMomentumLabel', 'negativeAwayMomentumLabel'];
1528            
1529            // Update away team label colors using primary color
1530            if (awayTeam) {
1531                const awayTeamData = teams.find(t => t.name === awayTeam);
1532                if (awayTeamData) {
1533                    awayLabels.forEach(labelId => {
1534                        const label = document.getElementById(labelId);
1535                        if (label) {
1536                            label.style.color = awayTeamData.primary;
1537                            label.style.fontWeight = 'bold';
1538                        }
1539                    });
1540                }
1541            } else {
1542                awayLabels.forEach(labelId => {
1543                    const label = document.getElementById(labelId);
1544                    if (label) {
1545                        label.style.color = '';
1546                        label.style.fontWeight = '';
1547                    }
1548                });
1549            }
1550            
1551            // Keep the flashing border always visible on instruction text
1552            instructionText.classList.add('flash-border');
1553        }
1554
1555        function disableTeamButton(teamName) {
1556            const buttons = document.querySelectorAll('.team-btn');
1557            buttons.forEach(btn => {
1558                const teamData = JSON.parse(btn.dataset.team);
1559                if (teamData.name === teamName) {
1560                    // Get the text color of the team card
1561                    const textColor = btn.style.color;
1562                    btn.style.border = '4px solid ' + textColor;
1563                    btn.style.pointerEvents = 'none';
1564                    btn.style.cursor = 'not-allowed';
1565                }
1566            });
1567        }
1568
1569        function enableAllTeamButtons() {
1570            const buttons = document.querySelectorAll('.team-btn');
1571            buttons.forEach(btn => {
1572                const teamData = JSON.parse(btn.dataset.team);
1573                btn.style.border = '1px solid #1d4ed8';
1574                btn.style.pointerEvents = 'auto';
1575                btn.style.cursor = 'grab';
1576            });
1577        }
1578        
1579        function highlightTeamButton(teamName) {
1580            const buttons = document.querySelectorAll('.team-btn');
1581            buttons.forEach(btn => {
1582                const teamData = JSON.parse(btn.dataset.team);
1583                if (teamData.name === teamName) {
1584                    const textColor = btn.style.color;
1585                    btn.style.border = '4px solid ' + textColor;
1586                }
1587            });
1588        }
1589
1590        function initializeGrid() {
1591            console.log('Initializing grid with', teams.length, 'teams');
1592            const grid = document.getElementById('teamGrid');
1593            grid.innerHTML = '';
1594            teams.forEach((team, index) => {
1595                const btn = document.createElement('div');
1596                btn.className = 'team-btn';
1597                btn.draggable = true;
1598                btn.innerHTML = \`
1599                    \${team.name}
1600                    <hr class="rank-separator">
1601                    <small>Rank: \${index + 1}</small>
1602                \`;
1603                btn.style.backgroundColor = team.primary;
1604                btn.style.color = darkColors.includes(team.secondary) ? '#FFFFFF' : team.secondary;
1605                btn.style.borderColor = team.secondary;
1606                
1607                if(team.name === 'Commanders') {
1608                    btn.style.justifyContent = 'space-evenly';
1609                }
1610
1611                const nameLength = team.name.length;
1612                btn.style.fontSize = nameLength <= 4 ? '16px' :
1613                                   nameLength <= 8 ? '14px' : '12px';
1614                
1615                btn.dataset.team = JSON.stringify(team);
1616                
1617                btn.addEventListener('dragstart', handleDragStart);
1618                btn.addEventListener('dragover', handleDragOver);
1619                btn.addEventListener('drop', handleGridDrop);
1620                btn.addEventListener('dblclick', () => {
1621                    // Check if button is disabled
1622                    if (btn.style.pointerEvents === 'none') {
1623                        return; // Don't allow selection if disabled
1624                    }
1625                    
1626                    const teamData = JSON.parse(btn.dataset.team);
1627                    let dropZone = null;
1628                    if (!awayTeam) {
1629                        dropZone = document.getElementById('awayDrop');
1630                        awayTeam = teamData.name;
1631                        // Disable this team button and add border
1632                        disableTeamButton(teamData.name);
1633                    } else if (!homeTeam) {
1634                        dropZone = document.getElementById('homeDrop');
1635                        homeTeam = teamData.name;
1636                        // Highlight home team button with border
1637                        highlightTeamButton(teamData.name);
1638                    }
1639                    if (dropZone) {
1640                        dropZone.style.backgroundColor = teamData.primary;
1641                        dropZone.style.color = darkColors.includes(teamData.secondary) ? '#FFFFFF' : teamData.secondary;
1642                        dropZone.innerHTML = \`
1643                            <div class="team-display" 
1644                                 style="width: 100%;
1645                                        height: 100%;
1646                                        display: flex;
1647                                        align-items: center;
1648                                        justify-content: center;">
1649                                \${teamData.name}
1650                            </div>
1651                        \`;
1652                        document.getElementById('result').textContent = '';
1653                        document.getElementById('clearBtn').disabled = false;
1654                        validateSelections();
1655                        updateCheckboxColors();
1656                    }
1657                });
1658                grid.appendChild(btn);
1659            });
1660
1661            document.querySelectorAll('.selected-team').forEach(zone => {
1662                zone.dataset.original = zone.innerHTML;
1663                zone.addEventListener('dragover', handleDragOver);
1664                zone.addEventListener('drop', handleTeamDrop);
1665            });
1666        }
1667
1668        function handleDragStart(e) {
1669            draggedItem = this;
1670            e.dataTransfer.setData('text/plain', this.dataset.team);
1671        }
1672
1673        function handleDragOver(e) {
1674            e.preventDefault();
1675        }
1676
1677        function handleGridDrop(e) {
1678            e.preventDefault();
1679            if (draggedItem !== this) {
1680                const grid = this.parentNode;
1681                const items = Array.from(grid.children);
1682                const oldIndex = items.indexOf(draggedItem);
1683                const newIndex = items.indexOf(this);
1684
1685                if (oldIndex < newIndex) {
1686                    grid.insertBefore(draggedItem, this.nextSibling);
1687                } else {
1688                    grid.insertBefore(draggedItem, this);
1689                }
1690                updateRanks();
1691            }
1692        }
1693
1694        function handleTeamDrop(e) {
1695            e.preventDefault();
1696            const team = JSON.parse(e.dataTransfer.getData('text/plain'));
1697            const dropZone = e.target.closest('.selected-team');
1698
1699            dropZone.style.backgroundColor = team.primary;
1700            dropZone.style.color = darkColors.includes(team.secondary) ? '#FFFFFF' : team.secondary;
1701            
1702            dropZone.innerHTML = \`
1703                <div class="team-display" 
1704                     style="width: 100%;
1705                            height: 100%;
1706                            display: flex;
1707                            align-items: center;
1708                            justify-content: center;">
1709                    \${team.name}
1710                </div>
1711            \`;
1712            
1713            if (dropZone.id === 'awayDrop') {
1714                awayTeam = team.name;
1715                // Disable this team button and add border
1716                disableTeamButton(team.name);
1717            }
1718            if (dropZone.id === 'homeDrop') {
1719                homeTeam = team.name;
1720                // Highlight home team button with border
1721                highlightTeamButton(team.name);
1722            }
1723            
1724            document.getElementById('result').textContent = '';
1725            document.getElementById('clearBtn').disabled = false;
1726            validateSelections();
1727            updateCheckboxColors();
1728        }
1729
1730        function updateRanks() {
1731            document.querySelectorAll('.team-btn').forEach((btn, index) => {
1732                btn.querySelector('small').textContent = \`Rank: \${index + 1}\`;
1733            });
1734        }
1735
1736        function clearTeams() {
1737            awayTeam = null;
1738            homeTeam = null;
1739            document.querySelectorAll('.selected-team').forEach(zone => {
1740                zone.style.backgroundColor = '#666';
1741                zone.style.color = 'white';
1742                zone.innerHTML = zone.dataset.original;
1743            });
1744            document.getElementById('result').textContent = '';
1745            document.getElementById('neutralSite').checked = false;
1746            // Commented out checkboxes - keep for potential future restoration
1747            // document.getElementById('homeInjury').checked = false;
1748            // document.getElementById('awayInjury').checked = false;
1749            // document.getElementById('positiveHomeMomentum').checked = false;
1750            // document.getElementById('negativeHomeMomentum').checked = false;
1751            // document.getElementById('positiveAwayMomentum').checked = false;
1752            // document.getElementById('negativeAwayMomentum').checked = false;
1753            document.getElementById('clearBtn').disabled = true;
1754            // Re-enable all team buttons
1755            enableAllTeamButtons();
1756            validateSelections();
1757            updateCheckboxColors();
1758        }
1759
1760        async function calculateOdds() {
1761            if (!awayTeam || !homeTeam || awayTeam === homeTeam) return;
1762
1763            const resultDiv = document.getElementById('result');
1764            resultDiv.textContent = 'Calculating...';
1765            
1766            // Wait 2 seconds before displaying the spread
1767            await new Promise(resolve => setTimeout(resolve, 2000));
1768            
1769            const awayRank = getCurrentRank(awayTeam);
1770            const homeRank = getCurrentRank(homeTeam);
1771            const rankDiff = awayRank - homeRank;
1772            const k = 0.5;
1773            const BASE_HOME_ADV = 2.0;
1774            const ADJUSTMENT = 0;
1775            const MAX_SPREAD = 18.5;
1776            const ABSOLUTE_MAX = 20.5;
1777            const INJURY_AWAY = 1.4;
1778            const INJURY_HOME = 0.91;
1779
1780            let baseSpread = k * rankDiff;
1781            let spread = baseSpread + BASE_HOME_ADV;
1782
1783            // NEW RULE: When away team is 1 rank higher than home team, home team favored by 3
1784            // This overrides all other conditions except injury and neutral site
1785            if (awayRank === homeRank - 1) {
1786                spread = 3.0; // Home team favored by 3 when they're ranked 1 position lower
1787            } else {
1788                // Apply rank 1 adjustment
1789                if (homeRank === 1) {
1790                    spread += 1.5; // Makes spread more positive, favoring home rank 1
1791                } else if (awayRank === 1) {
1792                    spread -= 1.5; // Makes spread more negative, favoring away rank 1
1793                }
1794
1795                // Apply specific matchup overrides
1796                if (awayRank === 2 && homeRank === 1) {
1797                    spread = 4.0; // Rank 1 favored by 4.0
1798                } else if (awayRank === 3 && homeRank === 1) {
1799                    spread = 4.5; // Rank 1 favored by 4.5
1800                } else if (awayRank === 1 && homeRank === 2) {
1801                    spread = 1.5; // Rank 2 favored by 1.5
1802                }
1803            }
1804
1805            // Apply offense/defense ranking adjustments
1806            const awayOffenseRank = getTeamOffenseRank(awayTeam);
1807            const awayDefenseRank = getTeamDefenseRank(awayTeam);
1808            const homeOffenseRank = getTeamOffenseRank(homeTeam);
1809            const homeDefenseRank = getTeamDefenseRank(homeTeam);
1810            
1811            const offenseDefenseAdjustment = calculateOffenseDefenseAdjustment(
1812                awayOffenseRank, awayDefenseRank, homeOffenseRank, homeDefenseRank, Math.abs(spread)
1813            );
1814            spread += offenseDefenseAdjustment;
1815
1816            // Apply injury adjustments - Commented out for potential future restoration
1817            // if (document.getElementById('awayInjury').checked) spread += INJURY_AWAY;
1818            // if (document.getElementById('homeInjury').checked) spread -= INJURY_HOME;
1819
1820            // Apply momentum adjustments with non-whole number logic
1821            // Helper function to determine adjustment that makes spread non-whole
1822            const getMomentumAdjustment = (baseAdjustment, alternateAdjustment) => {
1823                // Check if current spread is whole or half
1824                const isWhole = Math.abs(spread % 1) < 0.01;
1825                const isHalf = Math.abs((spread % 1) - 0.5) < 0.01;
1826                
1827                // If spread is currently whole, use the half adjustment; if half, use the whole adjustment
1828                if (isWhole) {
1829                    return alternateAdjustment; // This will make it non-whole
1830                } else if (isHalf) {
1831                    return baseAdjustment; // This will make it whole, so switch
1832                } else {
1833                    return baseAdjustment; // Use default
1834                }
1835            };
1836            
1837            // Commented out momentum adjustments for potential future restoration
1838            // Top 23 teams + positive home momentum: add 2 or 2.5 to make non-whole
1839            // if (document.getElementById('positiveHomeMomentum').checked && homeRank <= 23) {
1840            //     const adjustment = getMomentumAdjustment(2.0, 2.5);
1841            //     spread += adjustment;
1842            // }
1843            
1844            // Top 23 teams + positive away momentum: subtract 1.5 or 2 to make non-whole
1845            // if (document.getElementById('positiveAwayMomentum').checked && awayRank <= 23) {
1846            //     const adjustment = getMomentumAdjustment(2.0, 1.5);
1847            //     spread -= adjustment;
1848            // }
1849            
1850            // Top 23 teams + negative home momentum: subtract 1.5 or 2 to make non-whole
1851            // if (document.getElementById('negativeHomeMomentum').checked && homeRank <= 23) {
1852            //     const adjustment = getMomentumAdjustment(2.0, 1.5);
1853            //     spread -= adjustment;
1854            // }
1855            
1856            // Teams 24+ + negative home momentum: subtract 1.5 or 2 to make non-whole
1857            // if (document.getElementById('negativeHomeMomentum').checked && homeRank >= 24) {
1858            //     const adjustment = getMomentumAdjustment(2.0, 1.5);
1859            //     spread -= adjustment;
1860            // }
1861            
1862            // Teams 24+ + negative away momentum: add 2 or 2.5 to make non-whole
1863            // if (document.getElementById('negativeAwayMomentum').checked && awayRank >= 24) {
1864            //     const adjustment = getMomentumAdjustment(2.0, 2.5);
1865            //     spread += adjustment;
1866            // }
1867
1868            // Apply neutral site adjustment last
1869            if (document.getElementById('neutralSite').checked) spread -= BASE_HOME_ADV;
1870
1871            // Cap the spread
1872            spread = Math.min(Math.max(spread, -ABSOLUTE_MAX), ABSOLUTE_MAX);
1873            spread = Math.min(Math.max(spread, -MAX_SPREAD), MAX_SPREAD);
1874
1875            let rounded;
1876            const absSpread = Math.abs(spread);
1877            if (absSpread < 0.7) {
1878                rounded = 0;
1879            } else if (absSpread < 1.25) {
1880                rounded = Math.sign(spread) * 1.0;
1881            } else {
1882                rounded = Math.round(spread * 2) / 2;
1883            }
1884
1885            const formatted = rounded % 1 === 0 ? Math.abs(rounded).toFixed(0) : Math.abs(rounded).toFixed(1);
1886            const favoredTeam = rounded >= 0 ? homeTeam : awayTeam;
1887
1888            // Get favored team's color
1889            const favoredTeamData = teams.find(t => t.name === favoredTeam);
1890            const favoredTeamColor = favoredTeamData ? favoredTeamData.primary : '#000000';
1891
1892            resultDiv.innerHTML = rounded !== 0 
1893                ? \`<strong style="color: \${favoredTeamColor};">Spread: \${favoredTeam} -\${formatted}</strong>\` 
1894                : \`<strong>Even matchup</strong>\`;
1895        }
1896
1897        function getCurrentRank(teamName) {
1898            const buttons = document.querySelectorAll('.team-btn');
1899            for (let i = 0; i < buttons.length; i++) {
1900                if (buttons[i].textContent.includes(teamName)) {
1901                    return i + 1;
1902                }
1903            }
1904            return 32;
1905        }
1906
1907        function getTeamOffenseRank(teamName) {
1908            // Convert short name to full name for lookup
1909            const fullName = getFullTeamName(teamName);
1910            return offenseRanks[fullName] || offenseRanks[teamName] || 16; // Default to middle rank if not found
1911        }
1912
1913        function getTeamDefenseRank(teamName) {
1914            // Convert short name to full name for lookup
1915            const fullName = getFullTeamName(teamName);
1916            return defenseRanks[fullName] || defenseRanks[teamName] || 16; // Default to middle rank if not found
1917        }
1918
1919        function getFullTeamName(shortName) {
1920            const teamMap = {
1921                'Eagles': 'Philadelphia Eagles',
1922                'Chiefs': 'Kansas City Chiefs',
1923                'Ravens': 'Baltimore Ravens',
1924                'Bills': 'Buffalo Bills',
1925                'Lions': 'Detroit Lions',
1926                'Commanders': 'Washington Commanders',
1927                'Rams': 'Los Angeles Rams',
1928                '49ers': 'San Francisco 49ers',
1929                'Packers': 'Green Bay Packers',
1930                'Vikings': 'Minnesota Vikings',
1931                'Chargers': 'Los Angeles Chargers',
1932                'Bengals': 'Cincinnati Bengals',
1933                'Buccaneers': 'Tampa Bay Buccaneers',
1934                'Broncos': 'Denver Broncos',
1935                'Cowboys': 'Dallas Cowboys',
1936                'Texans': 'Houston Texans',
1937                'Bears': 'Chicago Bears',
1938                'Steelers': 'Pittsburgh Steelers',
1939                'Seahawks': 'Seattle Seahawks',
1940                'Cardinals': 'Arizona Cardinals',
1941                'Dolphins': 'Miami Dolphins',
1942                'Saints': 'New Orleans Saints',
1943                'Titans': 'Tennessee Titans',
1944                'Jets': 'New York Jets',
1945                'Patriots': 'New England Patriots',
1946                'Colts': 'Indianapolis Colts',
1947                'Jaguars': 'Jacksonville Jaguars',
1948                'Raiders': 'Las Vegas Raiders',
1949                'Falcons': 'Atlanta Falcons',
1950                'Browns': 'Cleveland Browns',
1951                'Panthers': 'Carolina Panthers',
1952                'Giants': 'New York Giants'
1953            };
1954            return teamMap[shortName] || shortName;
1955        }
1956
1957        function calculateOffenseDefenseAdjustment(awayOffenseRank, awayDefenseRank, homeOffenseRank, homeDefenseRank, currentSpread) {
1958            // Check if a team is highly ranked in both offense and defense (top 10 in both)
1959            // or lowly ranked in both (bottom 10 in both)
1960            const awayHighInBoth = awayOffenseRank <= 10 && awayDefenseRank <= 10;
1961            const awayLowInBoth = awayOffenseRank >= 23 && awayDefenseRank >= 23;
1962            const homeHighInBoth = homeOffenseRank <= 10 && homeDefenseRank <= 10;
1963            const homeLowInBoth = homeOffenseRank >= 23 && homeDefenseRank >= 23;
1964
1965            let adjustment = 0;
1966
1967            // If current spread is 8 or less
1968            if (currentSpread <= 8) {
1969                if (homeHighInBoth && !awayHighInBoth) {
1970                    adjustment = 0.5; // Favor home team by extra 0.5 points
1971                } else if (awayHighInBoth && !homeHighInBoth) {
1972                    adjustment = -0.5; // Favor away team by extra 0.5 points
1973                } else if (homeLowInBoth && !awayLowInBoth) {
1974                    adjustment = -0.5; // Penalize home team by 0.5 points
1975                } else if (awayLowInBoth && !homeLowInBoth) {
1976                    adjustment = 0.5; // Penalize away team by 0.5 points
1977                }
1978            } 
1979            // If current spread is 8.5 or more
1980            else if (currentSpread >= 8.5) {
1981                if (homeHighInBoth && !awayHighInBoth) {
1982                    adjustment = Math.random() < 0.5 ? 0.5 : 1.0; // Random 0.5 or 1.0 points
1983                } else if (awayHighInBoth && !homeHighInBoth) {
1984                    adjustment = Math.random() < 0.5 ? -0.5 : -1.0; // Random -0.5 or -1.0 points
1985                } else if (homeLowInBoth && !awayLowInBoth) {
1986                    adjustment = Math.random() < 0.5 ? -0.5 : -1.0; // Penalize home team
1987                } else if (awayLowInBoth && !homeLowInBoth) {
1988                    adjustment = Math.random() < 0.5 ? 0.5 : 1.0; // Penalize away team
1989                }
1990            }
1991
1992            console.log(\`Offense/Defense Adjustment: Away O:\${awayOffenseRank} D:\${awayDefenseRank}, Home O:\${homeOffenseRank} D:\${homeDefenseRank}, Spread:\${currentSpread}, Adjustment:\${adjustment}\`);
1993            return adjustment;
1994        }
1995
1996        window.addEventListener('load', () => {
1997            console.log('Window loaded, loading power rankings first');
1998            // Set logo src to use parent window origin for proper image loading in iframe
1999            const baseUrl = window.parent.location.origin;
2000            const headerLogo = document.getElementById('headerLogo');
2001            const mobileHeaderLogo = document.getElementById('mobileHeaderLogo');
2002            if (headerLogo) headerLogo.src = \`\${baseUrl}/public/hq-logo.png\`;
2003            if (mobileHeaderLogo) mobileHeaderLogo.src = \`\${baseUrl}/public/hq-logo.png\`;
2004            loadLivePowerRankings(); // Use live power rankings from Google Sheets API first, then initialize grid
2005        });
2006    <\/script>
2007</body>
2008</html>`,i=new Blob([r],{type:"text/html"}),o=URL.createObjectURL(i),e=document.createElement("iframe");e.src=o,e.className="odds-calculator-iframe",e.style.width="100%",e.style.border="none",e.style.overflow="hidden",e.scrolling="no";const a=document.getElementById("calculator-content");return a&&(a.innerHTML="",a.appendChild(e)),()=>{URL.revokeObjectURL(o)}},[]),t.jsxs("div",{style:{width:"100%",minHeight:"100vh",display:"flex",flexDirection:"column"},children:[t.jsx("style",{children:`
2009        .odds-calculator-iframe {
2010          height: 100vh;
2011        }
2012        @media (max-width: 768px) {
2013          .odds-calculator-iframe {
2014            height: 1450px; /* Reduced fixed height for mobile to condense blank space */
2015          }
2016        }
2017      `}),t.jsx(l,{showDesktopNavigation:!1}),t.jsx("div",{id:"calculator-content",style:{width:"100%",flex:1}})]})}export{c as default};

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.