-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.html
More file actions
944 lines (913 loc) · 68.9 KB
/
Copy pathindex.html
File metadata and controls
944 lines (913 loc) · 68.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GammaLedger – Analyze, Track & Visualize Your Options Portfolio Securely</title>
<!-- Security Headers (Content-Security-Policy is injected at build time — see injectCsp in vite.config.ts) -->
<meta http-equiv="X-Content-Type-Options" content="nosniff">
<meta http-equiv="X-XSS-Protection" content="1; mode=block">
<meta name="referrer" content="strict-origin-when-cross-origin">
<meta name="description" content="Powerful analytics for smarter options trading — track performance, analyze strategies, and optimize every trade with professional precision.">
<meta name="keywords" content="GammaLedger, options analytics, options trading journal, portfolio tracker, derivatives analytics, options strategy management">
<meta name="author" content="GammaLedger Contributors">
<meta name="copyright" content="GammaLedger">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://gammaledger.com/app/">
<!-- Open Graph -->
<meta property="og:type" content="website">
<meta property="og:site_name" content="GammaLedger">
<meta property="og:title" content="GammaLedger – Analyze, Track & Visualize Your Options Portfolio Securely">
<meta property="og:description" content="Powerful analytics for smarter options trading — track performance, analyze strategies, and optimize every trade with professional precision.">
<meta property="og:url" content="https://gammaledger.com/app/">
<meta property="og:image" content="https://raw.githubusercontent.com/r-brown/GammaLedger/refs/heads/main/assets/images/gammaledger-stage-01.jpg">
<meta property="og:image:alt" content="GammaLedger options analytics dashboard">
<meta property="og:locale" content="en_US">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="GammaLedger – Analyze, Track & Visualize Your Options Portfolio Securely">
<meta name="twitter:description" content="Powerful analytics for smarter options trading — track performance, analyze strategies, and optimize every trade with professional precision.">
<meta name="twitter:image" content="https://raw.githubusercontent.com/r-brown/GammaLedger/refs/heads/main/assets/images/gammaledger-stage-01.jpg">
<meta name="twitter:image:alt" content="GammaLedger options analytics dashboard">
<!-- Dublin Core -->
<meta name="DC.Title" content="GammaLedger – Analyze, Track & Visualize Your Options Portfolio Securely">
<meta name="DC.Description" content="Powerful analytics for smarter options trading — track performance, analyze strategies, and optimize every trade with professional precision.">
<meta name="DC.Subject" content="GammaLedger, options analytics, options trading journal, portfolio tracker, derivatives analytics, options strategy management">
<meta name="DC.Creator" content="GammaLedger Contributors">
<meta name="DC.Publisher" content="GammaLedger">
<meta name="DC.Type" content="Text">
<meta name="DC.Format" content="text/html">
<meta name="DC.Language" content="en">
<meta name="DC.Date" content="2025-10-23">
<link rel="stylesheet" href="/src/styles/app.css">
<link rel="icon" type="image/png" href="%BASE_URL%gammaledger-logo-16x16.png">
<link rel="icon" type="image/png" sizes="16x16" href="%BASE_URL%gammaledger-logo-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="%BASE_URL%gammaledger-logo-32x32.png">
<link rel="icon" type="image/png" sizes="64x64" href="%BASE_URL%gammaledger-logo-64x64.png">
</head>
<body>
<!-- Announcement banner — rendered by src/ui/announcement.ts -->
<div id="announcement-banner"></div>
<dialog id="disclaimer-banner" class="disclaimer-banner" aria-labelledby="disclaimer-title">
<div class="disclaimer-banner__panel">
<h2 id="disclaimer-title" class="disclaimer-banner__title">Disclaimer</h2>
<div class="disclaimer-banner__body" tabindex="0">
<p>The information and tools provided on this website are for educational and analytical/learning purposes only,
intended to help users understand options trading concepts.
Nothing on this site constitutes financial, investment, trading, or legal advice.</p>
<p>Users should not rely solely on the data, analytics, or calculations presented here for making investment decisions.
Options trading involves significant risk and is not suitable for all investors.
You may lose part or all of your invested capital, or potentially more than your invested capital
(for example, when selling naked calls or holding spreads with pin risk).</p>
<p>All data, analytics, and visualizations are provided "as is", without any warranty of accuracy,
completeness, or reliability. The website's creators and contributors assume no responsibility for
any losses or damages arising from the use or interpretation of the provided information.</p>
<p>This website does not offer or execute trades, provide broker services, or endorse any specific
financial products or platforms. Users remain fully responsible for verifying information and
complying with applicable laws and regulations in their jurisdiction.</p>
<p>If the website allows local or cloud-based data storage, users are solely responsible for managing
and protecting their own data. No guarantee is given for continuous access, data integrity, or
long-term storage.</p>
<p>By using this website, you agree to these terms and acknowledge that you understand the inherent
risks associated with financial and options trading, subject to applicable laws.</p>
</div>
<div class="disclaimer-banner__actions">
<button type="button" class="btn btn--primary disclaimer-banner__agree"
data-action="disclaimer-agree">Agree</button>
</div>
</div>
</dialog>
<dialog id="ai-coach-consent" class="ai-consent-modal" aria-labelledby="ai-consent-title" aria-describedby="ai-consent-description">
<div class="ai-consent-modal__panel" role="document">
<button type="button" class="ai-consent-modal__close" data-action="ai-consent-dismiss"
aria-label="Close AI Coach consent dialog">×</button>
<div class="ai-consent-modal__header">
<h2 id="ai-consent-title" class="ai-consent-modal__title">AI Coach Data Sharing</h2>
<p id="ai-consent-description" class="ai-consent-modal__lead">By using this feature, you agree that your
portfolio data — including trade details and summary information — will be securely sent to the AI Agent
for analysis and response generation.</p>
</div>
<div class="ai-consent-modal__body">
<ul class="ai-consent-modal__list">
<li>The AI Coach uses your shared data only to craft responses for this session.</li>
<li>Your API key and portfolio remain saved locally; requests are transmitted securely to your configured
AI endpoint.</li>
<li>You can revoke access any time by clearing the AI key in Settings.</li>
</ul>
</div>
<div class="ai-consent-modal__actions">
<button type="button" class="btn btn--secondary" data-action="ai-consent-dismiss">Cancel</button>
<button type="button" class="btn btn--primary" data-action="ai-consent-agree">I Understand & Agree</button>
</div>
</div>
</dialog>
<div class="app-container">
<!-- Sidebar Navigation -->
<aside class="sidebar">
<div class="sidebar-header">
<div class="sidebar-brand">
<img class="sidebar-brand__logo" src="%BASE_URL%gammaledger-logo-32x32.png" alt="GammaLedger logo">
<h2 class="sidebar-brand__name">GammaLedger</h2>
</div>
<span class="sidebar-brand__version" id="app-version"></span>
</div>
<nav class="sidebar-nav">
<button class="nav-item active" data-view="dashboard">
<span class="nav-icon">📊</span>
<span class="nav-label">Dashboard</span>
</button>
<button class="nav-item" data-view="trades-list">
<span class="nav-icon">📋</span>
<span class="nav-label">All Trades</span>
</button>
<!-- Disabled for now - will re-evaluate adding "Credit Playbook" in the future after we have stabilized core tracking and analytics features
<button class="nav-item" data-view="credit-playbook">
<span class="nav-icon">💳</span>
<span class="nav-label">Credit Playbook</span>
</button>
-->
<button class="nav-item" data-view="add-trade">
<span class="nav-icon">➕</span>
<span class="nav-label">Add Trade</span>
</button>
<button class="nav-item" data-view="import">
<span class="nav-icon">⬆️</span>
<span class="nav-label">Import</span>
</button>
<button class="nav-item" data-view="settings">
<span class="nav-icon">⚙️</span>
<span class="nav-label">Settings</span>
</button>
</nav>
<div class="sidebar-toggle-container">
<button type="button" id="sidebar-toggle" class="sidebar-toggle" aria-expanded="true" aria-label="Collapse navigation"></button>
</div>
<div class="sidebar-footer">
<a class="sidebar-link" href="https://gammaledger.com" target="_blank" rel="noopener noreferrer">
<span class="nav-icon nav-icon--logo">
<img src="%BASE_URL%gammaledger-logo-32x32.png" alt="GammaLedger logo">
</span>
<span class="nav-label">GammaLedger.com</span>
</a>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<!-- Header -->
<header class="app-header">
<div class="header-left">
<h1 id="page-title">Options Trading Dashboard</h1>
<div id="market-status" class="market-status market-status--loading">
<span class="market-status__dot"></span>
<span id="market-status-label" class="market-status__label">Checking market…</span>
<span id="market-status-countdown" class="market-status__countdown"></span>
</div>
</div>
<div class="header-right">
<div class="file-management">
<div class="share-action">
<button class="icon-button" id="share-portfolio-card"
aria-label="Share portfolio snapshot"
title="Share portfolio snapshot">
<span aria-hidden="true">⌯⌲</span>
</button>
<span class="share-action__label">Share your portfolio snapshot</span>
</div>
<div class="file-management__sep"></div>
<button class="btn btn--sm btn--secondary" id="new-database-btn">New Database</button>
<button class="btn btn--sm btn--secondary" id="load-database-btn">Load Database</button>
<button class="btn btn--sm btn--primary" id="save-database-btn">Save Database</button>
<div id="loading-indicator" class="loading-indicator hidden">Saving…</div>
</div>
<div class="file-info">
<span id="current-file-name" class="file-name">Unsaved Database</span>
<span id="unsaved-indicator" class="unsaved-indicator hidden">●</span>
</div>
</div>
</header>
<!-- Sample-data first-run banner — toggled by src/ui/announcement.ts -->
<div id="sample-data-banner" class="sample-data-banner hidden" role="status">
<span class="sample-data-banner__message">You're viewing <strong>sample data</strong>. Import your own trades or start a fresh database — your data never leaves this browser.</span>
<div class="sample-data-banner__actions">
<button type="button" class="btn btn--sm btn--primary" id="sample-banner-import">Import your trades</button>
<button type="button" class="btn btn--sm btn--secondary" id="sample-banner-fresh">Start fresh</button>
</div>
</div>
<!-- Browser Compatibility Notice -->
<div id="compatibility-notice" class="compatibility-notice hidden">
<div class="notice-content">
<h4>⚠️ Limited File System Support</h4>
<p>Your browser doesn't fully support the File System Access API. You can still export/import data
using download/upload methods.</p>
<button class="btn btn--sm btn--secondary" id="dismiss-fs-notice"
aria-label="Dismiss notice">Dismiss</button>
</div>
</div>
<!-- Enhanced Dashboard View with Integrated Analytics -->
<div class="view dashboard-view active">
<section id="grouped-metrics" class="metric-grid" aria-label="Portfolio metrics"></section>
<section class="card dashboard-performance-trend">
<div class="card-header">
<h3>Performance Trend</h3>
<div class="chart-range" id="cumulative-pl-controls" role="group" aria-label="Performance trend time range">
<button type="button" class="chart-range__button" data-range="7D">7D</button>
<button type="button" class="chart-range__button" data-range="MTD">MTD</button>
<button type="button" class="chart-range__button" data-range="1M">1M</button>
<button type="button" class="chart-range__button" data-range="3M">3M</button>
<button type="button" class="chart-range__button" data-range="YTD">YTD</button>
<button type="button" class="chart-range__button" data-range="1Y">1Y</button>
<button type="button" class="chart-range__button" data-range="ALL">All</button>
</div>
</div>
<div class="chart-responsive-wrapper chart-responsive-wrapper--tall">
<div id="performanceTrendChart" class="echarts-chart" role="img" aria-label="Monthly P&L bars with cumulative growth line"></div>
</div>
</section>
<!-- Positions & trades (tabbed — Wheel/PMCC tracker promoted to a peer tab) -->
<section class="card dashboard-positions gl-tabs" data-tab-group>
<div class="gl-tabs__list" role="tablist" aria-label="Positions and trades tables">
<button type="button" class="gl-tabs__tab is-active" role="tab" aria-selected="true" data-tab-target="tables-active">Active Positions</button>
<button type="button" class="gl-tabs__tab" role="tab" aria-selected="false" data-tab-target="tables-wheel">Wheel / PMCC Tracker</button>
<button type="button" class="gl-tabs__tab" role="tab" aria-selected="false" data-tab-target="tables-recent">Recent Closed</button>
</div>
<div class="gl-tabs__panel is-active" role="tabpanel" data-tab-panel="tables-active">
<div class="active-positions">
<div class="table-container dashboard-grid-container">
<div id="active-positions-table" class="dashboard-ag-grid ag-theme-quartz" aria-label="Active positions"></div>
</div>
</div>
</div>
<div class="gl-tabs__panel" role="tabpanel" data-tab-panel="tables-wheel" hidden>
<!-- Assigned Positions / Wheel Strategy Tracking -->
<div class="assigned-positions">
<p class="section-help-text">Positions from assigned Cash-Secured Puts / Wheel or PMCC strategies. "Premium Collected" is cash-basis (counts credits when sold); "Premium Earned" is realized-basis (counts credits when the contract terminates) and matches the dashboard's Wheel premium row.</p>
<div class="chart-range" id="assigned-positions-status-filter" role="group" aria-label="Position status filter">
<button type="button" class="chart-range__button is-active" data-status="open">Open</button>
<button type="button" class="chart-range__button" data-status="closed">Closed</button>
</div>
<div class="table-container dashboard-grid-container">
<div id="assigned-positions-table" class="dashboard-ag-grid dashboard-ag-grid--assigned ag-theme-quartz" aria-label="Wheel and PMCC tracker"></div>
</div>
</div>
</div>
<div class="gl-tabs__panel" role="tabpanel" data-tab-panel="tables-recent" hidden>
<div class="recent-trades">
<div class="table-container dashboard-grid-container">
<div id="recent-trades-table" class="dashboard-ag-grid ag-theme-quartz" aria-label="Recent closed trades"></div>
</div>
</div>
</div>
</section>
<!-- Performance Gauges -->
<!--
<div class="advanced-analytics-gauges">
<div class="chart-container gauge-card">
<h3>Sharpe Ratio</h3>
<div class="chart-responsive-wrapper chart-responsive-wrapper--compact">
<div id="sharpeGaugeChart" class="echarts-chart" role="img" aria-label="Sharpe ratio gauge"></div>
</div>
<p class="chart-metric" id="sharpeGaugeValue">—</p>
<p class="chart-subtext">Risk-adjusted return</p>
</div>
<div class="chart-container gauge-card">
<h3>Sortino Ratio</h3>
<div class="chart-responsive-wrapper chart-responsive-wrapper--compact">
<div id="sortinoGaugeChart" class="echarts-chart" role="img" aria-label="Sortino ratio gauge"></div>
</div>
<p class="chart-metric" id="sortinoGaugeValue">—</p>
<p class="chart-subtext">Focus on downside risk</p>
</div>
</div>
-->
<!-- Analytics (tabbed — one chart visible at a time) -->
<section class="card dashboard-analytics gl-tabs" data-tab-group>
<div class="gl-tabs__list" role="tablist" aria-label="Analytics charts">
<button type="button" class="gl-tabs__tab is-active" role="tab" aria-selected="true" data-tab-target="analytics-strategy">Strategy</button>
<button type="button" class="gl-tabs__tab" role="tab" aria-selected="false" data-tab-target="analytics-winrate">Win rate</button>
<button type="button" class="gl-tabs__tab" role="tab" aria-selected="false" data-tab-target="analytics-fees">Fees</button>
<button type="button" class="gl-tabs__tab" role="tab" aria-selected="false" data-tab-target="analytics-heatmap">Heatmap</button>
<button type="button" class="gl-tabs__tab" role="tab" aria-selected="false" data-tab-target="analytics-time">Time in trade</button>
<button type="button" class="gl-tabs__tab" role="tab" aria-selected="false" data-tab-target="analytics-montecarlo">Monte Carlo</button>
</div>
<div class="gl-tabs__panel is-active" role="tabpanel" data-tab-panel="analytics-strategy">
<div class="chart-container">
<h3>Strategy Performance</h3>
<div class="chart-responsive-wrapper chart-responsive-wrapper--medium">
<div id="strategyChart" class="echarts-chart" role="img" aria-label="Strategy performance chart"></div>
</div>
</div>
</div>
<div class="gl-tabs__panel" role="tabpanel" data-tab-panel="analytics-winrate" hidden>
<div class="chart-container">
<h3>Win Rate by Strategy</h3>
<div class="chart-responsive-wrapper chart-responsive-wrapper--tall">
<div id="winRateChart" class="echarts-chart" role="img" aria-label="Win rate by strategy chart"></div>
</div>
</div>
</div>
<div class="gl-tabs__panel" role="tabpanel" data-tab-panel="analytics-fees" hidden>
<div class="chart-container">
<h3>Commission Impact</h3>
<div class="chart-responsive-wrapper chart-responsive-wrapper--short">
<div id="commissionImpactChart" class="echarts-chart" role="img" aria-label="Commission impact chart"></div>
</div>
<p class="chart-subtext" id="commissionImpactSummary">No closed trades yet.</p>
</div>
</div>
<div class="gl-tabs__panel" role="tabpanel" data-tab-panel="analytics-heatmap" hidden>
<div class="chart-container heatmap-container">
<h3>Ticker Performance Heatmap</h3>
<div id="tickerHeatmap" class="echarts-chart heatmap-chart" role="img" aria-label="Ticker performance heatmap" aria-live="polite"></div>
</div>
</div>
<div class="gl-tabs__panel" role="tabpanel" data-tab-panel="analytics-time" hidden>
<div class="chart-container">
<h3>Time in Trade (Average Days)</h3>
<div class="chart-responsive-wrapper chart-responsive-wrapper--short">
<div id="timeInTradeChart" class="echarts-chart" role="img" aria-label="Average time in trade chart"></div>
</div>
</div>
</div>
<div class="gl-tabs__panel" role="tabpanel" data-tab-panel="analytics-montecarlo" hidden>
<div class="chart-container">
<h3>Monte Carlo Projection (60 Days)</h3>
<div class="chart-responsive-wrapper chart-responsive-wrapper--medium">
<div id="monteCarloChart" class="echarts-chart" role="img" aria-label="Monte Carlo projection chart"></div>
</div>
<p class="chart-subtext" id="monteCarloSummary">Need more closed trades to run projections.</p>
</div>
</div>
</section>
</div>
<!-- Add Trade View -->
<div class="view add-trade-view">
<form id="add-trade-form" class="trade-form">
<div class="form-sections">
<!-- Basic Trade Info -->
<section class="form-section">
<h3>Basic Trade Information</h3>
<p class="form-help-text">Opened, expiration, and closed dates are automatically derived from leg activity.</p>
<div class="form-row">
<div class="form-group">
<label class="form-label" for="ticker">Ticker Symbol</label>
<input type="text" id="ticker" name="ticker" class="form-control" required>
<div class="ticker-preview" id="ticker-preview"></div>
</div>
<div class="form-group">
<label class="form-label" for="underlyingType">Underlying Type</label>
<select id="underlyingType" name="underlyingType" class="form-control">
<option value="Stock" selected>Stock</option>
<option value="ETF">ETF</option>
<option value="Index">Index</option>
<option value="Future">Future</option>
</select>
<p class="form-help-text">Choose the asset category so GammaLedger can apply the right contract multiplier.</p>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label" for="strategy">Strategy</label>
<input type="search" id="strategy-search" class="form-control strategy-search" placeholder="Type to filter strategies…" aria-label="Filter strategies" autocomplete="off">
<select id="strategy" name="strategy" class="form-control" required>
<option value="">Select Strategy</option>
<optgroup label="⭐ Favorites">
<option value="Cash-Secured Put">⭐ Cash-Secured Put</option>
<option value="Covered Call">⭐ Covered Call</option>
<option value="Poor Man's Covered Call">⭐ Poor Man's Covered Call</option>
<option value="Wheel">⭐ Wheel</option>
</optgroup>
<optgroup label="Income & covered">
<option value="Collar">Collar</option>
<option value="Covered Put">Covered Put</option>
<option value="Covered Short Straddle">Covered Short Straddle</option>
<option value="Covered Short Strangle">Covered Short Strangle</option>
<option value="Jade Lizard">Jade Lizard</option>
<option value="Protective Put">Protective Put</option>
<option value="Reverse Jade Lizard">Reverse Jade Lizard</option>
<option value="Short Call">Short Call</option>
<option value="Short Put">Short Put</option>
</optgroup>
<optgroup label="Vertical spreads & ladders">
<option value="Bear Call Ladder">Bear Call Ladder</option>
<option value="Bear Call Spread">Bear Call Spread</option>
<option value="Bear Put Ladder">Bear Put Ladder</option>
<option value="Bear Put Spread">Bear Put Spread</option>
<option value="Box Spread">Box Spread</option>
<option value="Bull Call Ladder">Bull Call Ladder</option>
<option value="Bull Call Spread">Bull Call Spread</option>
<option value="Bull Put Ladder">Bull Put Ladder</option>
<option value="Bull Put Spread">Bull Put Spread</option>
</optgroup>
<optgroup label="Calendars & diagonals">
<option value="Calendar Call Spread">Calendar Call Spread</option>
<option value="Calendar Put Spread">Calendar Put Spread</option>
<option value="Calendar Straddle">Calendar Straddle</option>
<option value="Calendar Strangle">Calendar Strangle</option>
<option value="Diagonal Call Spread">Diagonal Call Spread</option>
<option value="Diagonal Put Spread">Diagonal Put Spread</option>
<option value="Double Diagonal">Double Diagonal</option>
</optgroup>
<optgroup label="Condors, butterflies & wings">
<option value="Call Broken Wing">Call Broken Wing</option>
<option value="Inverse Call Broken Wing">Inverse Call Broken Wing</option>
<option value="Inverse Iron Butterfly">Inverse Iron Butterfly</option>
<option value="Inverse Iron Condor">Inverse Iron Condor</option>
<option value="Inverse Put Broken Wing">Inverse Put Broken Wing</option>
<option value="Iron Albatross">Iron Albatross</option>
<option value="Iron Butterfly">Iron Butterfly</option>
<option value="Iron Condor">Iron Condor</option>
<option value="Long Call Butterfly">Long Call Butterfly</option>
<option value="Long Call Condor">Long Call Condor</option>
<option value="Long Put Butterfly">Long Put Butterfly</option>
<option value="Long Put Condor">Long Put Condor</option>
<option value="Put Broken Wing">Put Broken Wing</option>
<option value="Short Call Butterfly">Short Call Butterfly</option>
<option value="Short Call Condor">Short Call Condor</option>
<option value="Short Put Butterfly">Short Put Butterfly</option>
<option value="Short Put Condor">Short Put Condor</option>
</optgroup>
<optgroup label="Volatility (straddles & strangles)">
<option value="Guts">Guts</option>
<option value="Long Straddle">Long Straddle</option>
<option value="Long Strangle">Long Strangle</option>
<option value="Short Guts">Short Guts</option>
<option value="Short Straddle">Short Straddle</option>
<option value="Short Strangle">Short Strangle</option>
<option value="Strap">Strap</option>
<option value="Strip">Strip</option>
</optgroup>
<optgroup label="Advanced & synthetic">
<option value="Call Ratio Backspread">Call Ratio Backspread</option>
<option value="Call Ratio Spread">Call Ratio Spread</option>
<option value="Long Call">Long Call</option>
<option value="Long Put">Long Put</option>
<option value="Put Ratio Backspread">Put Ratio Backspread</option>
<option value="Put Ratio Spread">Put Ratio Spread</option>
<option value="Synthetic Long Stock">Synthetic Long Stock</option>
<option value="Synthetic Put">Synthetic Put</option>
<option value="Synthetic Short Stock">Synthetic Short Stock</option>
</optgroup>
</select>
<p class="form-help-text">Picking a ⭐ strategy pre-fills its opening legs.</p>
</div>
<div class="form-group">
<label class="form-label" for="tradeStatus">Trade Status</label>
<select id="tradeStatus" name="tradeStatus" class="form-control">
<option value="">Auto (based on legs)</option>
<option value="Open">Open</option>
<option value="Closed">Closed</option>
<option value="Rolling">Rolled</option>
<option value="Expired">Expired</option>
<option value="Assigned">Assigned</option>
</select>
<p class="form-help-text">Leave on Auto for lifecycle detection or pick a status to override it.</p>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label" for="exitReason">Exit Reason (if closed)</label>
<select id="exitReason" name="exitReason" class="form-control">
<option value="">Select reason</option>
<option value="Profit target reached">Profit target reached</option>
<option value="Early profit take">Early profit take</option>
<option value="Stop loss triggered">Stop loss triggered</option>
<option value="Expired">Expired</option>
<option value="Assignment">Assignment</option>
<option value="Cash Settlement">Cash Settlement</option>
<option value="Rolling position">Rolling position</option>
<option value="Time decay">Time decay</option>
<option value="Market change">Market change</option>
<option value="Volatility crush">Volatility crush</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label" for="notes">Notes</label>
<textarea id="notes" name="notes" class="form-control" rows="4"
placeholder="Capture market context, execution details, and risk management plans."></textarea>
</div>
</div>
</section>
<!-- Trade Legs -->
<section class="form-section">
<div class="form-section__header">
<h3>Trade Legs</h3>
<p class="form-help-text">Add one or more legs to fully describe this trade. Each leg represents a single execution (including rolls).</p>
</div>
<div id="trade-legs-container" class="trade-legs-container" aria-live="polite"></div>
<div class="form-row trade-legs-actions">
<button type="button" class="btn btn--secondary" id="add-leg-button">Add Leg</button>
</div>
</section>
</div>
<div class="form-actions">
<button type="button" class="btn btn--secondary" id="cancel-trade">Cancel</button>
<button type="submit" class="btn btn--primary">Save Trade</button>
</div>
</form>
</div>
<!-- Trades List View -->
<div class="view trades-list-view">
<div class="trades-header">
<div class="trades-header__controls">
<button type="button" class="btn btn--sm btn--secondary trades-filters-toggle" id="toggle-filters" aria-expanded="true" aria-controls="trades-filters-panel">
Hide Filters
</button>
<div class="trades-actions">
<button class="btn btn--secondary" id="trades-merge-toggle" aria-controls="trades-merge-panel" aria-expanded="false">Merge Trades</button>
<button class="btn btn--secondary" id="export-csv">Export CSV</button>
</div>
</div>
<div class="trades-filters is-open" id="trades-filters-panel">
<!-- The multi-selects stay as the canonical filter state (hidden);
the chip groups below are the visible UI. -->
<select id="filter-strategy" class="sr-only" multiple size="6" aria-hidden="true" tabindex="-1">
<option value="">All Strategies</option>
</select>
<select id="filter-status" class="sr-only" multiple size="6" aria-hidden="true" tabindex="-1">
<option value="">All Status</option>
<option value="Open">Open</option>
<option value="Rolling">Rolling</option>
<option value="Closed">Closed</option>
<option value="Assigned">Assigned</option>
<option value="Expired">Expired</option>
</select>
<div class="filter-chip-group" role="group" aria-label="Filter by status">
<span class="filter-chip-group__label">Status</span>
<div class="filter-chips" id="filter-status-chips"></div>
</div>
<div class="filter-chip-group" role="group" aria-label="Filter by strategy">
<span class="filter-chip-group__label">Strategy</span>
<div class="filter-chips" id="filter-strategy-chips"></div>
</div>
<div class="trades-filters-search">
<input type="text" id="search-ticker" class="form-control" placeholder="Search ticker, strategy, or notes...">
</div>
</div>
</div>
<section class="trades-merge-panel is-collapsed" id="trades-merge-panel" aria-live="polite" aria-hidden="true">
<header class="trades-merge-panel__header">
<div>
<h3 class="trades-merge-panel__title">Merge Trades by Ticker</h3>
<p id="trades-merge-summary" class="trades-merge-panel__summary">Select two or more trades with the same ticker to enable merging.</p>
</div>
<button type="button" class="btn btn--secondary" id="trades-merge-btn" disabled>Merge Selected Trades</button>
</header>
<div id="trades-merge-groups" class="trades-merge-groups"></div>
</section>
<div class="table-container trades-grid-container">
<div class="trades-grid-toolbar trade-select-header is-hidden" aria-hidden="true">
<label class="trades-grid-select-all">
<input type="checkbox" id="trades-select-all" aria-label="Select all visible trades" disabled>
<span>Select visible trades</span>
</label>
</div>
<div id="trades-table" class="trades-grid ag-theme-quartz" aria-label="All trades"></div>
</div>
</div>
<!-- Credit Playbook View -->
<div class="view credit-playbook-view">
<header class="credit-playbook-header">
<div class="credit-playbook-metrics" id="credit-playbook-metrics" aria-live="polite"></div>
<div class="credit-playbook-detail-meta credit-playbook-help">
Wheel trades: Credit Playbook tracks option premium legs. Total wheel P&L (including stock assignment/sale) is shown in All Trades and Dashboard → Wheel/PMCC tracker.
</div>
</header>
<section class="credit-playbook-controls" aria-label="Credit playbook filters">
<div class="credit-playbook-filter">
<span class="filter-label">Status</span>
<div class="chart-range" id="credit-playbook-status-filter" role="group" aria-label="Status filter">
<button type="button" class="chart-range__button" data-status="all">All</button>
<button type="button" class="chart-range__button is-active" data-status="active">Active</button>
<button type="button" class="chart-range__button" data-status="closed">Closed</button>
</div>
</div>
<div class="credit-playbook-filter">
<span class="filter-label">Time Horizon</span>
<select id="credit-playbook-horizon-filter" class="form-control">
<option value="all" selected>All time</option>
<option value="7d">Last 7 days</option>
<option value="14d">Last 14 days</option>
<option value="30d">Last 30 days</option>
<option value="90d">Last 90 days</option>
<option value="180d">Last 180 days</option>
<option value="365d">Last 365 days</option>
<option value="mtd">Month to date</option>
<option value="ytd">Year to date</option>
</select>
</div>
<div class="credit-playbook-filter">
<span class="filter-label">Strategy</span>
<select id="credit-playbook-strategy-filter" class="form-control">
<option value="all" selected>All strategies</option>
<option value="Bear Call Ladder">Bear Call Ladder</option>
<option value="Bear Call Spread">Bear Call Spread</option>
<option value="Bear Put Ladder">Bear Put Ladder</option>
<option value="Bear Put Spread">Bear Put Spread</option>
<option value="Box Spread">Box Spread</option>
<option value="Bull Call Ladder">Bull Call Ladder</option>
<option value="Bull Call Spread">Bull Call Spread</option>
<option value="Bull Put Ladder">Bull Put Ladder</option>
<option value="Bull Put Spread">Bull Put Spread</option>
<option value="Calendar Call Spread">Calendar Call Spread</option>
<option value="Calendar Put Spread">Calendar Put Spread</option>
<option value="Calendar Straddle">Calendar Straddle</option>
<option value="Calendar Strangle">Calendar Strangle</option>
<option value="Call Broken Wing">Call Broken Wing</option>
<option value="Call Ratio Backspread">Call Ratio Backspread</option>
<option value="Call Ratio Spread">Call Ratio Spread</option>
<option value="Cash-Secured Put">Cash-Secured Put</option>
<option value="Collar">Collar</option>
<option value="Covered Call">Covered Call</option>
<option value="Covered Put">Covered Put</option>
<option value="Covered Short Straddle">Covered Short Straddle</option>
<option value="Covered Short Strangle">Covered Short Strangle</option>
<option value="Diagonal Call Spread">Diagonal Call Spread</option>
<option value="Diagonal Put Spread">Diagonal Put Spread</option>
<option value="Double Diagonal">Double Diagonal</option>
<option value="Guts">Guts</option>
<option value="Inverse Call Broken Wing">Inverse Call Broken Wing</option>
<option value="Inverse Iron Butterfly">Inverse Iron Butterfly</option>
<option value="Inverse Iron Condor">Inverse Iron Condor</option>
<option value="Inverse Put Broken Wing">Inverse Put Broken Wing</option>
<option value="Iron Albatross">Iron Albatross</option>
<option value="Iron Butterfly">Iron Butterfly</option>
<option value="Iron Condor">Iron Condor</option>
<option value="Jade Lizard">Jade Lizard</option>
<option value="Long Call">Long Call</option>
<option value="Long Call Butterfly">Long Call Butterfly</option>
<option value="Long Call Condor">Long Call Condor</option>
<option value="Long Put">Long Put</option>
<option value="Long Put Butterfly">Long Put Butterfly</option>
<option value="Long Put Condor">Long Put Condor</option>
<option value="Long Straddle">Long Straddle</option>
<option value="Long Strangle">Long Strangle</option>
<option value="Poor Man's Covered Call">Poor Man's Covered Call</option>
<option value="Protective Put">Protective Put</option>
<option value="Put Broken Wing">Put Broken Wing</option>
<option value="Put Ratio Backspread">Put Ratio Backspread</option>
<option value="Put Ratio Spread">Put Ratio Spread</option>
<option value="Reverse Jade Lizard">Reverse Jade Lizard</option>
<option value="Short Call">Short Call</option>
<option value="Short Call Butterfly">Short Call Butterfly</option>
<option value="Short Call Condor">Short Call Condor</option>
<option value="Short Guts">Short Guts</option>
<option value="Short Put">Short Put</option>
<option value="Short Put Butterfly">Short Put Butterfly</option>
<option value="Short Put Condor">Short Put Condor</option>
<option value="Short Straddle">Short Straddle</option>
<option value="Short Strangle">Short Strangle</option>
<option value="Strap">Strap</option>
<option value="Strip">Strip</option>
<option value="Synthetic Long Stock">Synthetic Long Stock</option>
<option value="Synthetic Short Stock">Synthetic Short Stock</option>
<option value="Synthetic Put">Synthetic Put</option>
<option value="Wheel">Wheel</option>
</select>
</div>
<div class="credit-playbook-filter">
<label class="filter-label" for="credit-playbook-symbol-filter">Symbol</label>
<input type="search" id="credit-playbook-symbol-filter" class="form-control" placeholder="Filter ticker...">
</div>
</section>
<div class="credit-playbook-table-container">
<div id="credit-playbook-table" class="credit-playbook-grid ag-theme-quartz" aria-label="Credit playbook positions"></div>
</div>
</div>
<!-- Import View -->
<div class="view import-view">
<section class="import-section">
<header class="import-header">
<h2>Import Trade Activity</h2>
<p>Bring in broker exports without overwriting your existing database. Trades from OFX and CSV files are merged into your current portfolio.</p>
</header>
<div class="import-dropzone" id="import-dropzone" role="region" aria-label="Drop zone for import files">
<div class="import-actions">
<button type="button" class="btn btn--primary" id="import-ofx-btn">Import OFX…</button>
<button type="button" class="btn btn--primary" id="import-robinhood-btn">Import Robinhood CSV…</button>
<button type="button" class="btn btn--primary" id="import-schwab-btn">Import Schwab CSV…</button>
</div>
<p class="import-dropzone__hint">or drag & drop an OFX or CSV file here — CSVs are auto-detected (Robinhood, Schwab, or a column-mapper for anything else)</p>
</div>
<section class="import-stats" aria-live="polite">
<h3>Latest Import Summary</h3>
<div id="import-summary" class="import-summary"></div>
</section>
<section class="import-merge import-merge--hint" aria-live="polite">
<h3>Review Queue <span id="import-merge-count" class="import-merge__badge"></span></h3>
<p id="import-merge-hint" class="import-merge__help">After importing, some trades may need to be combined — for example, matching STO and BTC legs or rolling positions. Use the Merge Trades tool on the All Trades page to review and merge them.</p>
<div id="import-merge-list" class="import-merge-list"></div>
<div class="import-merge__bulk-actions">
<button type="button" class="btn btn--sm btn--primary" id="import-approve-selected" disabled>Approve Selected</button>
<button type="button" class="btn btn--sm btn--secondary" id="import-merge-btn" disabled>Merge Selected</button>
<button type="button" class="btn btn--sm btn--danger" id="import-discard-selected" disabled>Discard Selected</button>
<button type="button" class="btn btn--sm btn--secondary" id="import-merge-hint-btn">Review Merge Opportunities</button>
</div>
</section>
<section class="import-feedback" aria-live="polite">
<h3>Import Log</h3>
<div id="import-log" class="import-log" role="status"></div>
</section>
<section class="import-help">
<h3>Import Tips</h3>
<ul>
<li><strong>OFX / QFX:</strong> Download your activity or transaction history from your broker as an OFX or QFX file. Most brokers offer this under Account → History → Export.</li>
<li><strong>Robinhood CSV:</strong> Export your trade history from the Robinhood app under Account → Statements & History → Download CSV.</li>
<li><strong>Schwab CSV:</strong> Export transactions from Schwab under Accounts → History → Export. Options symbols, rolls, and assignments are detected; expiration rows are skipped (open contracts auto-expire from their expiration date).</li>
<li><strong>Other broker CSVs:</strong> Drop any CSV on the import zone — unrecognized formats open a column mapper where you match columns (date, action, symbol, …) and action values (BTO/STO/BTC/STC) before importing.</li>
<li><strong>AI Screenshot:</strong> Open the AI Coach, attach a screenshot of your broker's trade history, and click <em>Extract draft legs</em>. Extracted trades land here for review before being added to your portfolio.</li>
<li><strong>Multi-leg grouping:</strong> Legs that share the same timestamp are grouped into a single trade automatically.</li>
<li><strong>Open/close matching:</strong> BTC and STC legs are matched to open positions with the same ticker, strike, and expiration. Unmatched closing legs are placed in the review queue.</li>
<li><strong>Roll detection:</strong> A BTC and STO for the same ticker and option type on the same day are treated as a roll and merged into one trade.</li>
<li><strong>Wheel & assignment:</strong> Assignment and stock legs are consolidated into unified Wheel trades, preserving premium history and cost basis.</li>
<li><strong>Split fills:</strong> Multiple partial fills from the same order are consolidated into a single leg with a quantity-weighted average price.</li>
<li><strong>Review queue:</strong> Trades that need attention (unmatched legs, missing fields, AI drafts) appear in the Review Queue above. Approve, edit, merge, or discard each one before they count toward your portfolio stats.</li>
<li><strong>Safe to re-import:</strong> Duplicate legs from previously imported files are detected and skipped automatically.</li>
</ul>
</section>
</section>
</div>
<!-- Settings View -->
<div class="view settings-view">
<section class="settings-section">
<header class="settings-section__header">
<h2>Integration Settings</h2>
<p>Manage live data connections and other preferences that stay on this device.</p>
</header>
<div class="settings-card" id="finnhub-controls">
<div class="settings-card__header">
<h3>Finnhub API Key</h3>
<p class="settings-card__subtitle">We encrypt your key locally before storing it in this browser.</p>
</div>
<div class="settings-card__body">
<label for="finnhub-api-key" class="form-label">API Key</label>
<div class="settings-input-row">
<input type="password" id="finnhub-api-key" class="form-control finnhub-input" placeholder="Paste API key" autocomplete="off">
<button class="btn btn--sm btn--primary" id="finnhub-save">Save Key</button>
</div>
<p class="settings-help-text">The key never leaves your machine. Clearing browser storage will remove it.</p>
<div class="finnhub-status" id="finnhub-status" role="status">Not set</div>
<div class="settings-divider"></div>
<label for="finnhub-rate-limit" class="form-label">Rate Limit (requests per minute)</label>
<div class="settings-input-row">
<input type="number" id="finnhub-rate-limit" class="form-control" placeholder="60" min="1" max="300" step="1" autocomplete="off">
<button class="btn btn--sm btn--primary" id="finnhub-rate-save">Save</button>
<button class="btn btn--sm btn--secondary" id="finnhub-rate-reset">Reset</button>
</div>
<p class="settings-help-text">Free Finnhub accounts are limited to 60 requests/minute. Adjust if you have a paid plan.</p>
<div class="finnhub-rate-status" id="finnhub-rate-status" role="status">Default: 60/min</div>
</div>
</div>
<div class="settings-card" id="gemini-controls">
<div class="settings-card__header">
<h3>Gemini API</h3>
<p class="settings-card__subtitle">Store a Google Gemini-compatible API key to enable AI portfolio insights.</p>
</div>
<div class="settings-card__body">
<label for="gemini-api-key" class="form-label">API Key</label>
<div class="settings-input-row">
<input type="password" id="gemini-api-key" class="form-control" placeholder="Paste API key" autocomplete="off">
<button class="btn btn--sm btn--primary" id="gemini-save">Save Key</button>
<button class="btn btn--sm btn--secondary" id="gemini-clear">Clear</button>
</div>
<div class="form-group">
<label for="gemini-model" class="form-label">Model</label>
<select id="gemini-model" class="form-control"></select>
</div>
<p class="settings-help-text">Keys stay on this device. Use Google AI Studio or any compatible service exposing the Gemini generateContent API.</p>
<div class="gemini-status" id="gemini-status" role="status">Not set</div>
<div class="settings-divider"></div>
<label for="gemini-max-tokens" class="form-label">Max Output Tokens</label>
<div class="settings-input-row">
<input type="number" id="gemini-max-tokens" class="form-control" placeholder="65536" min="1024" max="1000000" step="1024" autocomplete="off">
<button class="btn btn--sm btn--primary" id="gemini-tokens-save">Save</button>
<button class="btn btn--sm btn--secondary" id="gemini-tokens-reset">Reset</button>
</div>
<p class="settings-help-text">Maximum tokens for AI responses. Higher values allow longer responses but may increase cost.</p>
<div class="gemini-tokens-status" id="gemini-tokens-status" role="status">Default: 65536</div>
</div>
</div>
</section>
<br>
<section class="settings-section">
<header class="settings-section__header">
<h2>Trade Entry Defaults</h2>
<p>Set default values to speed up manual trade entry.</p>
</header>
<div class="settings-card" id="default-fees-controls">
<div class="settings-card__header">
<h3>Default Fee Per Contract</h3>
<p class="settings-card__subtitle">Automatically apply this fee when adding new trade legs.</p>
</div>
<div class="settings-card__body">
<label for="default-fee-per-contract" class="form-label">Fee Per Contract</label>
<div class="settings-input-row">
<input type="number" id="default-fee-per-contract" class="form-control" placeholder="e.g. 0.65" step="0.01" min="0" autocomplete="off">
<button class="btn btn--sm btn--primary" id="default-fee-save">Save</button>
<button class="btn btn--sm btn--secondary" id="default-fee-clear">Clear</button>
</div>
<p class="settings-help-text">Enter the fee charged per contract (e.g., $0,65). This will be multiplied by the quantity when adding new legs.</p>
<div class="default-fee-status" id="default-fee-status" role="status">Not set</div>
</div>
</div>
</section>
</div>
</main>
</div>
<!-- Hidden file input for fallback -->
<input type="file" id="file-input" accept=".json" class="hidden">
<input type="file" id="import-ofx-input" accept=".ofx,.OFX" class="hidden">
<input type="file" id="import-robinhood-input" accept=".csv,.CSV" class="hidden">
<input type="file" id="import-schwab-input" accept=".csv,.CSV" class="hidden">
<input type="file" id="ai-chat-image-input" accept="image/png,image/jpeg,image/webp,image/heic,image/heif" class="hidden">
<div class="ai-chat" id="ai-chat">
<button type="button" class="ai-chat__toggle" id="ai-chat-toggle" aria-controls="ai-chat-panel" aria-expanded="false">
🤖 AI Coach
</button>
<div class="ai-chat__panel hidden" id="ai-chat-panel" aria-hidden="true">
<div class="ai-chat__resize-handle" id="ai-chat-resize-handle" role="presentation" aria-hidden="true"></div>
<div class="ai-chat__header">
<div>
<h3 id="ai-chat-title" class="ai-chat__title">Portfolio AI Coach</h3>
<p id="ai-chat-subtitle" class="ai-chat__subtitle"></p>
</div>
<button type="button" class="ai-chat__close" id="ai-chat-close" aria-label="Close AI chat">×</button>
</div>
<div class="ai-chat__body" id="ai-chat-history" aria-live="polite"></div>
<section class="ai-chat__draft-import hidden" id="ai-draft-import" aria-live="polite"></section>
<form class="ai-chat__form" id="ai-chat-form">
<input type="text" id="ai-chat-input" class="ai-chat__input" placeholder="Ask about your portfolio..." autocomplete="off" required>
<button type="button" class="btn btn--secondary ai-chat__attach" id="ai-chat-attach-image">Trade Screenshot</button>
<button type="submit" class="btn btn--primary ai-chat__send">Send</button>
</form>
<div class="ai-chat__quick" id="ai-chat-quick">
<span class="ai-chat__quick-label">Quick prompts:</span>
<div class="ai-chat__quick-buttons">
<button type="button" class="ai-chat__quick-btn" data-ai-prompt="Portfolio health" data-ai-prompt-type="portfolio_health">Portfolio health</button>
<button type="button" class="ai-chat__quick-btn" data-ai-prompt="Risk check" data-ai-prompt-type="risk_check">Risk check</button>
<button type="button" class="ai-chat__quick-btn" data-ai-prompt="Strategy ideas" data-ai-prompt-type="strategy_ideas">Strategy ideas</button>
</div>
</div>
</div>
</div>
<div id="share-card-root" class="share-card-root" aria-hidden="true">
<div class="share-card" role="presentation">
<header class="share-card__header">
<div class="share-card__title">
<h2 class="share-card__heading">Portfolio Snapshot</h2>
<p class="share-card__meta" id="share-card-date">—</p>
<p class="share-card__meta share-card__meta--range" id="share-card-range">Range: All Time</p>
</div>
</header>
<div class="share-card__metrics">
<div class="share-card__metric">
<span class="share-card__metric-label">Realized P&L</span>
<span class="share-card__metric-value" id="share-card-total-pl">$0.00</span>
</div>
<div class="share-card__metric">
<span class="share-card__metric-label">Win Rate</span>
<span class="share-card__metric-value" id="share-card-win-rate">0%</span>
</div>
<div class="share-card__metric">
<span class="share-card__metric-label">Profit Factor</span>
<span class="share-card__metric-value" id="share-card-profit-factor">0.00</span>
</div>
<div class="share-card__metric">
<span class="share-card__metric-label">Total ROI</span>
<span class="share-card__metric-value" id="share-card-total-roi">0%</span>
</div>
</div>
<div class="share-card__chart">
<h3 class="share-card__chart-title">Cumulative P&L</h3>
<div id="share-card-cumulative-chart" class="echarts-chart" role="img" aria-label="Cumulative P and L chart"></div>
</div>
<footer class="share-card__footer">
<span class="share-card__footnote">Generated with GammaLedger.com</span>
</footer>
</div>
</div>
<dialog id="shortcut-help" class="shortcut-help" aria-labelledby="shortcut-help-title">
<div class="shortcut-help__panel">
<h2 id="shortcut-help-title" class="shortcut-help__title">Keyboard shortcuts</h2>
<table class="shortcut-help__table">
<tbody>
<tr><td><kbd>n</kbd></td><td>New trade</td></tr>
<tr><td><kbd>/</kbd></td><td>Search trades</td></tr>
<tr><td><kbd>g</kbd> then <kbd>d</kbd></td><td>Go to Dashboard</td></tr>
<tr><td><kbd>g</kbd> then <kbd>t</kbd></td><td>Go to All Trades</td></tr>
<tr><td><kbd>g</kbd> then <kbd>i</kbd></td><td>Go to Import</td></tr>
<tr><td><kbd>g</kbd> then <kbd>s</kbd></td><td>Go to Settings</td></tr>
<tr><td><kbd>?</kbd></td><td>Toggle this help</td></tr>
<tr><td><kbd>Esc</kbd></td><td>Close dialogs, popovers, and the AI chat panel</td></tr>
</tbody>
</table>
<div class="shortcut-help__actions">
<button type="button" class="btn btn--sm btn--secondary" data-action="shortcut-help-close">Close</button>
</div>
</div>
</dialog>
<div id="toast-region" class="toast-region" aria-label="Notifications" role="region"></div>
<script type="module" src="/src/index.js"></script>
</body>
</html>