Nagaraj81 commited on
Commit
63b0483
Β·
verified Β·
1 Parent(s): 607396e

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +781 -0
index.html ADDED
@@ -0,0 +1,781 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!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>Options Intelligence β€” MSFT Β· BMNR Β· IREN Β· CRCL</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,300;0,400;0,500;0,600;0,700;1,400&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"/>
8
+ <style>
9
+ :root{
10
+ --bg:#F7F8FA;--surface:#fff;--surface2:#F0F2F7;
11
+ --border:#E2E5EE;--border2:#C8CCDB;
12
+ --t1:#0D0F1A;--t2:#3D4460;--t3:#8B92AA;
13
+ --blue:#1A56DB;--blue-l:#EBF1FF;--blue-d:#1341B0;
14
+ --green:#0A7A45;--green-l:#E8F8F0;--green-m:#D1F0E0;
15
+ --red:#CC2828;--red-l:#FFF0F0;--red-m:#FFD8D8;
16
+ --amber:#B45309;--amber-l:#FFF8ED;--amber-m:#FDECC8;
17
+ --purple:#6326C7;--purple-l:#F3EEFF;
18
+ --sh:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);
19
+ --sh2:0 4px 16px rgba(0,0,0,.09),0 2px 6px rgba(0,0,0,.05);
20
+ --r:10px;
21
+ }
22
+ *{box-sizing:border-box;margin:0;padding:0}
23
+ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--t1);-webkit-font-smoothing:antialiased;min-height:100vh}
24
+ a{color:var(--blue);text-decoration:none}a:hover{text-decoration:underline}
25
+ button,input{font-family:inherit;cursor:pointer}
26
+ textarea:focus,input:focus{outline:none}
27
+ ::-webkit-scrollbar{width:5px}::-webkit-scrollbar-track{background:var(--bg)}
28
+ ::-webkit-scrollbar-thumb{background:var(--border2);border-radius:3px}
29
+
30
+ /* ── HEADER ── */
31
+ .hdr{background:var(--surface);border-bottom:1px solid var(--border);padding:0 28px;position:sticky;top:0;z-index:100;box-shadow:var(--sh)}
32
+ .hdr-in{max-width:1280px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;height:58px}
33
+ .logo{display:flex;align-items:center;gap:10px}
34
+ .logo-mark{width:34px;height:34px;background:linear-gradient(135deg,#1A56DB,#6326C7);border-radius:9px;display:flex;align-items:center;justify-content:center;font-size:17px;box-shadow:0 2px 8px rgba(26,86,219,.3)}
35
+ .logo-title{font-size:16px;font-weight:700;letter-spacing:-.4px}
36
+ .logo-sub{font-size:11px;color:var(--t3);margin-top:1px}
37
+ .hdr-right{display:flex;align-items:center;gap:12px}
38
+ .hdr-time{font-size:11px;color:var(--t3)}
39
+ .hdr-vix{font-size:12px;font-weight:600;padding:4px 10px;border-radius:6px;background:var(--surface2);border:1px solid var(--border);display:none}
40
+ .btn-refresh{display:flex;align-items:center;gap:6px;padding:8px 18px;background:var(--blue);color:#fff;border:none;border-radius:8px;font-size:13px;font-weight:600;letter-spacing:-.1px;transition:all .15s}
41
+ .btn-refresh:hover:not(:disabled){background:var(--blue-d);transform:translateY(-1px);box-shadow:0 3px 10px rgba(26,86,219,.35)}
42
+ .btn-refresh:disabled{background:var(--border2);color:var(--t3);cursor:not-allowed;transform:none;box-shadow:none}
43
+ @keyframes spin{to{transform:rotate(360deg)}}
44
+ .spin{animation:spin .8s linear infinite}
45
+ @keyframes fadeUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
46
+
47
+ /* ── GATE ── */
48
+ #gate{min-height:calc(100vh - 58px);display:flex;align-items:center;justify-content:center;padding:32px 16px}
49
+ .gate-card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:40px;max-width:460px;width:100%;box-shadow:var(--sh2)}
50
+ .gate-logo{width:52px;height:52px;background:linear-gradient(135deg,#1A56DB,#6326C7);border-radius:14px;display:flex;align-items:center;justify-content:center;font-size:26px;margin:0 auto 20px;box-shadow:0 4px 12px rgba(26,86,219,.3)}
51
+ .gate-h{font-size:21px;font-weight:700;text-align:center;margin-bottom:8px;letter-spacing:-.4px}
52
+ .gate-p{font-size:13px;color:var(--t2);text-align:center;line-height:1.65;margin-bottom:28px}
53
+ .gate-lbl{font-size:12px;font-weight:600;color:var(--t2);margin-bottom:6px}
54
+ .gate-inp{width:100%;padding:11px 14px;border:1.5px solid var(--border);border-radius:8px;font-size:13px;font-family:'JetBrains Mono',monospace;color:var(--t1);background:var(--bg);transition:border-color .15s;margin-bottom:6px}
55
+ .gate-inp:focus{border-color:var(--blue);background:#fff}
56
+ .gate-hint{font-size:11px;color:var(--t3);line-height:1.6;margin-bottom:20px}
57
+ .gate-err{font-size:12px;color:var(--red);margin-bottom:10px;display:none}
58
+ .btn-start{width:100%;padding:12px;background:var(--blue);color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:700;transition:all .15s}
59
+ .btn-start:hover{background:var(--blue-d)}
60
+ .feat-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-top:24px}
61
+ .feat{padding:11px 14px;background:var(--bg);border-radius:8px;border:1px solid var(--border);font-size:11px;color:var(--t2);display:flex;align-items:flex-start;gap:8px;line-height:1.4}
62
+ .feat-ic{font-size:15px;flex-shrink:0}
63
+
64
+ /* ── PAGE ── */
65
+ .page{max-width:1280px;margin:0 auto;padding:24px 28px 48px}
66
+
67
+ /* ── SUMMARY STRIP ── */
68
+ .summary-strip{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:0;margin-bottom:24px;overflow:hidden;box-shadow:var(--sh)}
69
+ .summary-hdr{padding:12px 20px;background:var(--surface2);border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}
70
+ .summary-hdr-title{font-size:12px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;color:var(--t3)}
71
+ .summary-table{width:100%;border-collapse:collapse}
72
+ .summary-table th{padding:10px 16px;font-size:10px;font-weight:700;letter-spacing:.7px;text-transform:uppercase;color:var(--t3);text-align:left;border-bottom:1px solid var(--border);background:var(--surface)}
73
+ .summary-table td{padding:13px 16px;font-size:13px;border-bottom:1px solid var(--border);vertical-align:middle}
74
+ .summary-table tr:last-child td{border-bottom:none}
75
+ .summary-table tr:hover td{background:#FAFBFF}
76
+ .sticker{font-size:14px;font-weight:800;letter-spacing:-.3px}
77
+ .sprice{font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:500}
78
+ .schg{font-size:11px;font-weight:600;padding:2px 7px;border-radius:4px;font-family:'JetBrains Mono',monospace;margin-left:6px}
79
+ .up{background:var(--green-m);color:var(--green)}.dn{background:var(--red-m);color:var(--red)}.fl{background:var(--surface2);color:var(--t3)}
80
+ .strategy-pill{display:inline-flex;align-items:center;padding:4px 10px;border-radius:6px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;white-space:nowrap}
81
+ .conf-badge{font-size:10px;font-weight:700;padding:2px 7px;border-radius:4px;text-transform:uppercase;letter-spacing:.3px}
82
+ .conf-high{background:var(--green-m);color:var(--green)}
83
+ .conf-med{background:var(--amber-m);color:var(--amber)}
84
+ .conf-low{background:var(--surface2);color:var(--t3)}
85
+ .mono{font-family:'JetBrains Mono',monospace;font-size:12px}
86
+ .summary-loading td{color:var(--t3);font-style:italic;font-size:12px}
87
+
88
+ /* ── TICKER CARDS ── */
89
+ .cards-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:20px}
90
+ @media(max-width:900px){.cards-grid{grid-template-columns:1fr}}
91
+
92
+ .tcard{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);overflow:hidden;box-shadow:var(--sh);animation:fadeUp .35s ease both}
93
+ .tcard:hover{box-shadow:var(--sh2)}
94
+
95
+ .tcard-hdr{padding:16px 20px;border-bottom:1px solid var(--border);display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
96
+ .tcard-ticker{font-size:20px;font-weight:800;letter-spacing:-.5px}
97
+ .tcard-name{font-size:11px;color:var(--t3);margin-top:2px}
98
+ .tcard-price{text-align:right;flex-shrink:0}
99
+ .price-big{font-size:20px;font-weight:700;font-family:'JetBrains Mono',monospace}
100
+ .price-chg{font-size:11px;font-weight:600;padding:2px 8px;border-radius:5px;margin-top:4px;display:inline-block;font-family:'JetBrains Mono',monospace}
101
+
102
+ /* stats row */
103
+ .stats-band{display:grid;grid-template-columns:repeat(4,1fr);border-bottom:1px solid var(--border)}
104
+ .sc{padding:11px 14px;border-right:1px solid var(--border)}
105
+ .sc:last-child{border-right:none}
106
+ .sc-l{font-size:10px;font-weight:600;letter-spacing:.7px;text-transform:uppercase;color:var(--t3);margin-bottom:4px}
107
+ .sc-v{font-size:14px;font-weight:700;font-family:'JetBrains Mono',monospace}
108
+ .sc-s{font-size:10px;color:var(--t3);margin-top:2px}
109
+
110
+ /* IV bar */
111
+ .iv-bar-wrap{padding:13px 20px;border-bottom:1px solid var(--border)}
112
+ .iv-bar-row{display:flex;align-items:center;justify-content:space-between;margin-bottom:7px}
113
+ .iv-bar-lbl{font-size:11px;font-weight:600;color:var(--t2)}
114
+ .iv-regime-tag{font-size:10px;font-weight:700;padding:2px 9px;border-radius:10px;text-transform:uppercase;letter-spacing:.4px}
115
+ .rt-sell{background:var(--red-l);color:var(--red)}
116
+ .rt-buy{background:var(--green-l);color:var(--green)}
117
+ .rt-neutral{background:var(--amber-l);color:var(--amber)}
118
+ .iv-track{height:6px;background:var(--surface2);border-radius:3px;overflow:hidden;border:1px solid var(--border)}
119
+ .iv-fill{height:100%;border-radius:3px;transition:width .8s ease}
120
+
121
+ /* news pill */
122
+ .news-row{padding:9px 20px;border-bottom:1px solid var(--border);display:flex;align-items:flex-start;gap:8px;background:#FAFBFE}
123
+ .news-tag{font-size:10px;font-weight:700;padding:2px 7px;border-radius:4px;background:var(--blue-l);color:var(--blue);flex-shrink:0;margin-top:1px;text-transform:uppercase;letter-spacing:.3px}
124
+ .news-text{font-size:11px;color:var(--t2);line-height:1.55;flex:1}
125
+ .news-src{font-size:10px;color:var(--t3);margin-top:2px}
126
+
127
+ /* recommendation block */
128
+ .rec-block{padding:18px 20px;border-bottom:1px solid var(--border)}
129
+ .rec-block-title{font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--t3);margin-bottom:12px}
130
+
131
+ .rec-banner{border-radius:9px;padding:14px;margin-bottom:14px;border:1.5px solid}
132
+ .rec-top-row{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:10px}
133
+ .rec-strat-name{font-size:15px;font-weight:800;letter-spacing:-.3px}
134
+ .rec-dir{font-size:11px;color:var(--t2);margin-top:2px}
135
+ .rec-conf{text-align:right;flex-shrink:0}
136
+ .rec-strike-row{display:flex;flex-wrap:wrap;gap:10px}
137
+ .rec-chip{display:flex;flex-direction:column;padding:7px 12px;border-radius:6px;background:rgba(255,255,255,.7);border:1px solid rgba(0,0,0,.06)}
138
+ .rec-chip-l{font-size:9px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--t3);margin-bottom:3px}
139
+ .rec-chip-v{font-size:13px;font-weight:700;font-family:'JetBrains Mono',monospace}
140
+
141
+ /* P&L row */
142
+ .pnl-row{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:12px}
143
+ .pnl-box{padding:9px 11px;border-radius:7px;border:1px solid var(--border);background:var(--bg)}
144
+ .pnl-l{font-size:9px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--t3);margin-bottom:3px}
145
+ .pnl-v{font-size:12px;font-weight:700;font-family:'JetBrains Mono',monospace}
146
+
147
+ /* greeks row */
148
+ .greeks-row{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-bottom:14px}
149
+ .greek-box{padding:8px 10px;background:var(--surface2);border-radius:6px;text-align:center}
150
+ .greek-sym{font-size:14px;font-weight:700;color:var(--t2);margin-bottom:2px}
151
+ .greek-val{font-size:11px;font-family:'JetBrains Mono',monospace;color:var(--t1);font-weight:500}
152
+ .greek-lbl{font-size:9px;color:var(--t3);margin-top:1px}
153
+
154
+ /* plain english */
155
+ .plain-block{padding:16px 20px;border-bottom:1px solid var(--border);background:#FAFCFF}
156
+ .plain-title{font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--blue);margin-bottom:8px;display:flex;align-items:center;gap:5px}
157
+ .plain-text{font-size:13px;line-height:1.75;color:var(--t2)}
158
+ .plain-text strong{color:var(--t1);font-weight:600}
159
+
160
+ /* risk + pass */
161
+ .risk-block{padding:12px 20px;border-bottom:1px solid var(--border);background:#FFFBF5}
162
+ .risk-tag{font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--amber);margin-bottom:5px}
163
+ .risk-text{font-size:12px;line-height:1.65;color:#78350F}
164
+
165
+ .pass-block{padding:12px 20px;border-bottom:1px solid var(--border)}
166
+ .pass-tag{font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--t3);margin-bottom:5px}
167
+ .pass-text{font-size:12px;line-height:1.65;color:var(--t2)}
168
+
169
+ /* alt trade */
170
+ .alt-block{padding:12px 20px;border-bottom:1px solid var(--border)}
171
+ .alt-tag{font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--t3);margin-bottom:6px}
172
+ .alt-inner{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;background:var(--bg);border-radius:7px;border:1px solid var(--border)}
173
+ .alt-text{font-size:12px;line-height:1.6;color:var(--t2)}
174
+
175
+ /* scores */
176
+ .scores-block{padding:14px 20px}
177
+ .scores-title{font-size:10px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;color:var(--t3);margin-bottom:10px}
178
+ .score-row{display:flex;align-items:center;gap:8px;margin-bottom:5px}
179
+ .score-nm{font-size:11px;color:var(--t2);min-width:130px}
180
+ .score-tr{flex:1;height:5px;background:var(--surface2);border-radius:3px;overflow:hidden}
181
+ .score-fi{height:100%;border-radius:3px;transition:width 1s ease}
182
+ .score-n{font-size:11px;font-weight:700;min-width:26px;text-align:right;font-family:'JetBrains Mono',monospace}
183
+
184
+ /* loading state */
185
+ .card-loading{padding:32px 20px;display:flex;flex-direction:column;align-items:center;gap:10px}
186
+ .ld-spinner{width:28px;height:28px;border:2.5px solid var(--border);border-top-color:var(--blue);border-radius:50%;animation:spin .7s linear infinite}
187
+ .ld-text{font-size:13px;color:var(--t3)}
188
+ .ld-steps{font-size:11px;color:var(--border2);text-align:center;line-height:1.8}
189
+
190
+ /* error state */
191
+ .card-err{padding:28px 20px;text-align:center}
192
+ .card-err-ico{font-size:30px;margin-bottom:8px}
193
+ .card-err-msg{font-size:13px;color:var(--t2);line-height:1.6;margin-bottom:14px}
194
+ .btn-retry{padding:7px 16px;border:1px solid var(--border);border-radius:6px;background:var(--bg);color:var(--blue);font-size:12px;font-weight:600;cursor:pointer;font-family:inherit;transition:background .15s}
195
+ .btn-retry:hover{background:var(--blue-l)}
196
+
197
+ /* strategy color classes */
198
+ .s-sp{background:var(--purple-l);border-color:#C4B5FD}.b-sp{background:var(--purple-l);color:var(--purple)}
199
+ .s-sc{background:var(--amber-l);border-color:#FCD34D}.b-sc{background:var(--amber-l);color:var(--amber)}
200
+ .s-bc{background:var(--green-l);border-color:#6EE7B7}.b-bc{background:var(--green-l);color:var(--green)}
201
+ .s-bp{background:var(--red-l);border-color:#FCA5A5}.b-bp{background:var(--red-l);color:var(--red)}
202
+ .s-st{background:var(--blue-l);border-color:#93C5FD}.b-st{background:var(--blue-l);color:var(--blue)}
203
+ .s-sg{background:var(--blue-l);border-color:#BFDBFE}.b-sg{background:var(--blue-l);color:var(--blue)}
204
+ .s-ic{background:#F0FDF4;border-color:#86EFAC}.b-ic{background:#F0FDF4;color:#16A34A}
205
+ .s-bs{background:var(--green-l);border-color:#6EE7B7}.b-bs{background:var(--green-l);color:var(--green)}
206
+ .s-ps{background:var(--red-l);border-color:#FCA5A5}.b-ps{background:var(--red-l);color:var(--red)}
207
+ .s-df{background:var(--bg);border-color:var(--border)}.b-df{background:var(--bg);color:var(--t2)}
208
+
209
+ footer{padding:20px 28px;text-align:center;font-size:11px;color:var(--t3);border-top:1px solid var(--border);line-height:1.8;background:var(--surface)}
210
+ @media(max-width:700px){.page{padding:14px}.stats-band{grid-template-columns:repeat(2,1fr)}.pnl-row{grid-template-columns:repeat(2,1fr)}.greeks-row{grid-template-columns:repeat(2,1fr)}.hdr{padding:0 14px}}
211
+ </style>
212
+ </head>
213
+ <body>
214
+
215
+ <!-- HEADER -->
216
+ <header class="hdr">
217
+ <div class="hdr-in">
218
+ <div class="logo">
219
+ <div class="logo-mark">πŸ“ˆ</div>
220
+ <div>
221
+ <div class="logo-title">Options Intelligence</div>
222
+ <div class="logo-sub">MSFT Β· BMNR Β· IREN Β· CRCL β€” Live AI Recommendations</div>
223
+ </div>
224
+ </div>
225
+ <div class="hdr-right">
226
+ <span class="hdr-vix" id="hdr-vix"></span>
227
+ <span class="hdr-time" id="hdr-time"></span>
228
+ <button class="btn-refresh" id="btn-refresh" onclick="refreshAll()" disabled>
229
+ <svg id="ref-icon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 019-9 9.75 9.75 0 016.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 01-9 9 9.75 9.75 0 01-6.74-2.74L3 16"/><path d="M3 21v-5h5"/></svg>
230
+ Refresh
231
+ </button>
232
+ </div>
233
+ </div>
234
+ </header>
235
+
236
+ <!-- GATE -->
237
+ <div id="gate">
238
+ <div class="gate-card">
239
+ <div class="gate-logo">πŸ“Š</div>
240
+ <div class="gate-h">Options Intelligence Dashboard</div>
241
+ <div class="gate-p">Live AI-powered options recommendations for <strong>MSFT, BMNR, IREN, CRCL</strong>. Each refresh searches live market data and generates a fresh trade recommendation with plain English explanations.</div>
242
+ <div class="gate-lbl">Anthropic API Key</div>
243
+ <input type="password" id="gate-key" class="gate-inp" placeholder="sk-ant-api03-…"/>
244
+ <div class="gate-hint">Your key stays in your browser only β€” never stored anywhere. Get one free at <a href="https://console.anthropic.com" target="_blank">console.anthropic.com</a>. Cost per refresh: ~$0.08–0.12.</div>
245
+ <div class="gate-err" id="gate-err"></div>
246
+ <button class="btn-start" onclick="startApp()">Launch Dashboard β†’</button>
247
+ <div class="feat-grid">
248
+ <div class="feat"><div class="feat-ic">πŸ”</div><div>Live web search for current prices, IV and news on every refresh</div></div>
249
+ <div class="feat"><div class="feat-ic">πŸ“°</div><div>News sources shown β€” know where the information came from</div></div>
250
+ <div class="feat"><div class="feat-ic">πŸ’¬</div><div>Plain English explanation of every recommendation</div></div>
251
+ <div class="feat"><div class="feat-ic">🎯</div><div>Exact strike, expiry, entry price and breakevens</div></div>
252
+ <div class="feat"><div class="feat-ic">⚑</div><div>Greeks: Delta, Gamma, Theta, Vega for every trade</div></div>
253
+ <div class="feat"><div class="feat-ic">⚠️</div><div>Risk scenario and "skip if" conditions per ticker</div></div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+
258
+ <!-- APP -->
259
+ <div id="app" style="display:none">
260
+ <div class="page">
261
+
262
+ <!-- Summary strip -->
263
+ <div class="summary-strip">
264
+ <div class="summary-hdr">
265
+ <span class="summary-hdr-title">πŸ“‹ At-a-Glance Summary β€” What to trade today</span>
266
+ <span style="font-size:11px;color:var(--t3)" id="summary-ts"></span>
267
+ </div>
268
+ <table class="summary-table" id="summary-tbl">
269
+ <thead>
270
+ <tr>
271
+ <th>Ticker</th>
272
+ <th>Price</th>
273
+ <th>Strategy</th>
274
+ <th>Strike</th>
275
+ <th>Expiry / DTE</th>
276
+ <th>Entry (Mid)</th>
277
+ <th>Max Profit</th>
278
+ <th>Max Loss</th>
279
+ <th>Confidence</th>
280
+ </tr>
281
+ </thead>
282
+ <tbody id="summary-body">
283
+ <tr class="summary-loading">
284
+ <td colspan="9" style="padding:18px 16px;color:var(--t3);font-style:italic;font-size:12px">⏳ Loading live data…</td>
285
+ </tr>
286
+ </tbody>
287
+ </table>
288
+ </div>
289
+
290
+ <!-- Ticker cards -->
291
+ <div class="cards-grid" id="cards-grid"></div>
292
+
293
+ </div>
294
+ <footer>
295
+ Options Intelligence Β· Powered by Claude AI + Live Web Search<br/>
296
+ <strong>⚠ Not financial advice.</strong> Options trading involves substantial risk of loss. Always verify recommendations independently before placing any trade.
297
+ </footer>
298
+ </div>
299
+
300
+ <script>
301
+ 'use strict';
302
+
303
+ // ── CONFIG ──────────────────────────────────────────────────
304
+ const TICKERS = [
305
+ {sym:'MSFT', name:'Microsoft Corporation'},
306
+ {sym:'BMNR', name:'BitMine Immersion Technologies'},
307
+ {sym:'IREN', name:'Iris Energy'},
308
+ {sym:'CRCL', name:'Circle Internet Financial'},
309
+ ];
310
+
311
+ // Strategy type β†’ CSS class key
312
+ const TYPE_MAP = {
313
+ sell_put:'sp', sell_call:'sc', buy_call:'bc', buy_put:'bp',
314
+ straddle:'st', strangle:'sg', condor:'ic',
315
+ bull_spread:'bs', bear_spread:'ps',
316
+ };
317
+
318
+ let API_KEY = '';
319
+ let running = false;
320
+ let results = {}; // sym β†’ parsed data
321
+
322
+ // ── GATE ─────────────────────────────────────────────────────
323
+ document.getElementById('gate-key').addEventListener('keydown', e => { if(e.key==='Enter') startApp(); });
324
+
325
+ function startApp(){
326
+ const k = document.getElementById('gate-key').value.trim();
327
+ const err = document.getElementById('gate-err');
328
+ if(!k.startsWith('sk-ant-')){ err.textContent='⚠ Key must start with sk-ant-'; err.style.display='block'; return; }
329
+ err.style.display='none';
330
+ API_KEY = k;
331
+ document.getElementById('gate').style.display='none';
332
+ document.getElementById('app').style.display='block';
333
+ document.getElementById('btn-refresh').disabled=false;
334
+ initCards();
335
+ refreshAll();
336
+ }
337
+
338
+ // ── INIT CARDS ────────────────────────────────────────────────
339
+ function initCards(){
340
+ const grid = document.getElementById('cards-grid');
341
+ grid.innerHTML='';
342
+ TICKERS.forEach((t,i)=>{
343
+ const d=document.createElement('div');
344
+ d.className='tcard';
345
+ d.id='card-'+t.sym;
346
+ d.style.animationDelay=(i*0.08)+'s';
347
+ d.innerHTML=loadingHTML(t);
348
+ grid.appendChild(d);
349
+ });
350
+ }
351
+
352
+ function loadingHTML(t){
353
+ return `<div class="tcard-hdr"><div><div class="tcard-ticker">${t.sym}</div><div class="tcard-name">${t.name}</div></div></div>
354
+ <div class="card-loading"><div class="ld-spinner"></div><div class="ld-text">Searching live data…</div>
355
+ <div class="ld-steps">Fetching price &amp; options chain<br>Calculating IV Rank &amp; Greeks<br>Generating AI recommendation</div></div>`;
356
+ }
357
+
358
+ // ── REFRESH ALL ───────────────────────────────────────────────
359
+ async function refreshAll(){
360
+ if(running) return;
361
+ running=true;
362
+ results={};
363
+ const btn=document.getElementById('btn-refresh');
364
+ const ico=document.getElementById('ref-icon');
365
+ btn.disabled=true; ico.classList.add('spin');
366
+ document.getElementById('summary-body').innerHTML=
367
+ '<tr><td colspan="9" style="padding:18px 16px;color:var(--t3);font-style:italic;font-size:12px">⏳ Loading…</td></tr>';
368
+
369
+ // Reset cards
370
+ TICKERS.forEach(t=>{ document.getElementById('card-'+t.sym).innerHTML=loadingHTML(t); });
371
+
372
+ // Run all in parallel
373
+ await Promise.allSettled(TICKERS.map(t=>fetchAndRender(t)));
374
+
375
+ // Rebuild summary after all done
376
+ buildSummary();
377
+
378
+ const now=new Date();
379
+ const ts=now.toLocaleTimeString('en-US',{hour:'2-digit',minute:'2-digit'});
380
+ document.getElementById('hdr-time').textContent='Updated '+ts;
381
+ document.getElementById('summary-ts').textContent='Last updated '+ts;
382
+
383
+ ico.classList.remove('spin');
384
+ btn.disabled=false;
385
+ running=false;
386
+ }
387
+
388
+ // ── FETCH + RENDER ONE TICKER ─────────────────────────────────
389
+ async function fetchAndRender(ticker){
390
+ try{
391
+ const d=await callClaude(ticker);
392
+ results[ticker.sym]=d;
393
+ renderCard(ticker,d);
394
+ }catch(e){
395
+ renderError(ticker,e.message);
396
+ }
397
+ }
398
+
399
+ // ── CLAUDE API ────────────────────────────────────────────────
400
+ async function callClaude(ticker){
401
+ const today=new Date().toISOString().split('T')[0];
402
+ const dow=new Date().toLocaleDateString('en-US',{weekday:'long'});
403
+
404
+ const resp=await fetch('https://api.anthropic.com/v1/messages',{
405
+ method:'POST',
406
+ headers:{
407
+ 'Content-Type':'application/json',
408
+ 'x-api-key':API_KEY,
409
+ 'anthropic-version':'2023-06-01',
410
+ 'anthropic-dangerous-direct-browser-access':'true',
411
+ },
412
+ body:JSON.stringify({
413
+ model:'claude-sonnet-4-20250514',
414
+ max_tokens:1800,
415
+ tools:[{type:'web_search_20250305',name:'web_search'}],
416
+ system:`You are a senior options trader and quantitative analyst. Today is ${dow} ${today}.
417
+ Your job: Search for LIVE current data on the given stock ticker, then produce a precise options recommendation as JSON.
418
+ RULES:
419
+ 1. Always search the web first β€” never use stale training data for prices or IV
420
+ 2. Search for: current stock price, today's % change, options IV, recent news/catalysts, upcoming earnings, current VIX
421
+ 3. After gathering data, return ONLY valid JSON matching the exact schema. No markdown fences, no prose outside the JSON.
422
+ 4. Include the actual source name (e.g. "Reuters", "Yahoo Finance", "Bloomberg") for any news cited.`,
423
+ messages:[{role:'user',content:buildPrompt(ticker,today)}],
424
+ }),
425
+ });
426
+
427
+ if(!resp.ok){
428
+ const e=await resp.json().catch(()=>({}));
429
+ throw new Error((e.error&&e.error.message)||'API error '+resp.status);
430
+ }
431
+
432
+ const data=await resp.json();
433
+ // Extract text blocks (web search tool may produce mixed content blocks)
434
+ const text=(data.content||[]).filter(b=>b.type==='text').map(b=>b.text).join('');
435
+
436
+ // Robust JSON extraction
437
+ let js=text;
438
+ const fm=js.match(/```(?:json)?\s*([\s\S]*?)```/);
439
+ if(fm) js=fm[1];
440
+ const a=js.indexOf('{'), b=js.lastIndexOf('}');
441
+ if(a!==-1&&b!==-1) js=js.slice(a,b+1);
442
+
443
+ try{ return JSON.parse(js); }
444
+ catch(e){ throw new Error('Could not parse AI response β€” try refreshing.'); }
445
+ }
446
+
447
+ // ─�� PROMPT ────────────────────────────────────────────────────
448
+ function buildPrompt(ticker,today){
449
+ return `Analyse ticker: ${ticker.sym} (${ticker.name}). Today: ${today}.
450
+
451
+ STEP 1 β€” Search the web for:
452
+ β€’ Current price and today's % change for ${ticker.sym}
453
+ β€’ Current implied volatility (IV) and options chain activity
454
+ β€’ Most recent news or catalyst (past 7 days) β€” note the SOURCE
455
+ β€’ Next earnings date for ${ticker.sym}
456
+ β€’ Current VIX level and US 3-month T-bill yield
457
+
458
+ STEP 2 β€” Respond with ONLY this exact JSON (no other text):
459
+
460
+ {
461
+ "ticker": "${ticker.sym}",
462
+ "company": "${ticker.name}",
463
+ "price": <number>,
464
+ "price_change_pct": <number e.g. 1.23>,
465
+ "price_trend": "<BULLISH|BEARISH|NEUTRAL>",
466
+ "vix": <number>,
467
+ "risk_free_rate": <number e.g. 4.8>,
468
+ "iv_estimate": <number e.g. 42.0>,
469
+ "iv_rank": <number 0-100>,
470
+ "iv_regime": "<HIGH_SELL_PREMIUM|LOW_BUY_OPTIONS|NEUTRAL>",
471
+ "hv_30d": <number>,
472
+ "rsi_estimate": <number>,
473
+ "sma20": <number>,
474
+ "sma50": <number>,
475
+ "earnings_date": "<YYYY-MM-DD or Unknown>",
476
+ "days_to_earnings": <number or null>,
477
+ "has_liquid_options": <true|false>,
478
+ "options_note": "<one line on liquidity>",
479
+ "news_headline": "<most important recent news headline in one sentence>",
480
+ "news_source": "<source name e.g. Reuters, Yahoo Finance, Bloomberg, SEC filing>",
481
+ "news_date": "<YYYY-MM-DD or approximate>",
482
+ "news_impact": "<BULLISH|BEARISH|NEUTRAL β€” how this news affects the options strategy>",
483
+ "data_quality": "<LIVE|ESTIMATED>",
484
+
485
+ "top_strategy": {
486
+ "name": "<Sell Put|Sell Covered Call|Buy Call|Buy Put|Buy Straddle|Buy Strangle|Iron Condor|Bull Call Spread|Bear Put Spread>",
487
+ "type_class": "<sell_put|sell_call|buy_call|buy_put|straddle|strangle|condor|bull_spread|bear_spread>",
488
+ "direction": "<Bullish|Bearish|Neutral|Non-Directional>",
489
+ "confidence": "<HIGH|MEDIUM|LOW>",
490
+ "strike": "<e.g. $415>",
491
+ "expiry": "<e.g. Apr 17 2025>",
492
+ "dte": "<e.g. 42 DTE>",
493
+ "entry_mid": "<e.g. $3.20>",
494
+ "max_profit": "<e.g. $320 per contract>",
495
+ "max_loss": "<e.g. $680 per contract>",
496
+ "breakeven": "<e.g. $411.80 or Up: $420 / Down: $400>",
497
+ "delta": "<e.g. -0.28>",
498
+ "gamma": "<e.g. 0.012>",
499
+ "theta": "<e.g. -$0.09/day>",
500
+ "vega": "<e.g. $0.18 per 1pt IV>",
501
+ "technical_rationale": "<2-3 sentences: the professional analysis using IV rank, trend, Greeks, VIX>",
502
+ "plain_english": "<3-4 sentences in simple language explaining what this trade is, why it makes sense right now, and what outcome you are expecting. Avoid jargon. Write as if explaining to a smart friend who does not trade options.>",
503
+ "risk_scenario": "<one specific event that immediately kills this trade>",
504
+ "pass_if": "<two specific conditions under which you skip this trade today>"
505
+ },
506
+
507
+ "alternative_strategy": {
508
+ "name": "<strategy name>",
509
+ "type_class": "<type class>",
510
+ "direction": "<direction>",
511
+ "strike": "<strike>",
512
+ "expiry": "<expiry>",
513
+ "entry_mid": "<mid price>",
514
+ "rationale": "<2 sentences: why this is the second best option>"
515
+ },
516
+
517
+ "strategy_scores": [
518
+ {"name":"Sell Put","score":<0-100>},
519
+ {"name":"Sell Call","score":<0-100>},
520
+ {"name":"Buy Call","score":<0-100>},
521
+ {"name":"Buy Put","score":<0-100>},
522
+ {"name":"Buy Straddle","score":<0-100>},
523
+ {"name":"Iron Condor","score":<0-100>},
524
+ {"name":"Bull Spread","score":<0-100>},
525
+ {"name":"Bear Spread","score":<0-100>}
526
+ ]
527
+ }
528
+
529
+ If ${ticker.sym} has no liquid options (very small cap / newly listed), set has_liquid_options:false and adjust top_strategy to an equity-level recommendation. Always include your news source.`;
530
+ }
531
+
532
+ // ── BUILD SUMMARY TABLE ───────────────────────────────────────
533
+ function buildSummary(){
534
+ const tbody=document.getElementById('summary-body');
535
+ if(!Object.keys(results).length){ tbody.innerHTML='<tr><td colspan="9" style="padding:16px;color:var(--t3);font-size:12px">No results yet.</td></tr>'; return; }
536
+ tbody.innerHTML='';
537
+ TICKERS.forEach(t=>{
538
+ const d=results[t.sym];
539
+ if(!d){
540
+ const tr=document.createElement('tr');
541
+ tr.innerHTML=`<td class="sticker">${t.sym}</td><td colspan="8" style="color:var(--t3);font-size:12px;font-style:italic">Failed to load</td>`;
542
+ tbody.appendChild(tr);
543
+ return;
544
+ }
545
+ const ts=d.top_strategy||{};
546
+ const tc=TYPE_MAP[ts.type_class]||'df';
547
+ const chgSign=d.price_change_pct>=0?'+':'';
548
+ const chgCls=d.price_change_pct>0?'up':d.price_change_pct<0?'dn':'fl';
549
+ const confCls=ts.confidence==='HIGH'?'conf-high':ts.confidence==='MEDIUM'?'conf-med':'conf-low';
550
+ const tr=document.createElement('tr');
551
+ tr.innerHTML=`
552
+ <td><span class="sticker">${t.sym}</span><br><span style="font-size:10px;color:var(--t3)">${t.name}</span></td>
553
+ <td><span class="sprice">$${fmt(d.price)}</span><span class="schg ${chgCls}">${chgSign}${fmt(d.price_change_pct)}%</span></td>
554
+ <td><span class="strategy-pill b-${tc}">${ts.name||'β€”'}</span></td>
555
+ <td><span class="mono">${ts.strike||'β€”'}</span></td>
556
+ <td><span class="mono" style="font-size:11px">${ts.expiry||'β€”'}<br><span style="color:var(--t3)">${ts.dte||''}</span></span></td>
557
+ <td><span class="mono">${ts.entry_mid||'β€”'}</span></td>
558
+ <td style="color:var(--green);font-weight:600;font-size:12px">${ts.max_profit||'β€”'}</td>
559
+ <td style="color:var(--red);font-weight:600;font-size:12px">${ts.max_loss||'β€”'}</td>
560
+ <td><span class="conf-badge ${confCls}">${ts.confidence||'β€”'}</span></td>`;
561
+ tbody.appendChild(tr);
562
+ });
563
+ }
564
+
565
+ // ── RENDER CARD ───────────────────────────────────────────────
566
+ function renderCard(ticker,d){
567
+ const card=document.getElementById('card-'+ticker.sym);
568
+ if(!card) return;
569
+
570
+ // Update VIX in header once
571
+ if(d.vix && document.getElementById('hdr-vix').style.display==='none'||!document.getElementById('hdr-vix').textContent){
572
+ const vixEl=document.getElementById('hdr-vix');
573
+ vixEl.textContent=`VIX ${fmt(d.vix)}`;
574
+ vixEl.style.display='block';
575
+ }
576
+
577
+ const ts=d.top_strategy||{};
578
+ const alt=d.alternative_strategy||{};
579
+ const tc=TYPE_MAP[ts.type_class]||'df';
580
+ const altc=TYPE_MAP[alt.type_class]||'df';
581
+ const chgSign=d.price_change_pct>=0?'+':'';
582
+ const chgCls=d.price_change_pct>0?'up':d.price_change_pct<0?'dn':'fl';
583
+ const ivFill=Math.min(100,d.iv_rank||0);
584
+ const ivColor=d.iv_rank>60?'var(--red)':d.iv_rank<35?'var(--green)':'var(--amber)';
585
+ const regClass=d.iv_regime==='HIGH_SELL_PREMIUM'?'rt-sell':d.iv_regime==='LOW_BUY_OPTIONS'?'rt-buy':'rt-neutral';
586
+ const regLabel=d.iv_regime==='HIGH_SELL_PREMIUM'?'Sell Premium ↑':d.iv_regime==='LOW_BUY_OPTIONS'?'Buy Options ↓':'Neutral IV';
587
+ const trendColor=d.price_trend==='BULLISH'?'var(--green)':d.price_trend==='BEARISH'?'var(--red)':'var(--amber)';
588
+ const dq=d.data_quality||'';
589
+ const dqPill=dq.includes('LIVE')?
590
+ `<span style="font-size:10px;padding:2px 7px;border-radius:4px;background:var(--green-m);color:var(--green);font-weight:700">● LIVE</span>`:
591
+ `<span style="font-size:10px;padding:2px 7px;border-radius:4px;background:var(--amber-m);color:var(--amber);font-weight:700">◐ EST</span>`;
592
+ const confCls=ts.confidence==='HIGH'?'conf-high':ts.confidence==='MEDIUM'?'conf-med':'conf-low';
593
+ const scores=(d.strategy_scores||[]).sort((a,b)=>b.score-a.score);
594
+ const newsImpactColor=d.news_impact==='BULLISH'?'var(--green)':d.news_impact==='BEARISH'?'var(--red)':'var(--t3)';
595
+
596
+ card.innerHTML=`
597
+ <!-- Header -->
598
+ <div class="tcard-hdr">
599
+ <div>
600
+ <div class="tcard-ticker">${d.ticker} ${dqPill}</div>
601
+ <div class="tcard-name">${d.company}</div>
602
+ </div>
603
+ <div class="tcard-price">
604
+ <div class="price-big">$${fmt(d.price)}</div>
605
+ <div class="price-chg ${chgCls}">${chgSign}${fmt(d.price_change_pct)}%</div>
606
+ </div>
607
+ </div>
608
+
609
+ <!-- Stats -->
610
+ <div class="stats-band">
611
+ <div class="sc">
612
+ <div class="sc-l">Trend</div>
613
+ <div class="sc-v" style="color:${trendColor}">${d.price_trend||'β€”'}</div>
614
+ <div class="sc-s">RSI ${fmt(d.rsi_estimate,0)}</div>
615
+ </div>
616
+ <div class="sc">
617
+ <div class="sc-l">ATM IV</div>
618
+ <div class="sc-v">${fmt(d.iv_estimate)}%</div>
619
+ <div class="sc-s">HV30 ${fmt(d.hv_30d)}%</div>
620
+ </div>
621
+ <div class="sc">
622
+ <div class="sc-l">Earnings</div>
623
+ <div class="sc-v" style="font-size:12px">${d.earnings_date&&d.earnings_date!=='Unknown'?d.earnings_date:'β€”'}</div>
624
+ <div class="sc-s">${d.days_to_earnings?d.days_to_earnings+'d away':''}</div>
625
+ </div>
626
+ <div class="sc">
627
+ <div class="sc-l">Options</div>
628
+ <div class="sc-v" style="font-size:12px;color:${d.has_liquid_options?'var(--green)':'var(--red)'}">
629
+ ${d.has_liquid_options?'βœ“ Liquid':'βœ— Thin'}
630
+ </div>
631
+ <div class="sc-s" style="font-size:9px">${(d.options_note||'').substring(0,28)}</div>
632
+ </div>
633
+ </div>
634
+
635
+ <!-- IV Rank -->
636
+ <div class="iv-bar-wrap">
637
+ <div class="iv-bar-row">
638
+ <span class="iv-bar-lbl">IV Rank: <strong>${fmt(d.iv_rank,0)}</strong> / 100</span>
639
+ <span class="iv-regime-tag ${regClass}">${regLabel}</span>
640
+ </div>
641
+ <div class="iv-track"><div class="iv-fill" style="width:${ivFill}%;background:${ivColor}"></div></div>
642
+ </div>
643
+
644
+ <!-- News -->
645
+ ${d.news_headline?`<div class="news-row">
646
+ <span class="news-tag" style="color:${newsImpactColor}">News</span>
647
+ <div>
648
+ <div class="news-text">${esc(d.news_headline)}</div>
649
+ <div class="news-src">πŸ“° Source: <strong>${esc(d.news_source||'Unknown')}</strong>${d.news_date?' Β· '+d.news_date:''} Β· Impact: <span style="color:${newsImpactColor};font-weight:600">${d.news_impact||'β€”'}</span></div>
650
+ </div>
651
+ </div>`:''}
652
+
653
+ <!-- Recommendation Banner -->
654
+ <div class="rec-block">
655
+ <div class="rec-block-title">⭐ Top Recommendation</div>
656
+
657
+ <div class="rec-banner s-${tc}">
658
+ <div class="rec-top-row">
659
+ <div>
660
+ <div class="rec-strat-name">${ts.name||'β€”'}</div>
661
+ <div class="rec-dir">${ts.direction||''}</div>
662
+ </div>
663
+ <div class="rec-conf">
664
+ <span class="conf-badge ${confCls}">${ts.confidence||'β€”'}</span>
665
+ <div style="font-size:9px;color:var(--t3);margin-top:4px;text-align:right">confidence</div>
666
+ </div>
667
+ </div>
668
+ <div class="rec-strike-row">
669
+ <div class="rec-chip">
670
+ <span class="rec-chip-l">Strike</span>
671
+ <span class="rec-chip-v">${ts.strike||'β€”'}</span>
672
+ </div>
673
+ <div class="rec-chip">
674
+ <span class="rec-chip-l">Expiry</span>
675
+ <span class="rec-chip-v" style="font-size:11px">${ts.expiry||'β€”'}</span>
676
+ </div>
677
+ <div class="rec-chip">
678
+ <span class="rec-chip-l">DTE</span>
679
+ <span class="rec-chip-v">${ts.dte||'β€”'}</span>
680
+ </div>
681
+ <div class="rec-chip">
682
+ <span class="rec-chip-l">Entry Mid</span>
683
+ <span class="rec-chip-v">${ts.entry_mid||'β€”'}</span>
684
+ </div>
685
+ </div>
686
+ </div>
687
+
688
+ <!-- P&L -->
689
+ <div class="pnl-row">
690
+ <div class="pnl-box"><div class="pnl-l">Max Profit</div><div class="pnl-v" style="color:var(--green)">${ts.max_profit||'β€”'}</div></div>
691
+ <div class="pnl-box"><div class="pnl-l">Max Loss</div><div class="pnl-v" style="color:var(--red)">${ts.max_loss||'β€”'}</div></div>
692
+ <div class="pnl-box"><div class="pnl-l">Breakeven</div><div class="pnl-v" style="font-size:11px">${ts.breakeven||'β€”'}</div></div>
693
+ </div>
694
+
695
+ <!-- Greeks -->
696
+ <div class="greeks-row">
697
+ <div class="greek-box"><div class="greek-sym">Ξ”</div><div class="greek-val">${ts.delta||'β€”'}</div><div class="greek-lbl">Delta</div></div>
698
+ <div class="greek-box"><div class="greek-sym">Ξ“</div><div class="greek-val">${ts.gamma||'β€”'}</div><div class="greek-lbl">Gamma</div></div>
699
+ <div class="greek-box"><div class="greek-sym">ΞΈ</div><div class="greek-val">${ts.theta||'β€”'}</div><div class="greek-lbl">Theta/day</div></div>
700
+ <div class="greek-box"><div class="greek-sym">Ξ½</div><div class="greek-val">${ts.vega||'β€”'}</div><div class="greek-lbl">Vega/pt</div></div>
701
+ </div>
702
+
703
+ <!-- Professional rationale -->
704
+ ${ts.technical_rationale?`<div style="font-size:12px;line-height:1.7;color:var(--t2);margin-bottom:0">${esc(ts.technical_rationale)}</div>`:''}
705
+ </div>
706
+
707
+ <!-- Plain English -->
708
+ ${ts.plain_english?`<div class="plain-block">
709
+ <div class="plain-title">πŸ’¬ In Plain English</div>
710
+ <div class="plain-text">${esc(ts.plain_english)}</div>
711
+ </div>`:''}
712
+
713
+ <!-- Risk -->
714
+ ${ts.risk_scenario?`<div class="risk-block">
715
+ <div class="risk-tag">⚠ Key Risk</div>
716
+ <div class="risk-text">${esc(ts.risk_scenario)}</div>
717
+ </div>`:''}
718
+
719
+ <!-- Pass if -->
720
+ ${ts.pass_if?`<div class="pass-block">
721
+ <div class="pass-tag">🚫 Skip this trade if…</div>
722
+ <div class="pass-text">${esc(ts.pass_if)}</div>
723
+ </div>`:''}
724
+
725
+ <!-- Alternative -->
726
+ ${alt.name?`<div class="alt-block">
727
+ <div class="alt-tag">πŸ”€ Alternative Trade</div>
728
+ <div class="alt-inner">
729
+ <span class="strategy-pill b-${altc}" style="font-size:10px;flex-shrink:0">${alt.name}</span>
730
+ <div class="alt-text"><strong>${alt.strike||''} ${alt.expiry||''}</strong> Β· Mid ${alt.entry_mid||'β€”'}<br>${esc(alt.rationale||'')}</div>
731
+ </div>
732
+ </div>`:''}
733
+
734
+ <!-- Strategy Scores -->
735
+ <div class="scores-block">
736
+ <div class="scores-title">All Strategy Scores</div>
737
+ ${scores.map(s=>{
738
+ const sc=s.score||0;
739
+ const col=sc>=70?'var(--green)':sc>=50?'var(--blue)':sc>=35?'var(--amber)':'var(--border2)';
740
+ return `<div class="score-row">
741
+ <span class="score-nm">${s.name}</span>
742
+ <div class="score-tr"><div class="score-fi" style="width:${sc}%;background:${col}"></div></div>
743
+ <span class="score-n" style="color:${col}">${sc}</span>
744
+ </div>`;
745
+ }).join('')}
746
+ </div>`;
747
+ }
748
+
749
+ // ── RENDER ERROR ──────────────────────────────────────────────
750
+ function renderError(ticker,msg){
751
+ const card=document.getElementById('card-'+ticker.sym);
752
+ if(!card) return;
753
+ card.innerHTML=`
754
+ <div class="tcard-hdr"><div><div class="tcard-ticker">${ticker.sym}</div><div class="tcard-name">${ticker.name}</div></div></div>
755
+ <div class="card-err">
756
+ <div class="card-err-ico">⚠️</div>
757
+ <div class="card-err-msg">${esc(msg)}</div>
758
+ <button class="btn-retry" onclick="retryOne('${ticker.sym}')">↩ Retry ${ticker.sym}</button>
759
+ </div>`;
760
+ }
761
+
762
+ async function retryOne(sym){
763
+ const t=TICKERS.find(x=>x.sym===sym);
764
+ if(!t) return;
765
+ document.getElementById('card-'+sym).innerHTML=loadingHTML(t);
766
+ await fetchAndRender(t);
767
+ buildSummary();
768
+ }
769
+
770
+ // ── HELPERS ───────────────────────────────────────────────────
771
+ function fmt(n,dec=2){
772
+ if(n===null||n===undefined||n==='') return 'β€”';
773
+ const x=parseFloat(n);
774
+ return isNaN(x)?String(n):x.toFixed(dec);
775
+ }
776
+ function esc(s){
777
+ return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
778
+ }
779
+ </script>
780
+ </body>
781
+ </html>