@tradecanvas/chart 0.8.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +86 -4
  2. package/dist/Chart.d.ts +121 -1
  3. package/dist/Chart.d.ts.map +1 -1
  4. package/dist/{Chart-Cn_TSMO7.js → DragDropImporter-Br2ez5Gz.js} +560 -91
  5. package/dist/DragDropImporter-Br2ez5Gz.js.map +1 -0
  6. package/dist/DragDropImporter-ycI_Tcs6.cjs +2 -0
  7. package/dist/DragDropImporter-ycI_Tcs6.cjs.map +1 -0
  8. package/dist/finance/PerformanceDashboard.d.ts +43 -0
  9. package/dist/finance/PerformanceDashboard.d.ts.map +1 -0
  10. package/dist/finance/index.d.ts +4 -0
  11. package/dist/finance/index.d.ts.map +1 -1
  12. package/dist/finance/performanceData.d.ts +39 -0
  13. package/dist/finance/performanceData.d.ts.map +1 -0
  14. package/dist/index.cjs +1 -1
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.ts +5 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +287 -30
  19. package/dist/index.js.map +1 -1
  20. package/dist/io/DragDropImporter.d.ts +34 -0
  21. package/dist/io/DragDropImporter.d.ts.map +1 -0
  22. package/dist/io/index.d.ts +7 -0
  23. package/dist/io/index.d.ts.map +1 -0
  24. package/dist/io/parseOHLCV.d.ts +21 -0
  25. package/dist/io/parseOHLCV.d.ts.map +1 -0
  26. package/dist/io/resampleOHLCV.d.ts +29 -0
  27. package/dist/io/resampleOHLCV.d.ts.map +1 -0
  28. package/dist/widget/AlertNotifier.d.ts +32 -0
  29. package/dist/widget/AlertNotifier.d.ts.map +1 -0
  30. package/dist/widget/ChartWidget.d.ts +100 -2
  31. package/dist/widget/ChartWidget.d.ts.map +1 -1
  32. package/dist/widget/DrawingFavoritesStore.d.ts +22 -0
  33. package/dist/widget/DrawingFavoritesStore.d.ts.map +1 -0
  34. package/dist/widget/DrawingTemplateStore.d.ts +29 -0
  35. package/dist/widget/DrawingTemplateStore.d.ts.map +1 -0
  36. package/dist/widget/WidgetAlertsPanel.d.ts +58 -0
  37. package/dist/widget/WidgetAlertsPanel.d.ts.map +1 -0
  38. package/dist/widget/WidgetBracketBar.d.ts +21 -0
  39. package/dist/widget/WidgetBracketBar.d.ts.map +1 -0
  40. package/dist/widget/WidgetDataWindow.d.ts +41 -0
  41. package/dist/widget/WidgetDataWindow.d.ts.map +1 -0
  42. package/dist/widget/WidgetDepthLadder.d.ts +29 -0
  43. package/dist/widget/WidgetDepthLadder.d.ts.map +1 -0
  44. package/dist/widget/WidgetDrawingSidebar.d.ts +6 -0
  45. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -1
  46. package/dist/widget/WidgetDrawingStyle.d.ts +36 -0
  47. package/dist/widget/WidgetDrawingStyle.d.ts.map +1 -0
  48. package/dist/widget/WidgetHotkeySheet.d.ts +20 -0
  49. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -0
  50. package/dist/widget/WidgetIndicatorSettings.d.ts +42 -0
  51. package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -0
  52. package/dist/widget/WidgetObjectTree.d.ts +59 -0
  53. package/dist/widget/WidgetObjectTree.d.ts.map +1 -0
  54. package/dist/widget/WidgetReplayBar.d.ts +41 -0
  55. package/dist/widget/WidgetReplayBar.d.ts.map +1 -0
  56. package/dist/widget/WidgetSettings.d.ts +1 -0
  57. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  58. package/dist/widget/WidgetSymbolSearch.d.ts +34 -0
  59. package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -0
  60. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  61. package/dist/widget/WidgetWatchlist.d.ts +39 -0
  62. package/dist/widget/WidgetWatchlist.d.ts.map +1 -0
  63. package/dist/widget/icons.d.ts.map +1 -1
  64. package/dist/widget/index.cjs +2372 -877
  65. package/dist/widget/index.cjs.map +1 -1
  66. package/dist/widget/index.js +2455 -185
  67. package/dist/widget/index.js.map +1 -1
  68. package/dist/widget/ladderRows.d.ts +21 -0
  69. package/dist/widget/ladderRows.d.ts.map +1 -0
  70. package/dist/widget/types.d.ts +91 -1
  71. package/dist/widget/types.d.ts.map +1 -1
  72. package/dist/widget/widgetConfig.d.ts.map +1 -1
  73. package/dist/widget/widgetShareState.d.ts +26 -0
  74. package/dist/widget/widgetShareState.d.ts.map +1 -0
  75. package/package.json +3 -3
  76. package/dist/Chart-Br_N-BCL.cjs +0 -2
  77. package/dist/Chart-Br_N-BCL.cjs.map +0 -1
  78. package/dist/Chart-Cn_TSMO7.js.map +0 -1
@@ -1,878 +1,2373 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../Chart-Br_N-BCL.cjs`);let t=require(`@tradecanvas/commons`);var n=[{label:`1m`,value:`1m`},{label:`5m`,value:`5m`},{label:`15m`,value:`15m`},{label:`1H`,value:`1h`},{label:`4H`,value:`4h`},{label:`1D`,value:`1d`}],r=[{label:`Candlestick`,value:`candlestick`},{label:`Line`,value:`line`},{label:`Area`,value:`area`},{label:`Bar`,value:`bar`},{label:`Heikin-Ashi`,value:`heikinAshi`},{label:`Hollow Candle`,value:`hollowCandle`},{label:`Baseline`,value:`baseline`},{label:`Volume Candles`,value:`volumeCandles`},{label:`Equivolume`,value:`equivolume`},{label:`HLC Area`,value:`hlcArea`},{label:`Step Line`,value:`stepLine`},{label:`Line + Markers`,value:`lineWithMarkers`}],i=[{label:`Lines`,tools:[{label:`Trend Line`,value:`trendLine`},{label:`Ray`,value:`ray`},{label:`Extended Line`,value:`extendedLine`}]},{label:`Horizontal/Vertical`,tools:[{label:`Horizontal Line`,value:`horizontalLine`},{label:`Vertical Line`,value:`verticalLine`}]},{label:`Channels`,tools:[{label:`Parallel Channel`,value:`parallelChannel`},{label:`Regression Channel`,value:`regressionChannel`}]},{label:`Fibonacci`,tools:[{label:`Fib Retracement`,value:`fibRetracement`},{label:`Fib Extension`,value:`fibExtension`}]},{label:`Shapes`,tools:[{label:`Rectangle`,value:`rectangle`},{label:`Ellipse`,value:`ellipse`},{label:`Triangle`,value:`triangle`}]},{label:`Gann & Advanced`,tools:[{label:`Pitchfork`,value:`pitchfork`},{label:`Gann Fan`,value:`gannFan`},{label:`Gann Box`,value:`gannBox`},{label:`Elliott Wave`,value:`elliottWave`}]},{label:`Measure`,tools:[{label:`Price Range`,value:`priceRange`},{label:`Date Range`,value:`dateRange`},{label:`Measure`,value:`measure`}]},{label:`Annotation`,tools:[{label:`Text`,value:`text`},{label:`Arrow`,value:`arrow`}]}],a=[{id:`sma`,name:`SMA`,type:`overlay`},{id:`ema`,name:`EMA`,type:`overlay`},{id:`hma`,name:`Hull MA`,type:`overlay`},{id:`bb`,name:`Bollinger Bands`,type:`overlay`},{id:`vwap`,name:`VWAP`,type:`overlay`},{id:`avwap`,name:`Anchored VWAP`,type:`overlay`},{id:`ichimoku`,name:`Ichimoku Cloud`,type:`overlay`},{id:`psar`,name:`Parabolic SAR`,type:`overlay`},{id:`supertrend`,name:`Supertrend`,type:`overlay`},{id:`keltner`,name:`Keltner Channel`,type:`overlay`},{id:`donchian`,name:`Donchian Channel`,type:`overlay`},{id:`pivots`,name:`Pivot Points`,type:`overlay`},{id:`zigzag`,name:`ZigZag`,type:`overlay`},{id:`lrc`,name:`Linear Regression Channel`,type:`overlay`},{id:`rsi`,name:`RSI`,type:`panel`},{id:`macd`,name:`MACD`,type:`panel`},{id:`stochastic`,name:`Stochastic`,type:`panel`},{id:`atr`,name:`ATR`,type:`panel`},{id:`adx`,name:`ADX`,type:`panel`},{id:`obv`,name:`OBV`,type:`panel`},{id:`williamsR`,name:`Williams %R`,type:`panel`},{id:`cci`,name:`CCI`,type:`panel`},{id:`mfi`,name:`MFI`,type:`panel`},{id:`roc`,name:`ROC`,type:`panel`},{id:`tsi`,name:`TSI`,type:`panel`},{id:`cmf`,name:`CMF`,type:`panel`},{id:`aroon`,name:`Aroon`,type:`panel`},{id:`stddev`,name:`Std Deviation`,type:`panel`},{id:`vroc`,name:`Volume ROC`,type:`panel`},{id:`ad`,name:`Acc/Dist`,type:`panel`},{id:`ao`,name:`Awesome Oscillator`,type:`panel`},{id:`chaikinOsc`,name:`Chaikin Oscillator`,type:`panel`},{id:`volumeProfile`,name:`Volume Profile`,type:`panel`}],o=[`sma`,`ema`,`bb`,`rsi`,`macd`,`stochastic`,`vwap`,`atr`,`obv`,`ichimoku`],s=[`BTCUSDT`,`ETHUSDT`,`SOLUSDT`,`BNBUSDT`],c={candleUpColor:`#26A69A`,candleDownColor:`#EF5350`,candleUpWick:`#26A69A`,candleDownWick:`#EF5350`,backgroundColor:`#131722`,gridColor:`#1E222D`,gridVisible:!0,volumeVisible:!0,legendVisible:!0,barCountdown:!0,logScale:!1,autoScale:!0,crosshairMode:`magnet`,numberLocale:`en-US`},l=`/* === TradeCanvas Widget Styles === */\r
2
- \r
3
- .tcw-root {\r
4
- display: flex;\r
5
- flex-direction: column;\r
6
- width: 100%;\r
7
- height: 100%;\r
8
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\r
9
- font-size: 13px;\r
10
- color: #d1d4dc;\r
11
- background: #131722;\r
12
- position: relative;\r
13
- overflow: hidden;\r
14
- \r
15
- /* Dark theme tokens (default) */\r
16
- --tcw-bg: #131722;\r
17
- --tcw-bg-elevated: #1E222D;\r
18
- --tcw-border: #2A2E39;\r
19
- --tcw-text: #d1d4dc;\r
20
- --tcw-text-dim: #b2b5be;\r
21
- --tcw-text-muted: #787b86;\r
22
- --tcw-accent: #2962ff;\r
23
- --tcw-accent-dim: rgba(41,98,255,0.15);\r
24
- --tcw-accent-glow: rgba(41,98,255,0.12);\r
25
- --tcw-red: #ef5350;\r
26
- --tcw-green: #26a69a;\r
27
- --tcw-transition: 0.15s ease;\r
28
- --tcw-radius-lg: 8px;\r
29
- --tcw-font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;\r
30
- --tcw-hover-bg: rgba(255,255,255,0.04);\r
31
- }\r
32
- \r
33
- .tcw-root[data-tcw-theme="light"] {\r
34
- color: #131722;\r
35
- background: #ffffff;\r
36
- \r
37
- --tcw-bg: #ffffff;\r
38
- --tcw-bg-elevated: #f0f3fa;\r
39
- --tcw-border: #e0e3eb;\r
40
- --tcw-text: #131722;\r
41
- --tcw-text-dim: #434651;\r
42
- --tcw-text-muted: #787b86;\r
43
- --tcw-accent: #2962ff;\r
44
- --tcw-accent-dim: rgba(41,98,255,0.1);\r
45
- --tcw-accent-glow: rgba(41,98,255,0.08);\r
46
- --tcw-red: #ef5350;\r
47
- --tcw-green: #26a69a;\r
48
- --tcw-hover-bg: rgba(0,0,0,0.04);\r
49
- }\r
50
- \r
51
- /* === Toolbar === */\r
52
- \r
53
- .tcw-toolbar {\r
54
- display: flex;\r
55
- align-items: center;\r
56
- gap: 0;\r
57
- padding: 0 12px;\r
58
- height: 40px;\r
59
- border-bottom: 1px solid var(--tcw-border);\r
60
- background: var(--tcw-bg-elevated);\r
61
- flex-shrink: 0;\r
62
- position: relative;\r
63
- z-index: 20;\r
64
- }\r
65
- \r
66
- .tcw-toolbar-symbol {\r
67
- font-size: 13px;\r
68
- font-weight: 700;\r
69
- color: var(--tcw-text);\r
70
- padding: 0 10px;\r
71
- white-space: nowrap;\r
72
- letter-spacing: -0.01em;\r
73
- cursor: pointer;\r
74
- border: none;\r
75
- background: none;\r
76
- font-family: inherit;\r
77
- }\r
78
- \r
79
- .tcw-toolbar-sep {\r
80
- width: 1px;\r
81
- height: 20px;\r
82
- background: var(--tcw-border);\r
83
- flex-shrink: 0;\r
84
- }\r
85
- \r
86
- .tcw-toolbar-group {\r
87
- display: flex;\r
88
- align-items: center;\r
89
- gap: 2px;\r
90
- padding: 0 8px;\r
91
- }\r
92
- \r
93
- .tcw-toolbar-spacer {\r
94
- flex: 1;\r
95
- }\r
96
- \r
97
- .tcw-btn {\r
98
- padding: 4px 8px;\r
99
- font-size: 12px;\r
100
- font-family: inherit;\r
101
- border: none;\r
102
- border-radius: 4px;\r
103
- background: transparent;\r
104
- color: var(--tcw-text-dim);\r
105
- cursor: pointer;\r
106
- transition: all var(--tcw-transition);\r
107
- white-space: nowrap;\r
108
- line-height: 1;\r
109
- }\r
110
- \r
111
- .tcw-btn:hover {\r
112
- background: var(--tcw-hover-bg);\r
113
- color: var(--tcw-text);\r
114
- }\r
115
- \r
116
- .tcw-btn.tcw-active {\r
117
- background: var(--tcw-accent);\r
118
- color: white;\r
119
- }\r
120
- \r
121
- .tcw-btn-icon {\r
122
- width: 32px;\r
123
- height: 32px;\r
124
- display: inline-flex;\r
125
- align-items: center;\r
126
- justify-content: center;\r
127
- font-family: inherit;\r
128
- border: none;\r
129
- border-radius: 4px;\r
130
- background: transparent;\r
131
- color: var(--tcw-text-muted);\r
132
- cursor: pointer;\r
133
- transition: all var(--tcw-transition);\r
134
- line-height: 1;\r
135
- position: relative;\r
136
- }\r
137
- \r
138
- .tcw-btn-icon:hover {\r
139
- background: var(--tcw-hover-bg);\r
140
- color: var(--tcw-text);\r
141
- }\r
142
- \r
143
- .tcw-badge-count {\r
144
- font-size: 10px;\r
145
- color: var(--tcw-accent);\r
146
- background: var(--tcw-accent-dim);\r
147
- padding: 0 4px;\r
148
- border-radius: 8px;\r
149
- font-weight: 600;\r
150
- }\r
151
- \r
152
- .tcw-indicator-chips {\r
153
- display: flex;\r
154
- align-items: center;\r
155
- gap: 4px;\r
156
- padding: 0 4px;\r
157
- flex-wrap: nowrap;\r
158
- overflow: hidden;\r
159
- }\r
160
- \r
161
- .tcw-indicator-chip {\r
162
- display: inline-flex;\r
163
- align-items: center;\r
164
- gap: 4px;\r
165
- padding: 2px 6px 2px 8px;\r
166
- font-size: 11px;\r
167
- font-weight: 500;\r
168
- background: var(--tcw-accent-dim);\r
169
- color: var(--tcw-accent);\r
170
- border-radius: 4px;\r
171
- white-space: nowrap;\r
172
- line-height: 1.4;\r
173
- }\r
174
- \r
175
- .tcw-chip-remove {\r
176
- cursor: pointer;\r
177
- opacity: 0.6;\r
178
- padding: 0 2px;\r
179
- transition: opacity var(--tcw-transition);\r
180
- border: none;\r
181
- background: none;\r
182
- color: inherit;\r
183
- display: inline-flex;\r
184
- align-items: center;\r
185
- }\r
186
- \r
187
- .tcw-chip-remove:hover {\r
188
- opacity: 1;\r
189
- }\r
190
- \r
191
- /* === Dropdown === */\r
192
- \r
193
- .tcw-dropdown-trigger {\r
194
- display: inline-flex;\r
195
- align-items: center;\r
196
- gap: 4px;\r
197
- padding: 4px 8px;\r
198
- font-size: 12px;\r
199
- font-family: inherit;\r
200
- border: none;\r
201
- border-radius: 4px;\r
202
- background: transparent;\r
203
- color: var(--tcw-text-dim);\r
204
- cursor: pointer;\r
205
- transition: all var(--tcw-transition);\r
206
- white-space: nowrap;\r
207
- line-height: 1;\r
208
- }\r
209
- \r
210
- .tcw-dropdown-trigger:hover {\r
211
- background: var(--tcw-hover-bg);\r
212
- color: var(--tcw-text);\r
213
- }\r
214
- \r
215
- .tcw-dropdown {\r
216
- position: absolute;\r
217
- top: 100%;\r
218
- margin-top: 4px;\r
219
- background: var(--tcw-bg-elevated);\r
220
- border: 1px solid var(--tcw-border);\r
221
- border-radius: var(--tcw-radius-lg);\r
222
- box-shadow: 0 8px 32px rgba(0,0,0,0.4);\r
223
- z-index: 50;\r
224
- padding: 4px 0;\r
225
- max-height: 400px;\r
226
- overflow-y: auto;\r
227
- }\r
228
- \r
229
- .tcw-dropdown-item {\r
230
- display: flex;\r
231
- align-items: center;\r
232
- justify-content: space-between;\r
233
- padding: 6px 12px;\r
234
- font-size: 12px;\r
235
- color: var(--tcw-text-dim);\r
236
- cursor: pointer;\r
237
- transition: background var(--tcw-transition), color var(--tcw-transition);\r
238
- width: 100%;\r
239
- border: none;\r
240
- background: none;\r
241
- font-family: inherit;\r
242
- text-align: left;\r
243
- }\r
244
- \r
245
- .tcw-dropdown-item:hover {\r
246
- background: var(--tcw-hover-bg);\r
247
- color: var(--tcw-text);\r
248
- }\r
249
- \r
250
- .tcw-dropdown-item.tcw-active {\r
251
- color: var(--tcw-accent);\r
252
- }\r
253
- \r
254
- .tcw-dropdown-label {\r
255
- text-transform: uppercase;\r
256
- font-size: 10px;\r
257
- color: var(--tcw-text-muted);\r
258
- letter-spacing: 0.05em;\r
259
- padding: 6px 12px;\r
260
- font-weight: 600;\r
261
- }\r
262
- \r
263
- .tcw-dropdown-divider {\r
264
- border-top: 1px solid var(--tcw-border);\r
265
- margin: 4px 0;\r
266
- }\r
267
- \r
268
- .tcw-tag {\r
269
- font-size: 10px;\r
270
- color: var(--tcw-text-muted);\r
271
- padding: 1px 5px;\r
272
- border-radius: 3px;\r
273
- background: var(--tcw-hover-bg);\r
274
- }\r
275
- \r
276
- /* === Body === */\r
277
- \r
278
- .tcw-body {\r
279
- display: flex;\r
280
- flex: 1;\r
281
- min-height: 0;\r
282
- }\r
283
- \r
284
- .tcw-chart-container {\r
285
- flex: 1;\r
286
- min-width: 0;\r
287
- min-height: 0;\r
288
- width: 100%;\r
289
- height: 100%;\r
290
- }\r
291
- \r
292
- /* === Sidebar === */\r
293
- \r
294
- .tcw-sidebar {\r
295
- width: 36px;\r
296
- flex-shrink: 0;\r
297
- background: var(--tcw-bg-elevated);\r
298
- border-right: 1px solid var(--tcw-border);\r
299
- display: flex;\r
300
- flex-direction: column;\r
301
- align-items: center;\r
302
- padding: 4px 0;\r
303
- overflow: visible;\r
304
- }\r
305
- \r
306
- .tcw-tool-group-wrap {\r
307
- position: relative;\r
308
- }\r
309
- \r
310
- .tcw-sidebar-btn {\r
311
- width: 36px;\r
312
- height: 32px;\r
313
- display: flex;\r
314
- align-items: center;\r
315
- justify-content: center;\r
316
- border: none;\r
317
- background: transparent;\r
318
- color: var(--tcw-text-muted);\r
319
- cursor: pointer;\r
320
- font-family: inherit;\r
321
- transition: all var(--tcw-transition);\r
322
- position: relative;\r
323
- flex-shrink: 0;\r
324
- line-height: 1;\r
325
- }\r
326
- \r
327
- .tcw-sidebar-btn:hover {\r
328
- color: var(--tcw-text);\r
329
- background: var(--tcw-hover-bg);\r
330
- }\r
331
- \r
332
- .tcw-sidebar-btn.tcw-active {\r
333
- color: var(--tcw-accent);\r
334
- background: var(--tcw-accent-glow);\r
335
- }\r
336
- \r
337
- .tcw-sidebar-btn.tcw-danger:hover {\r
338
- color: var(--tcw-red);\r
339
- background: rgba(239,68,68,0.1);\r
340
- }\r
341
- \r
342
- .tcw-multi-dot {\r
343
- position: absolute;\r
344
- bottom: 2px;\r
345
- right: 2px;\r
346
- width: 4px;\r
347
- height: 4px;\r
348
- border-radius: 50%;\r
349
- background: var(--tcw-text-muted);\r
350
- }\r
351
- \r
352
- .tcw-sidebar-divider {\r
353
- width: 20px;\r
354
- height: 1px;\r
355
- background: var(--tcw-border);\r
356
- margin: 4px 0;\r
357
- flex-shrink: 0;\r
358
- }\r
359
- \r
360
- .tcw-sidebar-spacer {\r
361
- flex: 1;\r
362
- }\r
363
- \r
364
- /* === Flyout === */\r
365
- \r
366
- .tcw-flyout {\r
367
- position: absolute;\r
368
- left: 100%;\r
369
- top: 0;\r
370
- margin-left: 2px;\r
371
- min-width: 160px;\r
372
- background: var(--tcw-bg-elevated);\r
373
- border: 1px solid var(--tcw-border);\r
374
- border-radius: var(--tcw-radius-lg);\r
375
- box-shadow: 0 8px 32px rgba(0,0,0,0.4);\r
376
- z-index: 30;\r
377
- padding: 4px 0;\r
378
- }\r
379
- \r
380
- .tcw-flyout-header {\r
381
- text-transform: uppercase;\r
382
- font-size: 10px;\r
383
- color: var(--tcw-text-muted);\r
384
- letter-spacing: 0.05em;\r
385
- padding: 6px 12px;\r
386
- font-weight: 600;\r
387
- }\r
388
- \r
389
- .tcw-flyout-item {\r
390
- padding: 6px 12px;\r
391
- font-size: 12px;\r
392
- color: var(--tcw-text-dim);\r
393
- cursor: pointer;\r
394
- width: 100%;\r
395
- display: block;\r
396
- border: none;\r
397
- background: none;\r
398
- text-align: left;\r
399
- font-family: inherit;\r
400
- transition: background var(--tcw-transition), color var(--tcw-transition);\r
401
- }\r
402
- \r
403
- .tcw-flyout-item:hover {\r
404
- background: var(--tcw-hover-bg);\r
405
- color: var(--tcw-text);\r
406
- }\r
407
- \r
408
- .tcw-flyout-item.tcw-active {\r
409
- color: var(--tcw-accent);\r
410
- }\r
411
- \r
412
- /* === Modal === */\r
413
- \r
414
- .tcw-modal-backdrop {\r
415
- position: fixed;\r
416
- inset: 0;\r
417
- background: rgba(0,0,0,0.5);\r
418
- backdrop-filter: blur(4px);\r
419
- -webkit-backdrop-filter: blur(4px);\r
420
- z-index: 100;\r
421
- }\r
422
- \r
423
- .tcw-modal {\r
424
- position: fixed;\r
425
- z-index: 101;\r
426
- top: 50%;\r
427
- left: 50%;\r
428
- transform: translate(-50%, -50%);\r
429
- background: var(--tcw-bg-elevated);\r
430
- border: 1px solid var(--tcw-border);\r
431
- border-radius: var(--tcw-radius-lg);\r
432
- width: 480px;\r
433
- max-width: 90vw;\r
434
- max-height: 80vh;\r
435
- display: flex;\r
436
- flex-direction: column;\r
437
- box-shadow: 0 24px 64px rgba(0,0,0,0.5);\r
438
- }\r
439
- \r
440
- .tcw-modal-header {\r
441
- display: flex;\r
442
- align-items: center;\r
443
- justify-content: space-between;\r
444
- padding: 16px 20px;\r
445
- border-bottom: 1px solid var(--tcw-border);\r
446
- }\r
447
- \r
448
- .tcw-modal-header h3 {\r
449
- font-size: 15px;\r
450
- font-weight: 600;\r
451
- margin: 0;\r
452
- color: var(--tcw-text);\r
453
- }\r
454
- \r
455
- .tcw-modal-close {\r
456
- width: 28px;\r
457
- height: 28px;\r
458
- display: flex;\r
459
- align-items: center;\r
460
- justify-content: center;\r
461
- border: none;\r
462
- background: transparent;\r
463
- color: var(--tcw-text-muted);\r
464
- cursor: pointer;\r
465
- border-radius: 4px;\r
466
- transition: all var(--tcw-transition);\r
467
- }\r
468
- \r
469
- .tcw-modal-close:hover {\r
470
- background: var(--tcw-hover-bg);\r
471
- color: var(--tcw-text);\r
472
- }\r
473
- \r
474
- .tcw-modal-tabs {\r
475
- display: flex;\r
476
- gap: 0;\r
477
- padding: 0 20px;\r
478
- border-bottom: 1px solid var(--tcw-border);\r
479
- }\r
480
- \r
481
- .tcw-modal-tab {\r
482
- padding: 10px 16px;\r
483
- font-size: 12px;\r
484
- font-weight: 500;\r
485
- color: var(--tcw-text-muted);\r
486
- border: none;\r
487
- background: none;\r
488
- cursor: pointer;\r
489
- border-bottom: 2px solid transparent;\r
490
- margin-bottom: -1px;\r
491
- transition: color var(--tcw-transition);\r
492
- font-family: inherit;\r
493
- text-transform: capitalize;\r
494
- }\r
495
- \r
496
- .tcw-modal-tab:hover {\r
497
- color: var(--tcw-text-dim);\r
498
- }\r
499
- \r
500
- .tcw-modal-tab.tcw-active {\r
501
- color: var(--tcw-accent);\r
502
- border-bottom-color: var(--tcw-accent);\r
503
- }\r
504
- \r
505
- .tcw-modal-body {\r
506
- padding: 20px;\r
507
- overflow-y: auto;\r
508
- flex: 1;\r
509
- }\r
510
- \r
511
- .tcw-settings-section {\r
512
- margin-bottom: 20px;\r
513
- }\r
514
- \r
515
- .tcw-settings-section:last-child {\r
516
- margin-bottom: 0;\r
517
- }\r
518
- \r
519
- .tcw-settings-section-title {\r
520
- font-size: 11px;\r
521
- font-weight: 600;\r
522
- text-transform: uppercase;\r
523
- letter-spacing: 0.05em;\r
524
- color: var(--tcw-text-muted);\r
525
- margin-bottom: 12px;\r
526
- }\r
527
- \r
528
- .tcw-settings-row {\r
529
- display: flex;\r
530
- align-items: center;\r
531
- justify-content: space-between;\r
532
- padding: 8px 0;\r
533
- }\r
534
- \r
535
- .tcw-settings-row + .tcw-settings-row {\r
536
- border-top: 1px solid rgba(255,255,255,0.03);\r
537
- }\r
538
- \r
539
- .tcw-root[data-tcw-theme="light"] .tcw-settings-row + .tcw-settings-row {\r
540
- border-top: 1px solid rgba(0,0,0,0.04);\r
541
- }\r
542
- \r
543
- .tcw-settings-label {\r
544
- font-size: 13px;\r
545
- color: var(--tcw-text-dim);\r
546
- }\r
547
- \r
548
- .tcw-color-picker-wrap {\r
549
- display: flex;\r
550
- align-items: center;\r
551
- gap: 6px;\r
552
- }\r
553
- \r
554
- .tcw-color-picker-wrap input[type='color'] {\r
555
- width: 28px;\r
556
- height: 28px;\r
557
- border: 1px solid var(--tcw-border);\r
558
- border-radius: 4px;\r
559
- background: none;\r
560
- cursor: pointer;\r
561
- padding: 2px;\r
562
- }\r
563
- \r
564
- .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper {\r
565
- padding: 0;\r
566
- }\r
567
- \r
568
- .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch {\r
569
- border: none;\r
570
- border-radius: 2px;\r
571
- }\r
572
- \r
573
- .tcw-color-hex {\r
574
- font-size: 11px;\r
575
- font-family: var(--tcw-font-mono);\r
576
- color: var(--tcw-text-muted);\r
577
- min-width: 60px;\r
578
- }\r
579
- \r
580
- .tcw-toggle {\r
581
- width: 36px;\r
582
- height: 20px;\r
583
- background: rgba(255,255,255,0.1);\r
584
- border-radius: 10px;\r
585
- position: relative;\r
586
- cursor: pointer;\r
587
- transition: background var(--tcw-transition);\r
588
- border: none;\r
589
- padding: 0;\r
590
- flex-shrink: 0;\r
591
- }\r
592
- \r
593
- .tcw-toggle::after {\r
594
- content: '';\r
595
- position: absolute;\r
596
- top: 2px;\r
597
- left: 2px;\r
598
- width: 16px;\r
599
- height: 16px;\r
600
- border-radius: 50%;\r
601
- background: var(--tcw-text-muted);\r
602
- transition: all var(--tcw-transition);\r
603
- }\r
604
- \r
605
- .tcw-toggle.tcw-on {\r
606
- background: var(--tcw-accent);\r
607
- }\r
608
- \r
609
- .tcw-toggle.tcw-on::after {\r
610
- left: 18px;\r
611
- background: white;\r
612
- }\r
613
- \r
614
- .tcw-root[data-tcw-theme="light"] .tcw-toggle {\r
615
- background: rgba(0,0,0,0.1);\r
616
- }\r
617
- \r
618
- .tcw-root[data-tcw-theme="light"] .tcw-toggle::after {\r
619
- background: #888;\r
620
- }\r
621
- \r
622
- .tcw-root[data-tcw-theme="light"] .tcw-toggle.tcw-on {\r
623
- background: var(--tcw-accent);\r
624
- }\r
625
- \r
626
- .tcw-root[data-tcw-theme="light"] .tcw-toggle.tcw-on::after {\r
627
- background: white;\r
628
- }\r
629
- \r
630
- .tcw-settings-select {\r
631
- padding: 4px 8px;\r
632
- font-size: 12px;\r
633
- font-family: inherit;\r
634
- background: var(--tcw-bg);\r
635
- border: 1px solid var(--tcw-border);\r
636
- border-radius: 4px;\r
637
- color: var(--tcw-text);\r
638
- cursor: pointer;\r
639
- }\r
640
- \r
641
- .tcw-modal-footer {\r
642
- display: flex;\r
643
- align-items: center;\r
644
- justify-content: space-between;\r
645
- padding: 12px 20px;\r
646
- border-top: 1px solid var(--tcw-border);\r
647
- }\r
648
- \r
649
- .tcw-reset-link {\r
650
- font-size: 12px;\r
651
- color: var(--tcw-text-muted);\r
652
- cursor: pointer;\r
653
- border: none;\r
654
- background: none;\r
655
- font-family: inherit;\r
656
- text-decoration: underline;\r
657
- text-underline-offset: 2px;\r
658
- transition: color var(--tcw-transition);\r
659
- }\r
660
- \r
661
- .tcw-reset-link:hover {\r
662
- color: var(--tcw-text-dim);\r
663
- }\r
664
- \r
665
- .tcw-done-btn {\r
666
- padding: 6px 16px;\r
667
- font-size: 12px;\r
668
- font-weight: 500;\r
669
- background: var(--tcw-accent);\r
670
- color: white;\r
671
- border: none;\r
672
- border-radius: 4px;\r
673
- cursor: pointer;\r
674
- font-family: inherit;\r
675
- transition: background var(--tcw-transition);\r
676
- }\r
677
- \r
678
- .tcw-done-btn:hover {\r
679
- background: #2563eb;\r
680
- }\r
681
- \r
682
- /* === Status Bar === */\r
683
- \r
684
- .tcw-statusbar {\r
685
- display: flex;\r
686
- align-items: center;\r
687
- justify-content: space-between;\r
688
- padding: 6px 16px;\r
689
- border-top: 1px solid var(--tcw-border);\r
690
- background: var(--tcw-bg-elevated);\r
691
- font-size: 11px;\r
692
- color: var(--tcw-text-muted);\r
693
- flex-shrink: 0;\r
694
- }\r
695
- \r
696
- .tcw-status-indicator {\r
697
- display: flex;\r
698
- align-items: center;\r
699
- gap: 6px;\r
700
- }\r
701
- \r
702
- .tcw-status-dot {\r
703
- width: 6px;\r
704
- height: 6px;\r
705
- border-radius: 50%;\r
706
- background: var(--tcw-text-muted);\r
707
- transition: background 0.3s;\r
708
- }\r
709
- \r
710
- .tcw-status-dot.tcw-connected {\r
711
- background: var(--tcw-green);\r
712
- }\r
713
- \r
714
- .tcw-status-dot.tcw-error {\r
715
- background: var(--tcw-red);\r
716
- }\r
717
- \r
718
- /* === Command Palette === */\r
719
- \r
720
- .tcw-cmd-palette {\r
721
- position: fixed;\r
722
- z-index: 102;\r
723
- top: 20%;\r
724
- left: 50%;\r
725
- transform: translateX(-50%);\r
726
- background: var(--tcw-bg-elevated);\r
727
- border: 1px solid var(--tcw-border);\r
728
- border-radius: var(--tcw-radius-lg);\r
729
- width: 520px;\r
730
- max-width: 90vw;\r
731
- max-height: 60vh;\r
732
- display: flex;\r
733
- flex-direction: column;\r
734
- box-shadow: 0 24px 64px rgba(0,0,0,0.5);\r
735
- overflow: hidden;\r
736
- }\r
737
- \r
738
- .tcw-cmd-header {\r
739
- display: flex;\r
740
- align-items: center;\r
741
- padding: 12px 16px;\r
742
- border-bottom: 1px solid var(--tcw-border);\r
743
- gap: 10px;\r
744
- }\r
745
- \r
746
- .tcw-cmd-icon {\r
747
- font-size: 18px;\r
748
- color: var(--tcw-text-muted);\r
749
- flex-shrink: 0;\r
750
- }\r
751
- \r
752
- .tcw-cmd-input {\r
753
- flex: 1;\r
754
- background: none;\r
755
- border: none;\r
756
- outline: none;\r
757
- font-size: 14px;\r
758
- font-family: inherit;\r
759
- color: var(--tcw-text);\r
760
- caret-color: var(--tcw-accent);\r
761
- }\r
762
- \r
763
- .tcw-cmd-input::placeholder {\r
764
- color: var(--tcw-text-muted);\r
765
- }\r
766
- \r
767
- .tcw-cmd-hint {\r
768
- font-size: 10px;\r
769
- color: var(--tcw-text-muted);\r
770
- border: 1px solid var(--tcw-border);\r
771
- padding: 2px 6px;\r
772
- border-radius: 3px;\r
773
- flex-shrink: 0;\r
774
- }\r
775
- \r
776
- .tcw-cmd-list {\r
777
- overflow-y: auto;\r
778
- flex: 1;\r
779
- padding: 4px 0;\r
780
- max-height: 360px;\r
781
- }\r
782
- \r
783
- .tcw-cmd-category {\r
784
- text-transform: uppercase;\r
785
- font-size: 10px;\r
786
- color: var(--tcw-text-muted);\r
787
- letter-spacing: 0.05em;\r
788
- padding: 8px 16px 4px;\r
789
- font-weight: 600;\r
790
- }\r
791
- \r
792
- .tcw-cmd-item {\r
793
- display: flex;\r
794
- align-items: center;\r
795
- justify-content: space-between;\r
796
- padding: 8px 16px;\r
797
- font-size: 13px;\r
798
- color: var(--tcw-text-dim);\r
799
- cursor: pointer;\r
800
- width: 100%;\r
801
- border: none;\r
802
- background: none;\r
803
- font-family: inherit;\r
804
- text-align: left;\r
805
- transition: background 80ms ease;\r
806
- gap: 8px;\r
807
- }\r
808
- \r
809
- .tcw-cmd-item:hover,\r
810
- .tcw-cmd-item.tcw-selected {\r
811
- background: var(--tcw-hover-bg);\r
812
- color: var(--tcw-text);\r
813
- }\r
814
- \r
815
- .tcw-cmd-item.tcw-active .tcw-cmd-item-label {\r
816
- color: var(--tcw-accent);\r
817
- }\r
818
- \r
819
- .tcw-cmd-item-label {\r
820
- flex: 1;\r
821
- }\r
822
- \r
823
- .tcw-cmd-check {\r
824
- color: var(--tcw-accent);\r
825
- font-size: 14px;\r
826
- font-weight: 600;\r
827
- }\r
828
- \r
829
- .tcw-cmd-kbd {\r
830
- font-size: 10px;\r
831
- font-family: var(--tcw-font-mono);\r
832
- color: var(--tcw-text-muted);\r
833
- background: var(--tcw-bg);\r
834
- border: 1px solid var(--tcw-border);\r
835
- padding: 1px 5px;\r
836
- border-radius: 3px;\r
837
- }\r
838
- \r
839
- .tcw-cmd-empty {\r
840
- padding: 24px 16px;\r
841
- text-align: center;\r
842
- color: var(--tcw-text-muted);\r
843
- font-size: 13px;\r
844
- }\r
845
- \r
846
- .tcw-cmd-footer {\r
847
- display: flex;\r
848
- align-items: center;\r
849
- gap: 16px;\r
850
- padding: 8px 16px;\r
851
- border-top: 1px solid var(--tcw-border);\r
852
- font-size: 11px;\r
853
- color: var(--tcw-text-muted);\r
854
- }\r
855
- \r
856
- /* === Responsive === */\r
857
- \r
858
- @media (max-width: 768px) {\r
859
- .tcw-toolbar {\r
860
- padding: 0 8px;\r
861
- height: 36px;\r
862
- }\r
863
- .tcw-toolbar-sep {\r
864
- display: none;\r
865
- }\r
866
- .tcw-indicator-chips {\r
867
- display: none;\r
868
- }\r
869
- .tcw-sidebar {\r
870
- width: 32px;\r
871
- }\r
872
- .tcw-sidebar-btn {\r
873
- width: 32px;\r
874
- height: 28px;\r
875
- }\r
876
- }\r
877
- `,u=0,d=`tcw-styles`;function f(){if(u++,u>1||document.getElementById(d))return;let e=document.createElement(`style`);e.id=d,e.textContent=l,document.head.appendChild(e)}function p(){if(u--,u>0)return;let e=document.getElementById(d);e&&e.remove()}var m={cursor:`<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>`,trendingUp:`<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>`,minus:`<path d="M5 12h14"/>`,penLine:`<path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/>`,hash:`<line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/>`,square:`<rect width="18" height="18" x="3" y="3" rx="2"/>`,gitBranch:`<line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>`,ruler:`<path d="M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z"/><path d="m14.5 12.5 2-2"/><path d="m11.5 9.5 2-2"/><path d="m8.5 6.5 2-2"/><path d="m17.5 15.5 2-2"/>`,type:`<polyline points="4 7 4 4 20 4 20 7"/><line x1="9" y1="20" x2="15" y2="20"/><line x1="12" y1="4" x2="12" y2="20"/>`,magnet:`<path d="m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15"/><path d="m5 8 4 4"/><path d="m12 15 4 4"/>`,undo:`<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>`,redo:`<path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"/>`,trash:`<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/>`,camera:`<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>`,settings:`<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>`,moon:`<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>`,sun:`<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>`,chevronDown:`<path d="m6 9 6 6 6-6"/>`,chevronUp:`<path d="m18 15-6-6-6 6"/>`,barChart:`<line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/>`,x:`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`,play:`<polygon points="6 3 20 12 6 21 6 3"/>`,pause:`<rect width="4" height="16" x="6" y="4"/><rect width="4" height="16" x="14" y="4"/>`,stop:`<rect width="14" height="14" x="5" y="5" rx="1"/>`,receipt:`<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"/><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"/><path d="M12 17.5v-11"/>`};function h(e,t=14){let n=m[e];return n?`<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`:``}var g=class{trigger;panel;_isOpen=!1;onOutsideClick;onEscapeKey;onTriggerClick;constructor(e,t={}){this.trigger=e,this.panel=document.createElement(`div`),this.panel.className=`tcw-dropdown`,this.panel.style.width=t.width??`200px`,t.align===`right`?this.panel.style.right=`0`:this.panel.style.left=`0`,this.panel.style.display=`none`,e.style.position=`relative`,e.appendChild(this.panel),this.onTriggerClick=()=>{this._isOpen?this.close():this.open()},this.onOutsideClick=e=>{this.trigger.contains(e.target)||this.close()},this.onEscapeKey=e=>{e.key===`Escape`&&this.close()},e.addEventListener(`click`,this.onTriggerClick)}setContent(e){this.panel.innerHTML=e}open(){this._isOpen||(this._isOpen=!0,this.panel.style.display=``,document.addEventListener(`mousedown`,this.onOutsideClick),document.addEventListener(`keydown`,this.onEscapeKey))}close(){this._isOpen&&(this._isOpen=!1,this.panel.style.display=`none`,document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey))}isOpen(){return this._isOpen}destroy(){this.trigger.removeEventListener(`click`,this.onTriggerClick),document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey),this.panel.remove()}},_=class{config;callbacks;el;chartTypeDropdown=null;indicatorDropdown=null;tfButtons=[];chipsContainer=null;themeBtn=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-toolbar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this,r=document.createElement(`button`);r.className=`tcw-toolbar-symbol`,r.dataset.role=`symbol`,r.addEventListener(`click`,t.onSymbolClick),n.appendChild(r),n.appendChild(this.sep());let i=document.createElement(`div`);i.className=`tcw-toolbar-group`;for(let n of e.timeframes){let e=document.createElement(`button`);e.className=`tcw-btn`,e.textContent=n.label,e.dataset.tf=n.value,e.addEventListener(`click`,()=>t.onTimeframe(n.value)),i.appendChild(e),this.tfButtons.push(e)}n.appendChild(i),n.appendChild(this.sep());let a=document.createElement(`div`);a.style.position=`relative`,a.style.display=`inline-flex`;let o=document.createElement(`button`);o.className=`tcw-dropdown-trigger`,o.dataset.role=`charttype`,a.appendChild(o),n.appendChild(a),this.chartTypeDropdown=new g(a,{width:`160px`}),this.buildChartTypeMenu(),n.appendChild(this.sep());let s=document.createElement(`div`);s.style.position=`relative`,s.style.display=`inline-flex`;let c=document.createElement(`button`);c.className=`tcw-dropdown-trigger`,c.dataset.role=`indicators`,s.appendChild(c),n.appendChild(s),this.indicatorDropdown=new g(s,{width:`280px`}),this.buildIndicatorMenu(),this.chipsContainer=document.createElement(`div`),this.chipsContainer.className=`tcw-indicator-chips`,n.appendChild(this.chipsContainer),n.appendChild(this.spacer());let l=this.iconBtn(`camera`,`Screenshot`,t.onScreenshot);n.appendChild(l);let u=this.iconBtn(`settings`,`Chart Settings`,t.onSettings);n.appendChild(u),this.themeBtn=this.iconBtn(`moon`,`Toggle theme`,t.onToggleTheme),this.themeBtn.dataset.role=`theme`,n.appendChild(this.themeBtn)}buildChartTypeMenu(){if(!this.chartTypeDropdown)return;let e=this.config.chartTypes.map(e=>`<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join(``);this.chartTypeDropdown.setContent(e),this.chartTypeDropdown.panel.querySelectorAll(`.tcw-dropdown-item`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ct;this.callbacks.onChartType(t),this.chartTypeDropdown?.close()})})}buildIndicatorMenu(){if(!this.indicatorDropdown)return;let{indicators:e,popularIndicatorIds:t}=this.config,n=e.filter(e=>t.includes(e.id)),r=e.filter(e=>!t.includes(e.id)),i=`<div class="tcw-dropdown-label">Popular</div>`;for(let e of n)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;i+=`<div class="tcw-dropdown-divider"></div>`,i+=`<div class="tcw-dropdown-label">All</div>`;for(let e of r)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;this.indicatorDropdown.setContent(i),this.indicatorDropdown.panel.querySelectorAll(`.tcw-dropdown-item[data-ind]`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ind;this.callbacks.onAddIndicator(t)})})}update(e){let t=this.el.querySelector(`[data-role="symbol"]`);t&&(t.textContent=e.symbol);for(let t of this.tfButtons)t.classList.toggle(`tcw-active`,t.dataset.tf===e.timeframe);let n=this.el.querySelector(`[data-role="charttype"]`);if(n){let t=this.config.chartTypes.find(t=>t.value===e.chartType)?.label??`Candles`;n.innerHTML=`${h(`barChart`,14)} ${t} ${h(`chevronDown`,12)}`}let r=this.el.querySelector(`[data-role="indicators"]`);if(r){let t=e.activeIndicators.size,n=`${h(`trendingUp`,14)} Indicators`;t>0&&(n+=` <span class="tcw-badge-count">${t}</span>`),r.innerHTML=n}if(this.chipsContainer){let t=this.getActiveIndicatorList(e);this.chipsContainer.innerHTML=``;for(let e of t){let t=document.createElement(`div`);t.className=`tcw-indicator-chip`;let n=document.createElement(`span`);n.textContent=e.label,t.appendChild(n);let r=document.createElement(`button`);r.className=`tcw-chip-remove`,r.innerHTML=h(`x`,10),r.addEventListener(`click`,()=>this.callbacks.onRemoveIndicator(e.instanceId)),t.appendChild(r),this.chipsContainer.appendChild(t)}}this.themeBtn&&(this.themeBtn.innerHTML=e.isDark?h(`moon`,14):h(`sun`,14))}getActiveIndicatorList(e){let t=[];for(let[n,r]of e.activeIndicators.entries())t.push({instanceId:r,id:n,label:n.toUpperCase()});return t}sep(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-sep`,e}spacer(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-spacer`,e}iconBtn(e,t,n){let r=document.createElement(`button`);return r.className=`tcw-btn-icon`,r.title=t,r.innerHTML=h(e,14),r.addEventListener(`click`,n),r}destroy(){this.chartTypeDropdown?.destroy(),this.indicatorDropdown?.destroy(),this.el.remove()}},v=[`trendingUp`,`minus`,`penLine`,`hash`,`square`,`gitBranch`,`ruler`,`type`],y=class{config;callbacks;el;groupWraps=[];groupButtons=[];cursorBtn=null;magnetBtn=null;flyoutEl=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-sidebar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this;this.cursorBtn=document.createElement(`button`),this.cursorBtn.className=`tcw-sidebar-btn`,this.cursorBtn.title=`Cursor`,this.cursorBtn.innerHTML=h(`cursor`,14),this.cursorBtn.addEventListener(`click`,t.onCancelDrawing),n.appendChild(this.cursorBtn),n.appendChild(this.divider()),e.drawingToolGroups.forEach((e,r)=>{let i=document.createElement(`div`);i.className=`tcw-tool-group-wrap`;let a=document.createElement(`button`);if(a.className=`tcw-sidebar-btn`,a.title=e.label,a.innerHTML=h(v[r]??`square`,14),e.tools.length>1){let e=document.createElement(`span`);e.className=`tcw-multi-dot`,a.appendChild(e)}a.addEventListener(`click`,()=>t.onDrawingTool(e.tools[0].value)),i.appendChild(a),i.addEventListener(`mouseenter`,()=>this.showFlyout(r)),i.addEventListener(`mouseleave`,()=>this.hideFlyout()),n.appendChild(i),this.groupWraps.push(i),this.groupButtons.push(a)});let r=document.createElement(`div`);r.className=`tcw-sidebar-spacer`,n.appendChild(r),n.appendChild(this.divider()),this.magnetBtn=document.createElement(`button`),this.magnetBtn.className=`tcw-sidebar-btn`,this.magnetBtn.title=`Magnet`,this.magnetBtn.innerHTML=h(`magnet`,14),this.magnetBtn.addEventListener(`click`,t.onToggleMagnet),n.appendChild(this.magnetBtn);let i=document.createElement(`button`);i.className=`tcw-sidebar-btn`,i.title=`Undo`,i.innerHTML=h(`undo`,14),i.addEventListener(`click`,t.onUndo),n.appendChild(i);let a=document.createElement(`button`);a.className=`tcw-sidebar-btn`,a.title=`Redo`,a.innerHTML=h(`redo`,14),a.addEventListener(`click`,t.onRedo),n.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-sidebar-btn tcw-danger`,o.title=`Clear all`,o.innerHTML=h(`trash`,14),o.addEventListener(`click`,t.onClearDrawings),n.appendChild(o)}showFlyout(e){let t=this.config.drawingToolGroups[e];if(!t||t.tools.length<=1)return;this.hideFlyout();let n=document.createElement(`div`);n.className=`tcw-flyout`;let r=document.createElement(`div`);r.className=`tcw-flyout-header`,r.textContent=t.label,n.appendChild(r);for(let e of t.tools){let t=document.createElement(`button`);t.className=`tcw-flyout-item`,t.textContent=e.label,t.dataset.toolValue=e.value,t.addEventListener(`click`,()=>{this.callbacks.onDrawingTool(e.value),this.hideFlyout()}),n.appendChild(t)}this.flyoutEl=n,this.groupWraps[e].appendChild(n)}hideFlyout(){this.flyoutEl&&=(this.flyoutEl.remove(),null)}update(e){this.cursorBtn&&this.cursorBtn.classList.toggle(`tcw-active`,e.activeTool===null);let{drawingToolGroups:t}=this.config;for(let n=0;n<t.length;n++){let r=t[n].tools.some(t=>t.value===e.activeTool);this.groupButtons[n].classList.toggle(`tcw-active`,r)}this.flyoutEl&&this.flyoutEl.querySelectorAll(`.tcw-flyout-item`).forEach(t=>{let n=t;n.classList.toggle(`tcw-active`,n.dataset.toolValue===e.activeTool)}),this.magnetBtn&&(this.magnetBtn.classList.toggle(`tcw-active`,e.magnetEnabled),this.magnetBtn.title=e.magnetEnabled?`Magnet ON`:`Magnet OFF`)}divider(){let e=document.createElement(`div`);return e.className=`tcw-sidebar-divider`,e}destroy(){this.hideFlyout(),this.el.remove()}},b=[`style`,`display`,`scale`],x=class{callbacks;backdrop=null;modal=null;currentTab=`style`;currentSettings=null;bodyEl=null;tabButtons=[];constructor(e){this.callbacks=e}open(e){this.currentSettings={...e},this.currentTab=`style`,this.buildModal()}close(){this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.bodyEl=null,this.tabButtons=[]}buildModal(){this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),document.body.appendChild(this.backdrop),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal`;let e=document.createElement(`div`);e.className=`tcw-modal-header`;let t=document.createElement(`h3`);t.textContent=`Chart Settings`,e.appendChild(t);let n=document.createElement(`button`);n.className=`tcw-modal-close`,n.innerHTML=h(`x`,16),n.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),e.appendChild(n),this.modal.appendChild(e);let r=document.createElement(`div`);r.className=`tcw-modal-tabs`,this.tabButtons=[];for(let e of b){let t=document.createElement(`button`);t.className=`tcw-modal-tab`,t.textContent=e,t.dataset.tab=e,e===this.currentTab&&t.classList.add(`tcw-active`),t.addEventListener(`click`,()=>{this.currentTab=e,this.tabButtons.forEach(t=>t.classList.toggle(`tcw-active`,t.dataset.tab===e)),this.renderTabContent()}),r.appendChild(t),this.tabButtons.push(t)}this.modal.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`,this.modal.appendChild(this.bodyEl),this.renderTabContent();let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.callbacks.onReset()),i.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),i.appendChild(o),this.modal.appendChild(i),document.body.appendChild(this.modal);let s=e=>{e.key===`Escape`&&(document.removeEventListener(`keydown`,s),this.callbacks.onClose(),this.close())};document.addEventListener(`keydown`,s)}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.innerHTML=``,this.currentTab){case`style`:this.renderStyleTab();break;case`display`:this.renderDisplayTab();break;case`scale`:this.renderScaleTab();break}}renderStyleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section(`Candle Colors`);t.appendChild(this.colorRow(`Up Body`,e.candleUpColor,e=>this.patch({candleUpColor:e}))),t.appendChild(this.colorRow(`Down Body`,e.candleDownColor,e=>this.patch({candleDownColor:e}))),t.appendChild(this.colorRow(`Up Wick`,e.candleUpWick,e=>this.patch({candleUpWick:e}))),t.appendChild(this.colorRow(`Down Wick`,e.candleDownWick,e=>this.patch({candleDownWick:e}))),this.bodyEl.appendChild(t);let n=this.section(`Background`);n.appendChild(this.colorRow(`Background`,e.backgroundColor,e=>this.patch({backgroundColor:e}))),n.appendChild(this.colorRow(`Grid`,e.gridColor,e=>this.patch({gridColor:e}))),this.bodyEl.appendChild(n)}renderDisplayTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Grid Lines`,e.gridVisible,e=>this.patch({gridVisible:e}))),t.appendChild(this.toggleRow(`Volume`,e.volumeVisible,e=>this.patch({volumeVisible:e}))),t.appendChild(this.toggleRow(`OHLC Legend`,e.legendVisible,e=>this.patch({legendVisible:e}))),t.appendChild(this.toggleRow(`Bar Countdown`,e.barCountdown,e=>this.patch({barCountdown:e}))),t.appendChild(this.selectRow(`Crosshair Mode`,e.crosshairMode,[{label:`Magnet`,value:`magnet`},{label:`Normal`,value:`normal`},{label:`Hidden`,value:`hidden`}],e=>this.patch({crosshairMode:e}))),t.appendChild(this.selectRow(`Number Locale`,e.numberLocale,[{label:`en-US (65,234.00)`,value:`en-US`},{label:`de-DE (65.234,00)`,value:`de-DE`},{label:`fr-FR (65 234,00)`,value:`fr-FR`},{label:`vi-VN (65.234,00)`,value:`vi-VN`},{label:`en-IN (65,234.00)`,value:`en-IN`},{label:`ja-JP (65,234.00)`,value:`ja-JP`}],e=>this.patch({numberLocale:e}))),this.bodyEl.appendChild(t)}renderScaleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Auto Scale`,e.autoScale,e=>this.patch({autoScale:e}))),t.appendChild(this.toggleRow(`Log Scale`,e.logScale,e=>this.patch({logScale:e}))),this.bodyEl.appendChild(t)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}section(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n)}return t}colorRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`div`);a.className=`tcw-color-picker-wrap`;let o=document.createElement(`input`);o.type=`color`,o.value=t;let s=document.createElement(`span`);return s.className=`tcw-color-hex`,s.textContent=t,o.addEventListener(`input`,()=>{s.textContent=o.value,n(o.value)}),a.appendChild(o),a.appendChild(s),r.appendChild(a),r}toggleRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`button`);return a.className=`tcw-toggle${t?` tcw-on`:``}`,a.addEventListener(`click`,()=>{let e=!a.classList.contains(`tcw-on`);a.classList.toggle(`tcw-on`,e),n(e)}),r.appendChild(a),r}selectRow(e,t,n,r){let i=document.createElement(`div`);i.className=`tcw-settings-row`;let a=document.createElement(`span`);a.className=`tcw-settings-label`,a.textContent=e,i.appendChild(a);let o=document.createElement(`select`);o.className=`tcw-settings-select`;for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),o.appendChild(n)}return o.addEventListener(`change`,()=>r(o.value)),i.appendChild(o),i}destroy(){this.close()}},S=class{el;dotEl;messageEl;infoEl;constructor(e){this.el=document.createElement(`div`),this.el.className=`tcw-statusbar`;let t=document.createElement(`div`);t.className=`tcw-status-indicator`,this.dotEl=document.createElement(`span`),this.dotEl.className=`tcw-status-dot`,t.appendChild(this.dotEl),this.messageEl=document.createElement(`span`),t.appendChild(this.messageEl),this.el.appendChild(t),this.infoEl=document.createElement(`span`),this.el.appendChild(this.infoEl),e.appendChild(this.el)}update(e){this.dotEl.className=`tcw-status-dot`,e.connectionState===`connected`?this.dotEl.classList.add(`tcw-connected`):e.connectionState===`error`&&this.dotEl.classList.add(`tcw-error`),this.messageEl.textContent=e.message,this.infoEl.textContent=`${e.symbol} ${e.timeframe}`}destroy(){this.el.remove()}},C=class{backdrop=null;modal=null;input=null;list=null;items=[];filtered=[];selectedIndex=0;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=this.handleKeydown.bind(this)}open(e){if(this.backdrop)return;this.items=e,this.filtered=e,this.selectedIndex=0,this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-cmd-palette`;let t=document.createElement(`div`);t.className=`tcw-cmd-header`;let n=document.createElement(`span`);n.className=`tcw-cmd-icon`,n.textContent=`⌕`,t.appendChild(n),this.input=document.createElement(`input`),this.input.className=`tcw-cmd-input`,this.input.type=`text`,this.input.placeholder=`Search indicators, chart types, tools...`,this.input.addEventListener(`input`,()=>this.filter()),t.appendChild(this.input);let r=document.createElement(`span`);r.className=`tcw-cmd-hint`,r.textContent=`ESC`,t.appendChild(r),this.modal.appendChild(t),this.list=document.createElement(`div`),this.list.className=`tcw-cmd-list`,this.modal.appendChild(this.list);let i=document.createElement(`div`);i.className=`tcw-cmd-footer`,i.innerHTML=`<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>`,this.modal.appendChild(i),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),this.renderList(),this.input.focus(),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.input=null,this.list=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}filter(){let e=this.input?.value.toLowerCase().trim()??``;e?this.filtered=this.items.filter(t=>t.label.toLowerCase().includes(e)||t.category.toLowerCase().includes(e)||t.id.toLowerCase().includes(e)):this.filtered=this.items,this.selectedIndex=0,this.renderList()}renderList(){if(!this.list)return;if(this.list.innerHTML=``,this.filtered.length===0){let e=document.createElement(`div`);e.className=`tcw-cmd-empty`,e.textContent=`No results found`,this.list.appendChild(e);return}let e=``;for(let t=0;t<this.filtered.length;t++){let n=this.filtered[t];if(n.category!==e){e=n.category;let t=document.createElement(`div`);t.className=`tcw-cmd-category`,t.textContent=this.categoryLabel(e),this.list.appendChild(t)}let r=document.createElement(`button`);r.className=`tcw-cmd-item`,t===this.selectedIndex&&r.classList.add(`tcw-selected`),n.active&&r.classList.add(`tcw-active`),r.dataset.index=String(t);let i=document.createElement(`span`);if(i.className=`tcw-cmd-item-label`,i.textContent=n.label,r.appendChild(i),n.active){let e=document.createElement(`span`);e.className=`tcw-cmd-check`,e.textContent=`✓`,r.appendChild(e)}if(n.shortcut){let e=document.createElement(`kbd`);e.className=`tcw-cmd-kbd`,e.textContent=n.shortcut,r.appendChild(e)}r.addEventListener(`click`,()=>this.select(t)),r.addEventListener(`mouseenter`,()=>{this.selectedIndex=t,this.updateSelection()}),this.list.appendChild(r)}}updateSelection(){if(!this.list)return;let e=this.list.querySelectorAll(`.tcw-cmd-item`);e.forEach((e,t)=>{e.classList.toggle(`tcw-selected`,t===this.selectedIndex)}),e[this.selectedIndex]?.scrollIntoView({block:`nearest`})}select(e){let t=this.filtered[e];if(t){switch(t.category){case`indicator`:this.callbacks.onIndicator(t.id);break;case`chartType`:this.callbacks.onChartType(t.id);break;case`drawing`:this.callbacks.onDrawingTool(t.id);break;case`timeframe`:this.callbacks.onTimeframe(t.id);break;case`action`:this.callbacks.onAction(t.id);break}this.close()}}handleKeydown(e){switch(e.key){case`Escape`:e.preventDefault(),this.close();break;case`ArrowDown`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex+1)%this.filtered.length,this.updateSelection());break;case`ArrowUp`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex-1+this.filtered.length)%this.filtered.length,this.updateSelection());break;case`Enter`:e.preventDefault(),this.select(this.selectedIndex);break}}categoryLabel(e){switch(e){case`indicator`:return`Indicators`;case`chartType`:return`Chart Types`;case`drawing`:return`Drawing Tools`;case`timeframe`:return`Timeframes`;case`action`:return`Actions`;default:return e}}destroy(){this.close()}},w=class{chart;state;toolbar=null;sidebar=null;settings=null;statusBar=null;commandPalette=null;root;chartContainer;destroyed=!1;options;symbolIndex=0;symbols;settingsState;adapter=null;boundGlobalKeydown=null;constructor(t,l={}){this.options=l,this.symbols=l.symbols??s,this.settingsState={...c};let u=this.resolveIsDark(l.theme),d=this.resolveTheme(l.theme);this.state={symbol:l.symbol??this.symbols[0]??`BTCUSDT`,timeframe:l.timeframe??`5m`,chartType:l.chartOptions?.chartType??`candlestick`,isDark:u,activeIndicators:new Map,activeTool:null,magnetEnabled:!0,connectionState:`connecting`,connectionMessage:`Connecting...`};let p=this.symbols.indexOf(this.state.symbol);p>=0&&(this.symbolIndex=p),f(),this.root=document.createElement(`div`),this.root.className=`tcw-root`,this.root.dataset.tcwTheme=u?`dark`:`light`,t.appendChild(this.root),l.toolbar!==!1&&(this.toolbar=new _(this.root,{symbols:this.symbols,timeframes:l.timeframes?n.filter(e=>l.timeframes.includes(e.value)):n,chartTypes:l.chartTypes?r.filter(e=>l.chartTypes.includes(e.value)):r,indicators:a,popularIndicatorIds:o},{onSymbolClick:()=>this.handleSymbolClick(),onTimeframe:e=>this.handleTimeframe(e),onChartType:e=>this.handleChartType(e),onAddIndicator:e=>this.handleAddIndicator(e),onRemoveIndicator:e=>this.handleRemoveIndicator(e),onScreenshot:()=>this.chart.screenshot(),onSettings:()=>this.openSettings(),onToggleTheme:()=>this.handleToggleTheme()}));let m=document.createElement(`div`);m.className=`tcw-body`,l.drawingTools!==!1&&(this.sidebar=new y(m,{drawingToolGroups:i},{onDrawingTool:e=>this.handleDrawingTool(e),onCancelDrawing:()=>this.handleCancelDrawing(),onToggleMagnet:()=>this.handleToggleMagnet(),onUndo:()=>this.chart.undo(),onRedo:()=>this.chart.redo(),onClearDrawings:()=>{this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI()}})),this.chartContainer=document.createElement(`div`),this.chartContainer.className=`tcw-chart-container`,m.appendChild(this.chartContainer),this.root.appendChild(m),this.chart=new e.t(this.chartContainer,{chartType:this.state.chartType,theme:d,autoScale:!0,crosshair:{mode:`magnet`},features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:l.trading!==!1,tradingContextMenu:l.trading!==!1,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0},...l.chartOptions}),l.statusBar!==!1&&(this.statusBar=new S(this.root)),l.settings!==!1&&(this.settings=new x({onChange:e=>this.applySettings(e),onReset:()=>this.resetSettings(),onClose:()=>{}})),this.commandPalette=new C({onIndicator:e=>this.handleAddIndicator(e),onChartType:e=>this.handleChartType(e),onDrawingTool:e=>this.handleDrawingTool(e),onTimeframe:e=>this.handleTimeframe(e),onAction:e=>this.handleAction(e),onClose:()=>{}}),this.boundGlobalKeydown=e=>{(e.ctrlKey||e.metaKey)&&e.key===`k`&&(e.preventDefault(),this.toggleCommandPalette())},document.addEventListener(`keydown`,this.boundGlobalKeydown),l.adapter&&(this.adapter=l.adapter,this.connectStream()),this.updateUI(),l.onReady?.(this.chart)}async setSymbol(e){this.state={...this.state,symbol:e};let t=this.symbols.indexOf(e);t>=0&&(this.symbolIndex=t),this.options.onSymbolChange?.(e),this.updateUI(),this.adapter&&await this.connectStream()}async setTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&await this.connectStream()}setTheme(e){let t=this.resolveIsDark(e),n=this.resolveTheme(e);this.state={...this.state,isDark:t},this.root.dataset.tcwTheme=t?`dark`:`light`,this.chart.setTheme(n),this.updateUI()}getChart(){return this.chart}destroy(){this.destroyed||(this.destroyed=!0,this.boundGlobalKeydown&&document.removeEventListener(`keydown`,this.boundGlobalKeydown),this.commandPalette?.destroy(),this.toolbar?.destroy(),this.sidebar?.destroy(),this.settings?.destroy(),this.statusBar?.destroy(),this.chart.destroy(),this.root.remove(),p())}handleSymbolClick(){this.symbolIndex=(this.symbolIndex+1)%this.symbols.length;let e=this.symbols[this.symbolIndex];this.state={...this.state,symbol:e},this.options.onSymbolChange?.(e),this.updateUI(),this.adapter&&this.connectStream()}handleTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&this.connectStream()}handleChartType(e){this.state={...this.state,chartType:e},this.chart.setChartType(e),this.updateUI()}handleAddIndicator(e){if(this.state.activeIndicators.has(e)){let t=this.state.activeIndicators.get(e);this.chart.removeIndicator(t);let n=new Map(this.state.activeIndicators);n.delete(e),this.state={...this.state,activeIndicators:n}}else{let t=this.chart.addIndicator(e);if(t){let n=new Map(this.state.activeIndicators);n.set(e,t),this.state={...this.state,activeIndicators:n}}}this.updateUI()}handleRemoveIndicator(e){this.chart.removeIndicator(e);let t=new Map(this.state.activeIndicators);for(let[n,r]of t.entries())if(r===e){t.delete(n);break}this.state={...this.state,activeIndicators:t},this.updateUI()}toggleCommandPalette(){if(this.commandPalette?.isOpen()){this.commandPalette.close();return}this.commandPalette?.open(this.buildCommandItems())}buildCommandItems(){let e=[];for(let t of a)e.push({id:t.id,label:t.name,category:`indicator`,active:this.state.activeIndicators.has(t.id)});for(let t of r)e.push({id:t.value,label:t.label,category:`chartType`,active:this.state.chartType===t.value});for(let t of i)for(let n of t.tools)e.push({id:n.value,label:n.label,category:`drawing`,active:this.state.activeTool===n.value});for(let t of n)e.push({id:t.value,label:t.label,category:`timeframe`,active:this.state.timeframe===t.value});return e.push({id:`screenshot`,label:`Screenshot`,category:`action`,shortcut:``},{id:`toggleTheme`,label:`Toggle Theme`,category:`action`},{id:`settings`,label:`Settings`,category:`action`},{id:`clearDrawings`,label:`Clear All Drawings`,category:`action`}),e}handleAction(e){switch(e){case`screenshot`:this.chart.screenshot();break;case`toggleTheme`:this.handleToggleTheme();break;case`settings`:this.openSettings();break;case`clearDrawings`:this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI();break}}handleDrawingTool(e){this.state={...this.state,activeTool:e},this.chart.setDrawingTool(e),this.updateUI()}handleCancelDrawing(){this.state={...this.state,activeTool:null},this.chart.setDrawingTool(null),this.updateUI()}handleToggleMagnet(){let e=!this.state.magnetEnabled;this.state={...this.state,magnetEnabled:e},this.chart.setDrawingMagnet(e),this.updateUI()}handleToggleTheme(){let e=!this.state.isDark;this.state={...this.state,isDark:e},this.root.dataset.tcwTheme=e?`dark`:`light`,this.chart.setTheme(e?t.DARK_THEME:t.LIGHT_THEME),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:e?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.updateUI()}openSettings(){this.settings?.open(this.settingsState)}applySettings(e){this.settingsState={...this.settingsState,...e},e.gridVisible!==void 0&&this.chart.setGridVisible(e.gridVisible),e.volumeVisible!==void 0&&this.chart.setVolumeVisible(e.volumeVisible),e.crosshairMode!==void 0&&this.chart.setCrosshairMode(e.crosshairMode),e.autoScale!==void 0&&this.chart.setAutoScale(e.autoScale),e.logScale!==void 0&&this.chart.setLogScale(e.logScale),e.numberLocale!==void 0&&this.chart.setNumberLocale(e.numberLocale);let t={...this.chart.getTheme()},n=!1;e.candleUpColor!==void 0&&(t.candleUp=e.candleUpColor,n=!0),e.candleDownColor!==void 0&&(t.candleDown=e.candleDownColor,n=!0),e.candleUpWick!==void 0&&(t.candleUpWick=e.candleUpWick,n=!0),e.candleDownWick!==void 0&&(t.candleDownWick=e.candleDownWick,n=!0),e.backgroundColor!==void 0&&(t.background=e.backgroundColor,n=!0),e.gridColor!==void 0&&(t.grid=e.gridColor,n=!0),n&&this.chart.setTheme(t)}resetSettings(){this.settingsState={...c},this.applySettings(this.settingsState)}async connectStream(){if(this.adapter){this.state={...this.state,connectionState:`connecting`,connectionMessage:`Connecting...`},this.updateUI();try{this.chart.disconnectStream(),await this.chart.connect({adapter:this.adapter,symbol:this.state.symbol,timeframe:this.state.timeframe,historyLimit:this.options.historyLimit??500}),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:this.state.isDark?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.state={...this.state,connectionState:`connected`,connectionMessage:`Live`}}catch(e){this.state={...this.state,connectionState:`error`,connectionMessage:e instanceof Error?e.message:`Connection failed`}}this.updateUI()}}updateUI(){this.toolbar?.update(this.state),this.sidebar?.update(this.state),this.statusBar?.update({connectionState:this.state.connectionState,message:this.state.connectionMessage,symbol:this.state.symbol,timeframe:this.state.timeframe})}resolveIsDark(e){return e===void 0||e===`dark`?!0:e===`light`?!1:typeof e==`object`&&e.background?this.isColorDark(e.background):!0}resolveTheme(e){return e===void 0||e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:typeof e==`object`?e:t.DARK_THEME}isColorDark(e){if(e.startsWith(`#`)&&e.length>=7){let t=parseInt(e.slice(1,3),16),n=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return t+n+r<384}return!0}};exports.ChartWidget=w;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../DragDropImporter-ycI_Tcs6.cjs`);let t=require(`@tradecanvas/commons`);function n(e,n,r={}){if(e.length===0)return[];let i=r.weekStartsOn??1,a=[],o=null,s=NaN;for(let r of e){let e=(0,t.timeframeBucketStart)(r.time,n,i);o===null||e!==s?(o!==null&&a.push(o),o={time:e,open:r.open,high:r.high,low:r.low,close:r.close,volume:r.volume},s=e):o={time:o.time,open:o.open,high:Math.max(o.high,r.high),low:Math.min(o.low,r.low),close:r.close,volume:o.volume+r.volume}}return o!==null&&a.push(o),a}function r(e){if(e.length<2)return 0;let t=[];for(let n=1;n<e.length;n++){let r=e[n].time-e[n-1].time;r>0&&t.push(r)}return t.length===0?0:(t.sort((e,t)=>e-t),t[Math.floor(t.length/2)])}var i=[{label:`1m`,value:`1m`},{label:`5m`,value:`5m`},{label:`15m`,value:`15m`},{label:`1H`,value:`1h`},{label:`4H`,value:`4h`},{label:`1D`,value:`1d`}],a=[{label:`Candlestick`,value:`candlestick`},{label:`Line`,value:`line`},{label:`Area`,value:`area`},{label:`Bar`,value:`bar`},{label:`Heikin-Ashi`,value:`heikinAshi`},{label:`Hollow Candle`,value:`hollowCandle`},{label:`Baseline`,value:`baseline`},{label:`Volume Candles`,value:`volumeCandles`},{label:`Equivolume`,value:`equivolume`},{label:`HLC Area`,value:`hlcArea`},{label:`Step Line`,value:`stepLine`},{label:`Line + Markers`,value:`lineWithMarkers`}],o=[{label:`Lines`,tools:[{label:`Trend Line`,value:`trendLine`},{label:`Ray`,value:`ray`},{label:`Extended Line`,value:`extendedLine`}]},{label:`Horizontal/Vertical`,tools:[{label:`Horizontal Line`,value:`horizontalLine`},{label:`Vertical Line`,value:`verticalLine`}]},{label:`Channels`,tools:[{label:`Parallel Channel`,value:`parallelChannel`},{label:`Regression Channel`,value:`regressionChannel`}]},{label:`Fibonacci`,tools:[{label:`Fib Retracement`,value:`fibRetracement`},{label:`Fib Extension`,value:`fibExtension`}]},{label:`Shapes`,tools:[{label:`Rectangle`,value:`rectangle`},{label:`Ellipse`,value:`ellipse`},{label:`Triangle`,value:`triangle`}]},{label:`Gann & Advanced`,tools:[{label:`Pitchfork`,value:`pitchfork`},{label:`Gann Fan`,value:`gannFan`},{label:`Gann Box`,value:`gannBox`},{label:`Elliott Wave`,value:`elliottWave`}]},{label:`Measure`,tools:[{label:`Price Range`,value:`priceRange`},{label:`Date Range`,value:`dateRange`},{label:`Measure`,value:`measure`}]},{label:`Annotation`,tools:[{label:`Text`,value:`text`},{label:`Arrow`,value:`arrow`}]}],s=[{id:`sma`,name:`SMA`,type:`overlay`},{id:`ema`,name:`EMA`,type:`overlay`},{id:`hma`,name:`Hull MA`,type:`overlay`},{id:`mtfma`,name:`MTF Moving Average`,type:`overlay`},{id:`bb`,name:`Bollinger Bands`,type:`overlay`},{id:`vwap`,name:`VWAP`,type:`overlay`},{id:`avwap`,name:`Anchored VWAP`,type:`overlay`},{id:`svwap`,name:`Session VWAP`,type:`overlay`},{id:`ichimoku`,name:`Ichimoku Cloud`,type:`overlay`},{id:`psar`,name:`Parabolic SAR`,type:`overlay`},{id:`supertrend`,name:`Supertrend`,type:`overlay`},{id:`keltner`,name:`Keltner Channel`,type:`overlay`},{id:`donchian`,name:`Donchian Channel`,type:`overlay`},{id:`pivots`,name:`Pivot Points`,type:`overlay`},{id:`zigzag`,name:`ZigZag`,type:`overlay`},{id:`lrc`,name:`Linear Regression Channel`,type:`overlay`},{id:`chandelier`,name:`Chandelier Exit`,type:`overlay`},{id:`alligator`,name:`Alligator`,type:`overlay`},{id:`rsi`,name:`RSI`,type:`panel`},{id:`macd`,name:`MACD`,type:`panel`},{id:`stochastic`,name:`Stochastic`,type:`panel`},{id:`atr`,name:`ATR`,type:`panel`},{id:`adx`,name:`ADX`,type:`panel`},{id:`obv`,name:`OBV`,type:`panel`},{id:`williamsR`,name:`Williams %R`,type:`panel`},{id:`cci`,name:`CCI`,type:`panel`},{id:`mfi`,name:`MFI`,type:`panel`},{id:`roc`,name:`ROC`,type:`panel`},{id:`tsi`,name:`TSI`,type:`panel`},{id:`cmf`,name:`CMF`,type:`panel`},{id:`aroon`,name:`Aroon`,type:`panel`},{id:`stddev`,name:`Std Deviation`,type:`panel`},{id:`vroc`,name:`Volume ROC`,type:`panel`},{id:`ad`,name:`Acc/Dist`,type:`panel`},{id:`ao`,name:`Awesome Oscillator`,type:`panel`},{id:`chaikinOsc`,name:`Chaikin Oscillator`,type:`panel`},{id:`voldelta`,name:`Volume Delta`,type:`panel`},{id:`vortex`,name:`Vortex Indicator`,type:`panel`},{id:`chop`,name:`Choppiness Index`,type:`panel`},{id:`uo`,name:`Ultimate Oscillator`,type:`panel`},{id:`fi`,name:`Force Index`,type:`panel`},{id:`crsi`,name:`Connors RSI`,type:`panel`},{id:`coppock`,name:`Coppock Curve`,type:`panel`},{id:`kst`,name:`Know Sure Thing`,type:`panel`},{id:`elderray`,name:`Elder Ray`,type:`panel`},{id:`stc`,name:`Schaff Trend Cycle`,type:`panel`},{id:`kvo`,name:`Klinger Oscillator`,type:`panel`},{id:`fisher`,name:`Fisher Transform`,type:`panel`},{id:`dpo`,name:`Detrended Price Osc`,type:`panel`},{id:`bop`,name:`Balance of Power`,type:`panel`},{id:`massindex`,name:`Mass Index`,type:`panel`},{id:`cmo`,name:`Chande Momentum`,type:`panel`},{id:`trix`,name:`TRIX`,type:`panel`},{id:`emv`,name:`Ease of Movement`,type:`panel`},{id:`pvt`,name:`Price Volume Trend`,type:`panel`},{id:`wad`,name:`Williams A/D`,type:`panel`},{id:`chaikinvol`,name:`Chaikin Volatility`,type:`panel`},{id:`rvi`,name:`Relative Vigor Index`,type:`panel`},{id:`stochrsi`,name:`Stochastic RSI`,type:`panel`},{id:`ppo`,name:`Percentage Price Oscillator`,type:`panel`},{id:`ac`,name:`Accelerator Oscillator`,type:`panel`},{id:`rmi`,name:`Relative Momentum Index`,type:`panel`},{id:`disparity`,name:`Disparity Index`,type:`panel`},{id:`qstick`,name:`Qstick`,type:`panel`},{id:`pgo`,name:`Pretty Good Oscillator`,type:`panel`},{id:`volumeProfile`,name:`Volume Profile`,type:`panel`}],c=[`sma`,`ema`,`bb`,`rsi`,`macd`,`stochastic`,`vwap`,`atr`,`obv`,`ichimoku`],l=[`BTCUSDT`,`ETHUSDT`,`SOLUSDT`,`BNBUSDT`],u={candleUpColor:`#26A69A`,candleDownColor:`#EF5350`,candleUpWick:`#26A69A`,candleDownWick:`#EF5350`,backgroundColor:`#131722`,gridColor:`#1E222D`,gridVisible:!0,volumeVisible:!0,volumeProfileVisible:!1,marketProfileVisible:!1,marketProfileSplit:!1,marketProfileLetters:!1,marketProfileBuckets:48,marketProfileOpacity:.32,depthHeatmapVisible:!1,depthHeatmapOpacity:.7,sessionShadingVisible:!1,pivotMarkersVisible:!1,pivotStrength:5,pivotStructureLabels:!1,periodLevelsVisible:!1,periodLevelsPeriod:`day`,legendVisible:!0,barCountdown:!0,logScale:!1,scaleMode:`regular`,autoScale:!0,crosshairMode:`magnet`,numberLocale:`en-US`,timezone:`local`},d=`/* === TradeCanvas Widget — Premium Styles === */
2
+
3
+ .tcw-root {
4
+ display: flex;
5
+ flex-direction: column;
6
+ width: 100%;
7
+ height: 100%;
8
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;
9
+ font-feature-settings: 'cv11', 'ss01', 'ss03';
10
+ font-size: 13px;
11
+ line-height: 1.4;
12
+ color: #d1d4dc;
13
+ background: #0d0f17;
14
+ position: relative;
15
+ overflow: hidden;
16
+ -webkit-font-smoothing: antialiased;
17
+ -moz-osx-font-smoothing: grayscale;
18
+
19
+ /* --- Dark theme tokens (default) --- */
20
+ --tcw-bg: #0d0f17;
21
+ --tcw-bg-surface: #131722;
22
+ --tcw-bg-elevated: #1a1e2d;
23
+ --tcw-bg-overlay: #20253480;
24
+ --tcw-border: #2a2e39;
25
+ --tcw-border-strong: #363a45;
26
+ --tcw-text: #e9ebf0;
27
+ --tcw-text-dim: #b2b5be;
28
+ --tcw-text-muted: #6b6f7a;
29
+
30
+ --tcw-accent: #4f88ff;
31
+ --tcw-accent-hover: #6b9aff;
32
+ --tcw-accent-soft: rgba(79, 136, 255, 0.14);
33
+ --tcw-accent-glow: rgba(79, 136, 255, 0.22);
34
+ --tcw-accent-line: rgba(79, 136, 255, 0.55);
35
+
36
+ --tcw-red: #f23645;
37
+ --tcw-red-soft: rgba(242, 54, 69, 0.12);
38
+ --tcw-green: #26a17b;
39
+ --tcw-green-soft: rgba(38, 161, 123, 0.12);
40
+ --tcw-amber: #ff9f43;
41
+
42
+ --tcw-hover-bg: rgba(255, 255, 255, 0.05);
43
+ --tcw-active-bg: rgba(255, 255, 255, 0.08);
44
+ --tcw-divider: rgba(255, 255, 255, 0.06);
45
+
46
+ /* Motion */
47
+ --tcw-ease: cubic-bezier(0.2, 0, 0, 1);
48
+ --tcw-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
49
+ --tcw-dur-fast: 120ms;
50
+ --tcw-dur-normal: 180ms;
51
+ --tcw-dur-slow: 260ms;
52
+
53
+ /* Shape */
54
+ --tcw-radius-sm: 4px;
55
+ --tcw-radius: 6px;
56
+ --tcw-radius-lg: 10px;
57
+ --tcw-radius-xl: 14px;
58
+
59
+ /* Elevation */
60
+ --tcw-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
61
+ --tcw-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.2);
62
+ --tcw-shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3);
63
+ --tcw-shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.55), 0 12px 24px rgba(0, 0, 0, 0.35);
64
+ --tcw-ring: 0 0 0 2px rgba(79, 136, 255, 0.45);
65
+
66
+ /* Type */
67
+ --tcw-font-mono: 'JetBrains Mono', 'SF Mono', 'Cascadia Code', 'Fira Code', 'Consolas', ui-monospace, monospace;
68
+ }
69
+
70
+ .tcw-root[data-tcw-theme='light'] {
71
+ color: #131722;
72
+ background: #fcfcfd;
73
+
74
+ --tcw-bg: #fcfcfd;
75
+ --tcw-bg-surface: #ffffff;
76
+ --tcw-bg-elevated: #ffffff;
77
+ --tcw-bg-overlay: rgba(255, 255, 255, 0.75);
78
+ --tcw-border: #e7e9ef;
79
+ --tcw-border-strong: #d4d7e0;
80
+ --tcw-text: #131722;
81
+ --tcw-text-dim: #50545e;
82
+ --tcw-text-muted: #8b8f99;
83
+
84
+ --tcw-accent: #2962ff;
85
+ --tcw-accent-hover: #1e4fd6;
86
+ --tcw-accent-soft: rgba(41, 98, 255, 0.10);
87
+ --tcw-accent-glow: rgba(41, 98, 255, 0.16);
88
+ --tcw-accent-line: rgba(41, 98, 255, 0.45);
89
+
90
+ --tcw-hover-bg: rgba(0, 0, 0, 0.04);
91
+ --tcw-active-bg: rgba(41, 98, 255, 0.08);
92
+ --tcw-divider: rgba(0, 0, 0, 0.06);
93
+
94
+ --tcw-shadow-sm: 0 1px 2px rgba(20, 28, 56, 0.05);
95
+ --tcw-shadow-md: 0 4px 12px rgba(20, 28, 56, 0.08), 0 1px 3px rgba(20, 28, 56, 0.04);
96
+ --tcw-shadow-lg: 0 12px 36px rgba(20, 28, 56, 0.14), 0 4px 12px rgba(20, 28, 56, 0.08);
97
+ --tcw-shadow-xl: 0 24px 64px rgba(20, 28, 56, 0.18), 0 12px 24px rgba(20, 28, 56, 0.1);
98
+ }
99
+
100
+ /* === Toolbar === */
101
+
102
+ .tcw-toolbar {
103
+ display: flex;
104
+ align-items: center;
105
+ gap: 0;
106
+ padding: 0 10px;
107
+ height: 44px;
108
+ border-bottom: 1px solid var(--tcw-border);
109
+ background:
110
+ linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);
111
+ flex-shrink: 0;
112
+ position: relative;
113
+ z-index: 20;
114
+ box-shadow: var(--tcw-shadow-sm);
115
+ }
116
+
117
+ .tcw-toolbar-symbol {
118
+ font-size: 14px;
119
+ font-weight: 650;
120
+ color: var(--tcw-text);
121
+ padding: 6px 12px;
122
+ white-space: nowrap;
123
+ letter-spacing: -0.015em;
124
+ cursor: pointer;
125
+ border: none;
126
+ background: transparent;
127
+ font-family: inherit;
128
+ border-radius: var(--tcw-radius);
129
+ transition: background var(--tcw-dur-fast) var(--tcw-ease);
130
+ }
131
+
132
+ .tcw-toolbar-symbol:hover {
133
+ background: var(--tcw-hover-bg);
134
+ }
135
+
136
+ .tcw-toolbar-sep {
137
+ width: 1px;
138
+ height: 22px;
139
+ background: var(--tcw-border);
140
+ flex-shrink: 0;
141
+ margin: 0 4px;
142
+ }
143
+
144
+ .tcw-toolbar-group {
145
+ display: flex;
146
+ align-items: center;
147
+ gap: 2px;
148
+ padding: 0 4px;
149
+ }
150
+
151
+ .tcw-toolbar-spacer {
152
+ flex: 1;
153
+ }
154
+
155
+ .tcw-btn {
156
+ padding: 6px 10px;
157
+ font-size: 12px;
158
+ font-weight: 500;
159
+ font-family: inherit;
160
+ border: none;
161
+ border-radius: var(--tcw-radius);
162
+ background: transparent;
163
+ color: var(--tcw-text-dim);
164
+ cursor: pointer;
165
+ transition:
166
+ background var(--tcw-dur-fast) var(--tcw-ease),
167
+ color var(--tcw-dur-fast) var(--tcw-ease),
168
+ transform var(--tcw-dur-fast) var(--tcw-ease);
169
+ white-space: nowrap;
170
+ line-height: 1;
171
+ letter-spacing: -0.005em;
172
+ }
173
+
174
+ .tcw-btn:hover {
175
+ background: var(--tcw-hover-bg);
176
+ color: var(--tcw-text);
177
+ }
178
+
179
+ .tcw-btn:active {
180
+ transform: translateY(0.5px);
181
+ }
182
+
183
+ .tcw-btn.tcw-active {
184
+ background: var(--tcw-accent-soft);
185
+ color: var(--tcw-accent);
186
+ font-weight: 600;
187
+ box-shadow: inset 0 0 0 1px var(--tcw-accent-line);
188
+ }
189
+
190
+ .tcw-btn:focus-visible,
191
+ .tcw-btn-icon:focus-visible,
192
+ .tcw-sidebar-btn:focus-visible,
193
+ .tcw-dropdown-trigger:focus-visible {
194
+ outline: none;
195
+ box-shadow: var(--tcw-ring);
196
+ }
197
+
198
+ .tcw-btn-icon {
199
+ width: 32px;
200
+ height: 32px;
201
+ display: inline-flex;
202
+ align-items: center;
203
+ justify-content: center;
204
+ font-family: inherit;
205
+ border: none;
206
+ border-radius: var(--tcw-radius);
207
+ background: transparent;
208
+ color: var(--tcw-text-muted);
209
+ cursor: pointer;
210
+ transition:
211
+ background var(--tcw-dur-fast) var(--tcw-ease),
212
+ color var(--tcw-dur-fast) var(--tcw-ease);
213
+ line-height: 1;
214
+ position: relative;
215
+ }
216
+
217
+ .tcw-btn-icon:hover {
218
+ background: var(--tcw-hover-bg);
219
+ color: var(--tcw-text);
220
+ }
221
+
222
+ .tcw-btn-icon svg {
223
+ display: block;
224
+ }
225
+
226
+ .tcw-badge-count {
227
+ font-size: 10px;
228
+ font-weight: 600;
229
+ color: var(--tcw-accent);
230
+ background: var(--tcw-accent-soft);
231
+ padding: 1px 5px;
232
+ border-radius: 9px;
233
+ font-family: var(--tcw-font-mono);
234
+ }
235
+
236
+ .tcw-indicator-chips {
237
+ display: flex;
238
+ align-items: center;
239
+ gap: 4px;
240
+ padding: 0 4px;
241
+ flex-wrap: nowrap;
242
+ overflow: hidden;
243
+ }
244
+
245
+ .tcw-indicator-chip {
246
+ display: inline-flex;
247
+ align-items: center;
248
+ gap: 4px;
249
+ padding: 3px 6px 3px 9px;
250
+ font-size: 11px;
251
+ font-weight: 500;
252
+ background: var(--tcw-accent-soft);
253
+ color: var(--tcw-accent);
254
+ border-radius: 9999px;
255
+ white-space: nowrap;
256
+ line-height: 1.4;
257
+ letter-spacing: -0.005em;
258
+ border: 1px solid transparent;
259
+ transition: border-color var(--tcw-dur-fast) var(--tcw-ease);
260
+ }
261
+
262
+ .tcw-indicator-chip:hover {
263
+ border-color: var(--tcw-accent-line);
264
+ }
265
+
266
+ .tcw-chip-remove {
267
+ cursor: pointer;
268
+ opacity: 0.55;
269
+ padding: 0 2px;
270
+ transition: opacity var(--tcw-dur-fast) var(--tcw-ease);
271
+ border: none;
272
+ background: transparent;
273
+ color: inherit;
274
+ display: inline-flex;
275
+ align-items: center;
276
+ }
277
+
278
+ .tcw-chip-remove:hover {
279
+ opacity: 1;
280
+ }
281
+
282
+ /* === Dropdown === */
283
+
284
+ .tcw-dropdown-trigger {
285
+ display: inline-flex;
286
+ align-items: center;
287
+ gap: 4px;
288
+ padding: 6px 10px;
289
+ font-size: 12px;
290
+ font-weight: 500;
291
+ font-family: inherit;
292
+ border: none;
293
+ border-radius: var(--tcw-radius);
294
+ background: transparent;
295
+ color: var(--tcw-text-dim);
296
+ cursor: pointer;
297
+ transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);
298
+ white-space: nowrap;
299
+ line-height: 1;
300
+ }
301
+
302
+ .tcw-dropdown-trigger:hover {
303
+ background: var(--tcw-hover-bg);
304
+ color: var(--tcw-text);
305
+ }
306
+
307
+ .tcw-dropdown {
308
+ position: absolute;
309
+ top: 100%;
310
+ margin-top: 6px;
311
+ background: var(--tcw-bg-elevated);
312
+ border: 1px solid var(--tcw-border);
313
+ border-radius: var(--tcw-radius-lg);
314
+ box-shadow: var(--tcw-shadow-lg);
315
+ z-index: 50;
316
+ padding: 6px;
317
+ max-height: 420px;
318
+ overflow-y: auto;
319
+ backdrop-filter: blur(12px);
320
+ -webkit-backdrop-filter: blur(12px);
321
+ animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);
322
+ }
323
+
324
+ @keyframes tcw-pop-in {
325
+ from { opacity: 0; transform: translateY(-4px) scale(0.98); }
326
+ to { opacity: 1; transform: translateY(0) scale(1); }
327
+ }
328
+
329
+ .tcw-dropdown-item {
330
+ display: flex;
331
+ align-items: center;
332
+ justify-content: space-between;
333
+ padding: 7px 10px;
334
+ font-size: 12.5px;
335
+ color: var(--tcw-text-dim);
336
+ cursor: pointer;
337
+ transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);
338
+ width: 100%;
339
+ border: none;
340
+ background: transparent;
341
+ font-family: inherit;
342
+ text-align: left;
343
+ border-radius: var(--tcw-radius-sm);
344
+ gap: 12px;
345
+ }
346
+
347
+ .tcw-dropdown-item:hover {
348
+ background: var(--tcw-hover-bg);
349
+ color: var(--tcw-text);
350
+ }
351
+
352
+ .tcw-dropdown-item.tcw-active {
353
+ color: var(--tcw-accent);
354
+ background: var(--tcw-accent-soft);
355
+ font-weight: 600;
356
+ }
357
+
358
+ .tcw-dropdown-label {
359
+ text-transform: uppercase;
360
+ font-size: 10px;
361
+ color: var(--tcw-text-muted);
362
+ letter-spacing: 0.08em;
363
+ padding: 8px 10px 4px;
364
+ font-weight: 600;
365
+ }
366
+
367
+ .tcw-dropdown-divider {
368
+ border-top: 1px solid var(--tcw-divider);
369
+ margin: 6px 4px;
370
+ }
371
+
372
+ .tcw-tag {
373
+ font-size: 10px;
374
+ font-family: var(--tcw-font-mono);
375
+ color: var(--tcw-text-muted);
376
+ padding: 2px 6px;
377
+ border-radius: 4px;
378
+ background: var(--tcw-hover-bg);
379
+ letter-spacing: 0.02em;
380
+ }
381
+
382
+ /* === Body === */
383
+
384
+ .tcw-body {
385
+ display: flex;
386
+ flex: 1;
387
+ min-height: 0;
388
+ background: var(--tcw-bg);
389
+ }
390
+
391
+ .tcw-chart-container {
392
+ flex: 1;
393
+ min-width: 0;
394
+ min-height: 0;
395
+ width: 100%;
396
+ height: 100%;
397
+ position: relative;
398
+ }
399
+
400
+ /* === Sidebar === */
401
+
402
+ .tcw-sidebar {
403
+ width: 40px;
404
+ flex-shrink: 0;
405
+ background: linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);
406
+ border-right: 1px solid var(--tcw-border);
407
+ display: flex;
408
+ flex-direction: column;
409
+ align-items: center;
410
+ padding: 6px 0;
411
+ overflow: visible;
412
+ box-shadow: var(--tcw-shadow-sm);
413
+ }
414
+
415
+ .tcw-tool-group-wrap {
416
+ position: relative;
417
+ }
418
+
419
+ .tcw-sidebar-btn {
420
+ width: 32px;
421
+ height: 32px;
422
+ margin: 1px 0;
423
+ display: flex;
424
+ align-items: center;
425
+ justify-content: center;
426
+ border: none;
427
+ background: transparent;
428
+ color: var(--tcw-text-muted);
429
+ cursor: pointer;
430
+ font-family: inherit;
431
+ transition:
432
+ background var(--tcw-dur-fast) var(--tcw-ease),
433
+ color var(--tcw-dur-fast) var(--tcw-ease);
434
+ position: relative;
435
+ flex-shrink: 0;
436
+ line-height: 1;
437
+ border-radius: var(--tcw-radius);
438
+ }
439
+
440
+ .tcw-sidebar-btn:hover {
441
+ color: var(--tcw-text);
442
+ background: var(--tcw-hover-bg);
443
+ }
444
+
445
+ .tcw-sidebar-btn.tcw-active {
446
+ color: var(--tcw-accent);
447
+ background: var(--tcw-accent-soft);
448
+ box-shadow: inset 2px 0 0 var(--tcw-accent);
449
+ }
450
+
451
+ .tcw-sidebar-btn.tcw-danger:hover {
452
+ color: var(--tcw-red);
453
+ background: var(--tcw-red-soft);
454
+ }
455
+
456
+ .tcw-multi-dot {
457
+ position: absolute;
458
+ bottom: 3px;
459
+ right: 3px;
460
+ width: 4px;
461
+ height: 4px;
462
+ border-radius: 50%;
463
+ background: var(--tcw-text-muted);
464
+ opacity: 0.7;
465
+ }
466
+
467
+ .tcw-sidebar-divider {
468
+ width: 22px;
469
+ height: 1px;
470
+ background: var(--tcw-divider);
471
+ margin: 6px 0;
472
+ flex-shrink: 0;
473
+ }
474
+
475
+ .tcw-sidebar-spacer {
476
+ flex: 1;
477
+ }
478
+
479
+ /* === Flyout === */
480
+
481
+ .tcw-flyout {
482
+ position: absolute;
483
+ left: 100%;
484
+ top: 0;
485
+ margin-left: 6px;
486
+ min-width: 180px;
487
+ background: var(--tcw-bg-elevated);
488
+ border: 1px solid var(--tcw-border);
489
+ border-radius: var(--tcw-radius-lg);
490
+ box-shadow: var(--tcw-shadow-lg);
491
+ z-index: 30;
492
+ padding: 6px;
493
+ backdrop-filter: blur(12px);
494
+ -webkit-backdrop-filter: blur(12px);
495
+ animation: tcw-slide-right var(--tcw-dur-normal) var(--tcw-ease-out);
496
+ }
497
+
498
+ @keyframes tcw-slide-right {
499
+ from { opacity: 0; transform: translateX(-4px); }
500
+ to { opacity: 1; transform: translateX(0); }
501
+ }
502
+
503
+ .tcw-flyout-header {
504
+ text-transform: uppercase;
505
+ font-size: 10px;
506
+ color: var(--tcw-text-muted);
507
+ letter-spacing: 0.08em;
508
+ padding: 6px 10px 4px;
509
+ font-weight: 600;
510
+ }
511
+
512
+ .tcw-flyout-item {
513
+ padding: 7px 10px;
514
+ font-size: 12.5px;
515
+ color: var(--tcw-text-dim);
516
+ cursor: pointer;
517
+ width: 100%;
518
+ display: block;
519
+ border: none;
520
+ background: transparent;
521
+ text-align: left;
522
+ font-family: inherit;
523
+ border-radius: var(--tcw-radius-sm);
524
+ transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);
525
+ }
526
+
527
+ .tcw-flyout-item:hover {
528
+ background: var(--tcw-hover-bg);
529
+ color: var(--tcw-text);
530
+ }
531
+
532
+ .tcw-flyout-item.tcw-active {
533
+ color: var(--tcw-accent);
534
+ background: var(--tcw-accent-soft);
535
+ font-weight: 600;
536
+ }
537
+
538
+ /* Pinned (favorited) flyout item — a star marker on the right. */
539
+ .tcw-flyout-item.tcw-flyout-faved::after {
540
+ content: '★';
541
+ float: right;
542
+ color: var(--tcw-accent);
543
+ font-size: 11px;
544
+ line-height: 1.4;
545
+ }
546
+
547
+ /* Favorites strip — pinned drawing tools above the tool groups. */
548
+ .tcw-sidebar-favorites {
549
+ display: flex;
550
+ flex-direction: column;
551
+ gap: 2px;
552
+ }
553
+ .tcw-sidebar-favorites .tcw-sidebar-btn {
554
+ position: relative;
555
+ }
556
+ .tcw-sidebar-favorites .tcw-sidebar-btn::before {
557
+ content: '';
558
+ position: absolute;
559
+ top: 3px;
560
+ right: 3px;
561
+ width: 4px;
562
+ height: 4px;
563
+ border-radius: 50%;
564
+ background: var(--tcw-accent);
565
+ opacity: 0.7;
566
+ }
567
+
568
+ /* === Modal === */
569
+
570
+ .tcw-modal-backdrop {
571
+ position: fixed;
572
+ inset: 0;
573
+ background: rgba(8, 10, 18, 0.55);
574
+ backdrop-filter: blur(6px) saturate(140%);
575
+ -webkit-backdrop-filter: blur(6px) saturate(140%);
576
+ z-index: 100;
577
+ animation: tcw-fade-in var(--tcw-dur-normal) var(--tcw-ease-out);
578
+ }
579
+
580
+ @keyframes tcw-fade-in {
581
+ from { opacity: 0; }
582
+ to { opacity: 1; }
583
+ }
584
+
585
+ .tcw-modal {
586
+ position: fixed;
587
+ z-index: 101;
588
+ top: 50%;
589
+ left: 50%;
590
+ transform: translate(-50%, -50%);
591
+ background: var(--tcw-bg-elevated);
592
+ border: 1px solid var(--tcw-border);
593
+ border-radius: var(--tcw-radius-xl);
594
+ width: 520px;
595
+ max-width: 92vw;
596
+ max-height: 82vh;
597
+ display: flex;
598
+ flex-direction: column;
599
+ box-shadow: var(--tcw-shadow-xl);
600
+ animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);
601
+ }
602
+
603
+ @keyframes tcw-modal-in {
604
+ from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
605
+ to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
606
+ }
607
+
608
+ .tcw-modal-header {
609
+ display: flex;
610
+ align-items: center;
611
+ justify-content: space-between;
612
+ padding: 18px 22px;
613
+ border-bottom: 1px solid var(--tcw-divider);
614
+ }
615
+
616
+ .tcw-modal-header h3 {
617
+ font-size: 15px;
618
+ font-weight: 650;
619
+ margin: 0;
620
+ color: var(--tcw-text);
621
+ letter-spacing: -0.015em;
622
+ }
623
+
624
+ .tcw-modal-close {
625
+ width: 28px;
626
+ height: 28px;
627
+ display: flex;
628
+ align-items: center;
629
+ justify-content: center;
630
+ border: none;
631
+ background: transparent;
632
+ color: var(--tcw-text-muted);
633
+ cursor: pointer;
634
+ border-radius: var(--tcw-radius);
635
+ transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);
636
+ }
637
+
638
+ .tcw-modal-close:hover {
639
+ background: var(--tcw-hover-bg);
640
+ color: var(--tcw-text);
641
+ }
642
+
643
+ .tcw-modal-tabs {
644
+ display: flex;
645
+ gap: 4px;
646
+ padding: 0 18px;
647
+ border-bottom: 1px solid var(--tcw-divider);
648
+ }
649
+
650
+ .tcw-modal-tab {
651
+ padding: 11px 14px;
652
+ font-size: 12px;
653
+ font-weight: 500;
654
+ color: var(--tcw-text-muted);
655
+ border: none;
656
+ background: transparent;
657
+ cursor: pointer;
658
+ border-bottom: 2px solid transparent;
659
+ margin-bottom: -1px;
660
+ transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);
661
+ font-family: inherit;
662
+ text-transform: capitalize;
663
+ letter-spacing: -0.005em;
664
+ }
665
+
666
+ .tcw-modal-tab:hover {
667
+ color: var(--tcw-text-dim);
668
+ }
669
+
670
+ .tcw-modal-tab.tcw-active {
671
+ color: var(--tcw-accent);
672
+ border-bottom-color: var(--tcw-accent);
673
+ font-weight: 600;
674
+ }
675
+
676
+ .tcw-modal-body {
677
+ padding: 20px 22px;
678
+ overflow-y: auto;
679
+ flex: 1;
680
+ }
681
+
682
+ .tcw-settings-section {
683
+ margin-bottom: 22px;
684
+ }
685
+
686
+ .tcw-settings-section:last-child {
687
+ margin-bottom: 0;
688
+ }
689
+
690
+ .tcw-settings-section-title {
691
+ font-size: 10.5px;
692
+ font-weight: 600;
693
+ text-transform: uppercase;
694
+ letter-spacing: 0.09em;
695
+ color: var(--tcw-text-muted);
696
+ margin-bottom: 12px;
697
+ }
698
+
699
+ .tcw-settings-row {
700
+ display: flex;
701
+ align-items: center;
702
+ justify-content: space-between;
703
+ padding: 10px 0;
704
+ }
705
+
706
+ .tcw-settings-row + .tcw-settings-row {
707
+ border-top: 1px solid var(--tcw-divider);
708
+ }
709
+
710
+ .tcw-settings-label {
711
+ font-size: 13px;
712
+ color: var(--tcw-text-dim);
713
+ letter-spacing: -0.005em;
714
+ }
715
+
716
+ .tcw-color-picker-wrap {
717
+ display: flex;
718
+ align-items: center;
719
+ gap: 8px;
720
+ }
721
+
722
+ .tcw-color-picker-wrap input[type='color'] {
723
+ width: 28px;
724
+ height: 28px;
725
+ border: 1px solid var(--tcw-border-strong);
726
+ border-radius: var(--tcw-radius-sm);
727
+ background: transparent;
728
+ cursor: pointer;
729
+ padding: 2px;
730
+ }
731
+
732
+ .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper {
733
+ padding: 0;
734
+ }
735
+
736
+ .tcw-color-picker-wrap input[type='color']::-webkit-color-swatch {
737
+ border: none;
738
+ border-radius: 2px;
739
+ }
740
+
741
+ .tcw-color-hex {
742
+ font-size: 11px;
743
+ font-family: var(--tcw-font-mono);
744
+ color: var(--tcw-text-muted);
745
+ min-width: 64px;
746
+ letter-spacing: 0.01em;
747
+ }
748
+
749
+ .tcw-toggle {
750
+ width: 36px;
751
+ height: 20px;
752
+ background: rgba(255, 255, 255, 0.12);
753
+ border-radius: 10px;
754
+ position: relative;
755
+ cursor: pointer;
756
+ transition: background var(--tcw-dur-fast) var(--tcw-ease);
757
+ border: none;
758
+ padding: 0;
759
+ flex-shrink: 0;
760
+ }
761
+
762
+ .tcw-toggle::after {
763
+ content: '';
764
+ position: absolute;
765
+ top: 2px;
766
+ left: 2px;
767
+ width: 16px;
768
+ height: 16px;
769
+ border-radius: 50%;
770
+ background: var(--tcw-text-muted);
771
+ transition:
772
+ left var(--tcw-dur-normal) var(--tcw-ease-out),
773
+ background var(--tcw-dur-fast) var(--tcw-ease);
774
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
775
+ }
776
+
777
+ .tcw-toggle.tcw-on {
778
+ background: var(--tcw-accent);
779
+ box-shadow: 0 0 0 2px var(--tcw-accent-glow);
780
+ }
781
+
782
+ .tcw-toggle.tcw-on::after {
783
+ left: 18px;
784
+ background: #fff;
785
+ }
786
+
787
+ .tcw-root[data-tcw-theme='light'] .tcw-toggle {
788
+ background: rgba(0, 0, 0, 0.12);
789
+ }
790
+
791
+ .tcw-root[data-tcw-theme='light'] .tcw-toggle::after {
792
+ background: #999;
793
+ }
794
+
795
+ .tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on {
796
+ background: var(--tcw-accent);
797
+ }
798
+
799
+ .tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on::after {
800
+ background: #fff;
801
+ }
802
+
803
+ .tcw-settings-select {
804
+ padding: 6px 10px;
805
+ font-size: 12px;
806
+ font-family: inherit;
807
+ background: var(--tcw-bg-surface);
808
+ border: 1px solid var(--tcw-border);
809
+ border-radius: var(--tcw-radius);
810
+ color: var(--tcw-text);
811
+ cursor: pointer;
812
+ transition: border-color var(--tcw-dur-fast) var(--tcw-ease);
813
+ }
814
+
815
+ .tcw-settings-select:hover {
816
+ border-color: var(--tcw-border-strong);
817
+ }
818
+
819
+ .tcw-settings-select:focus-visible {
820
+ outline: none;
821
+ border-color: var(--tcw-accent);
822
+ box-shadow: var(--tcw-ring);
823
+ }
824
+
825
+ .tcw-modal-footer {
826
+ display: flex;
827
+ align-items: center;
828
+ justify-content: space-between;
829
+ padding: 14px 22px;
830
+ border-top: 1px solid var(--tcw-divider);
831
+ background: var(--tcw-bg-surface);
832
+ border-radius: 0 0 var(--tcw-radius-xl) var(--tcw-radius-xl);
833
+ }
834
+
835
+ .tcw-reset-link {
836
+ font-size: 12px;
837
+ color: var(--tcw-text-muted);
838
+ cursor: pointer;
839
+ border: none;
840
+ background: transparent;
841
+ font-family: inherit;
842
+ text-decoration: underline;
843
+ text-underline-offset: 2px;
844
+ text-decoration-color: var(--tcw-border-strong);
845
+ transition: color var(--tcw-dur-fast) var(--tcw-ease), text-decoration-color var(--tcw-dur-fast) var(--tcw-ease);
846
+ }
847
+
848
+ .tcw-reset-link:hover {
849
+ color: var(--tcw-text-dim);
850
+ text-decoration-color: currentColor;
851
+ }
852
+
853
+ .tcw-done-btn {
854
+ padding: 8px 18px;
855
+ font-size: 12.5px;
856
+ font-weight: 600;
857
+ background: var(--tcw-accent);
858
+ color: #fff;
859
+ border: none;
860
+ border-radius: var(--tcw-radius);
861
+ cursor: pointer;
862
+ font-family: inherit;
863
+ transition:
864
+ background var(--tcw-dur-fast) var(--tcw-ease),
865
+ transform var(--tcw-dur-fast) var(--tcw-ease),
866
+ box-shadow var(--tcw-dur-fast) var(--tcw-ease);
867
+ letter-spacing: -0.005em;
868
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.15);
869
+ }
870
+
871
+ .tcw-done-btn:hover {
872
+ background: var(--tcw-accent-hover);
873
+ box-shadow: var(--tcw-shadow-md), 0 0 0 3px var(--tcw-accent-glow);
874
+ }
875
+
876
+ .tcw-done-btn:active {
877
+ transform: translateY(0.5px);
878
+ }
879
+
880
+ /* === Status Bar === */
881
+
882
+ .tcw-statusbar {
883
+ display: flex;
884
+ align-items: center;
885
+ justify-content: space-between;
886
+ padding: 7px 16px;
887
+ border-top: 1px solid var(--tcw-border);
888
+ background: var(--tcw-bg-surface);
889
+ font-size: 11px;
890
+ color: var(--tcw-text-muted);
891
+ flex-shrink: 0;
892
+ font-feature-settings: 'tnum';
893
+ }
894
+
895
+ .tcw-status-indicator {
896
+ display: flex;
897
+ align-items: center;
898
+ gap: 7px;
899
+ font-weight: 500;
900
+ }
901
+
902
+ .tcw-status-dot {
903
+ width: 7px;
904
+ height: 7px;
905
+ border-radius: 50%;
906
+ background: var(--tcw-text-muted);
907
+ transition: background var(--tcw-dur-normal) var(--tcw-ease), box-shadow var(--tcw-dur-normal) var(--tcw-ease);
908
+ position: relative;
909
+ }
910
+
911
+ .tcw-status-dot.tcw-connected {
912
+ background: var(--tcw-green);
913
+ box-shadow: 0 0 0 3px rgba(38, 161, 123, 0.18);
914
+ }
915
+
916
+ .tcw-status-dot.tcw-connected::after {
917
+ content: '';
918
+ position: absolute;
919
+ inset: -3px;
920
+ border-radius: 50%;
921
+ border: 2px solid var(--tcw-green);
922
+ opacity: 0;
923
+ animation: tcw-pulse 2.2s ease-out infinite;
924
+ }
925
+
926
+ @keyframes tcw-pulse {
927
+ 0% { opacity: 0.6; transform: scale(0.6); }
928
+ 100% { opacity: 0; transform: scale(2.2); }
929
+ }
930
+
931
+ .tcw-status-dot.tcw-error {
932
+ background: var(--tcw-red);
933
+ box-shadow: 0 0 0 3px rgba(242, 54, 69, 0.2);
934
+ }
935
+
936
+ /* === Command Palette === */
937
+
938
+ .tcw-cmd-palette {
939
+ position: fixed;
940
+ z-index: 102;
941
+ top: 18%;
942
+ left: 50%;
943
+ transform: translateX(-50%);
944
+ background: var(--tcw-bg-elevated);
945
+ border: 1px solid var(--tcw-border);
946
+ border-radius: var(--tcw-radius-xl);
947
+ width: 560px;
948
+ max-width: 92vw;
949
+ max-height: 62vh;
950
+ display: flex;
951
+ flex-direction: column;
952
+ box-shadow: var(--tcw-shadow-xl);
953
+ overflow: hidden;
954
+ backdrop-filter: blur(20px);
955
+ -webkit-backdrop-filter: blur(20px);
956
+ animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);
957
+ }
958
+
959
+ .tcw-cmd-header {
960
+ display: flex;
961
+ align-items: center;
962
+ padding: 14px 18px;
963
+ border-bottom: 1px solid var(--tcw-divider);
964
+ gap: 12px;
965
+ }
966
+
967
+ .tcw-cmd-icon {
968
+ font-size: 18px;
969
+ color: var(--tcw-text-muted);
970
+ flex-shrink: 0;
971
+ display: inline-flex;
972
+ align-items: center;
973
+ }
974
+
975
+ .tcw-cmd-input {
976
+ flex: 1;
977
+ background: transparent;
978
+ border: none;
979
+ outline: none;
980
+ font-size: 14.5px;
981
+ font-family: inherit;
982
+ color: var(--tcw-text);
983
+ caret-color: var(--tcw-accent);
984
+ letter-spacing: -0.005em;
985
+ }
986
+
987
+ .tcw-cmd-input::placeholder {
988
+ color: var(--tcw-text-muted);
989
+ }
990
+
991
+ .tcw-cmd-hint {
992
+ font-size: 10px;
993
+ color: var(--tcw-text-muted);
994
+ font-family: var(--tcw-font-mono);
995
+ border: 1px solid var(--tcw-border);
996
+ background: var(--tcw-bg-surface);
997
+ padding: 3px 7px;
998
+ border-radius: 4px;
999
+ flex-shrink: 0;
1000
+ box-shadow: inset 0 -1px 0 var(--tcw-border);
1001
+ }
1002
+
1003
+ .tcw-cmd-list {
1004
+ overflow-y: auto;
1005
+ flex: 1;
1006
+ padding: 6px;
1007
+ max-height: 380px;
1008
+ }
1009
+
1010
+ .tcw-cmd-category {
1011
+ text-transform: uppercase;
1012
+ font-size: 10px;
1013
+ color: var(--tcw-text-muted);
1014
+ letter-spacing: 0.09em;
1015
+ padding: 10px 10px 4px;
1016
+ font-weight: 600;
1017
+ }
1018
+
1019
+ .tcw-cmd-item {
1020
+ display: flex;
1021
+ align-items: center;
1022
+ justify-content: space-between;
1023
+ padding: 9px 12px;
1024
+ font-size: 13px;
1025
+ color: var(--tcw-text-dim);
1026
+ cursor: pointer;
1027
+ width: 100%;
1028
+ border: none;
1029
+ background: transparent;
1030
+ font-family: inherit;
1031
+ text-align: left;
1032
+ transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);
1033
+ gap: 10px;
1034
+ border-radius: var(--tcw-radius);
1035
+ letter-spacing: -0.005em;
1036
+ }
1037
+
1038
+ .tcw-cmd-item:hover,
1039
+ .tcw-cmd-item.tcw-selected {
1040
+ background: var(--tcw-hover-bg);
1041
+ color: var(--tcw-text);
1042
+ }
1043
+
1044
+ .tcw-cmd-item.tcw-selected {
1045
+ box-shadow: inset 2px 0 0 var(--tcw-accent);
1046
+ }
1047
+
1048
+ .tcw-cmd-item.tcw-active .tcw-cmd-item-label {
1049
+ color: var(--tcw-accent);
1050
+ font-weight: 600;
1051
+ }
1052
+
1053
+ .tcw-cmd-item-label {
1054
+ flex: 1;
1055
+ }
1056
+
1057
+ .tcw-cmd-check {
1058
+ color: var(--tcw-accent);
1059
+ font-size: 14px;
1060
+ font-weight: 700;
1061
+ }
1062
+
1063
+ .tcw-cmd-kbd {
1064
+ font-size: 10px;
1065
+ font-family: var(--tcw-font-mono);
1066
+ color: var(--tcw-text-muted);
1067
+ background: var(--tcw-bg-surface);
1068
+ border: 1px solid var(--tcw-border);
1069
+ padding: 2px 6px;
1070
+ border-radius: 4px;
1071
+ box-shadow: inset 0 -1px 0 var(--tcw-border);
1072
+ }
1073
+
1074
+ .tcw-cmd-empty {
1075
+ padding: 32px 16px;
1076
+ text-align: center;
1077
+ color: var(--tcw-text-muted);
1078
+ font-size: 13px;
1079
+ }
1080
+
1081
+ .tcw-cmd-footer {
1082
+ display: flex;
1083
+ align-items: center;
1084
+ gap: 18px;
1085
+ padding: 10px 18px;
1086
+ border-top: 1px solid var(--tcw-divider);
1087
+ font-size: 11px;
1088
+ color: var(--tcw-text-muted);
1089
+ background: var(--tcw-bg-surface);
1090
+ }
1091
+
1092
+ /* === Watchlist === */
1093
+
1094
+ .tcw-watchlist {
1095
+ width: 220px;
1096
+ flex-shrink: 0;
1097
+ background: var(--tcw-bg-surface);
1098
+ border-left: 1px solid var(--tcw-border);
1099
+ display: flex;
1100
+ flex-direction: column;
1101
+ overflow: hidden;
1102
+ box-shadow: var(--tcw-shadow-sm);
1103
+ }
1104
+
1105
+ .tcw-watchlist-header {
1106
+ padding: 10px 14px;
1107
+ font-size: 11px;
1108
+ font-weight: 600;
1109
+ text-transform: uppercase;
1110
+ letter-spacing: 0.08em;
1111
+ color: var(--tcw-text-muted);
1112
+ border-bottom: 1px solid var(--tcw-divider);
1113
+ }
1114
+
1115
+ .tcw-watchlist-list {
1116
+ flex: 1;
1117
+ overflow-y: auto;
1118
+ padding: 4px 0;
1119
+ }
1120
+
1121
+ .tcw-watchlist-row {
1122
+ display: grid;
1123
+ grid-template-columns: 1fr auto auto;
1124
+ align-items: center;
1125
+ gap: 8px;
1126
+ padding: 8px 12px;
1127
+ cursor: pointer;
1128
+ transition: background var(--tcw-dur-fast) var(--tcw-ease);
1129
+ border-left: 2px solid transparent;
1130
+ outline: none;
1131
+ }
1132
+
1133
+ .tcw-watchlist-row:hover {
1134
+ background: var(--tcw-hover-bg);
1135
+ }
1136
+
1137
+ .tcw-watchlist-row:focus-visible {
1138
+ background: var(--tcw-hover-bg);
1139
+ border-left-color: var(--tcw-accent);
1140
+ }
1141
+
1142
+ .tcw-watchlist-row.tcw-watchlist-active {
1143
+ background: var(--tcw-accent-soft);
1144
+ border-left-color: var(--tcw-accent);
1145
+ }
1146
+
1147
+ .tcw-watchlist-symbol {
1148
+ font-size: 12.5px;
1149
+ font-weight: 600;
1150
+ color: var(--tcw-text);
1151
+ letter-spacing: -0.005em;
1152
+ white-space: nowrap;
1153
+ }
1154
+
1155
+ .tcw-watchlist-spark {
1156
+ width: 56px;
1157
+ height: 22px;
1158
+ align-self: center;
1159
+ }
1160
+
1161
+ .tcw-watchlist-stats {
1162
+ display: flex;
1163
+ flex-direction: column;
1164
+ align-items: flex-end;
1165
+ gap: 1px;
1166
+ font-variant-numeric: tabular-nums;
1167
+ font-family: var(--tcw-font-mono);
1168
+ }
1169
+
1170
+ .tcw-watchlist-price {
1171
+ font-size: 12px;
1172
+ color: var(--tcw-text);
1173
+ font-weight: 500;
1174
+ }
1175
+
1176
+ .tcw-watchlist-change {
1177
+ font-size: 10.5px;
1178
+ color: var(--tcw-text-muted);
1179
+ font-weight: 500;
1180
+ }
1181
+
1182
+ .tcw-watchlist-change.tcw-up {
1183
+ color: var(--tcw-green);
1184
+ }
1185
+
1186
+ .tcw-watchlist-change.tcw-down {
1187
+ color: var(--tcw-red);
1188
+ }
1189
+
1190
+ @media (max-width: 768px) {
1191
+ .tcw-watchlist {
1192
+ display: none;
1193
+ }
1194
+ }
1195
+
1196
+ /* === Toast === */
1197
+
1198
+ .tcw-toast {
1199
+ position: absolute;
1200
+ bottom: 60px;
1201
+ left: 50%;
1202
+ transform: translate(-50%, 12px);
1203
+ z-index: 40;
1204
+ padding: 9px 14px;
1205
+ background: var(--tcw-bg-elevated);
1206
+ border: 1px solid var(--tcw-border-strong);
1207
+ border-radius: 9999px;
1208
+ box-shadow: var(--tcw-shadow-lg);
1209
+ font-size: 12.5px;
1210
+ font-weight: 500;
1211
+ color: var(--tcw-text);
1212
+ opacity: 0;
1213
+ transition: opacity var(--tcw-dur-normal) var(--tcw-ease-out), transform var(--tcw-dur-normal) var(--tcw-ease-out);
1214
+ pointer-events: none;
1215
+ max-width: calc(100% - 32px);
1216
+ white-space: nowrap;
1217
+ overflow: hidden;
1218
+ text-overflow: ellipsis;
1219
+ letter-spacing: -0.005em;
1220
+ }
1221
+
1222
+ .tcw-toast.tcw-toast-in {
1223
+ opacity: 1;
1224
+ transform: translate(-50%, 0);
1225
+ }
1226
+
1227
+ .tcw-toast-error {
1228
+ border-color: var(--tcw-red);
1229
+ color: var(--tcw-red);
1230
+ }
1231
+
1232
+ /* === Replay scrubber === */
1233
+
1234
+ .tcw-replay-bar {
1235
+ position: absolute;
1236
+ left: 50%;
1237
+ bottom: 16px;
1238
+ transform: translateX(-50%);
1239
+ z-index: 25;
1240
+ display: flex;
1241
+ align-items: center;
1242
+ gap: 6px;
1243
+ padding: 6px 10px;
1244
+ background: var(--tcw-bg-elevated);
1245
+ border: 1px solid var(--tcw-border);
1246
+ border-radius: 9999px;
1247
+ box-shadow: var(--tcw-shadow-lg);
1248
+ backdrop-filter: blur(12px);
1249
+ -webkit-backdrop-filter: blur(12px);
1250
+ font-size: 12px;
1251
+ color: var(--tcw-text);
1252
+ animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);
1253
+ }
1254
+
1255
+ .tcw-replay-btn {
1256
+ width: 28px;
1257
+ height: 28px;
1258
+ display: inline-flex;
1259
+ align-items: center;
1260
+ justify-content: center;
1261
+ border: none;
1262
+ background: transparent;
1263
+ color: var(--tcw-text-dim);
1264
+ border-radius: 9999px;
1265
+ cursor: pointer;
1266
+ font-family: inherit;
1267
+ transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);
1268
+ }
1269
+
1270
+ .tcw-replay-btn:hover {
1271
+ background: var(--tcw-hover-bg);
1272
+ color: var(--tcw-text);
1273
+ }
1274
+
1275
+ .tcw-replay-btn.tcw-replay-play {
1276
+ background: var(--tcw-accent);
1277
+ color: #fff;
1278
+ width: 32px;
1279
+ height: 32px;
1280
+ box-shadow: 0 0 0 3px var(--tcw-accent-glow);
1281
+ }
1282
+
1283
+ .tcw-replay-btn.tcw-replay-play:hover {
1284
+ background: var(--tcw-accent-hover);
1285
+ }
1286
+
1287
+ .tcw-replay-scrubber {
1288
+ appearance: none;
1289
+ -webkit-appearance: none;
1290
+ width: 220px;
1291
+ height: 4px;
1292
+ background: var(--tcw-border-strong);
1293
+ border-radius: 2px;
1294
+ outline: none;
1295
+ cursor: pointer;
1296
+ }
1297
+
1298
+ .tcw-replay-scrubber::-webkit-slider-thumb {
1299
+ -webkit-appearance: none;
1300
+ appearance: none;
1301
+ width: 14px;
1302
+ height: 14px;
1303
+ border-radius: 50%;
1304
+ background: var(--tcw-accent);
1305
+ border: 2px solid var(--tcw-bg-elevated);
1306
+ box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);
1307
+ cursor: pointer;
1308
+ }
1309
+
1310
+ .tcw-replay-scrubber::-moz-range-thumb {
1311
+ width: 14px;
1312
+ height: 14px;
1313
+ border-radius: 50%;
1314
+ background: var(--tcw-accent);
1315
+ border: 2px solid var(--tcw-bg-elevated);
1316
+ box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);
1317
+ cursor: pointer;
1318
+ }
1319
+
1320
+ .tcw-replay-progress {
1321
+ font-size: 11px;
1322
+ font-family: var(--tcw-font-mono);
1323
+ color: var(--tcw-text-muted);
1324
+ min-width: 64px;
1325
+ text-align: center;
1326
+ font-feature-settings: 'tnum';
1327
+ }
1328
+
1329
+ .tcw-replay-speed {
1330
+ padding: 4px 8px;
1331
+ font-size: 11px;
1332
+ font-family: var(--tcw-font-mono);
1333
+ background: var(--tcw-bg-surface);
1334
+ border: 1px solid var(--tcw-border);
1335
+ border-radius: var(--tcw-radius);
1336
+ color: var(--tcw-text-dim);
1337
+ cursor: pointer;
1338
+ }
1339
+
1340
+ .tcw-replay-speed:hover {
1341
+ border-color: var(--tcw-border-strong);
1342
+ }
1343
+
1344
+ @media (max-width: 640px) {
1345
+ .tcw-replay-scrubber {
1346
+ width: 140px;
1347
+ }
1348
+ .tcw-replay-progress {
1349
+ display: none;
1350
+ }
1351
+ }
1352
+
1353
+ /* === Hotkey sheet === */
1354
+
1355
+ .tcw-hotkey-grid {
1356
+ display: grid;
1357
+ grid-template-columns: 1fr 1fr;
1358
+ gap: 24px 32px;
1359
+ }
1360
+
1361
+ .tcw-hotkey-section .tcw-settings-section-title {
1362
+ margin-bottom: 8px;
1363
+ }
1364
+
1365
+ .tcw-hotkey-row {
1366
+ display: flex;
1367
+ align-items: center;
1368
+ justify-content: space-between;
1369
+ gap: 12px;
1370
+ padding: 6px 0;
1371
+ border-bottom: 1px solid var(--tcw-divider);
1372
+ }
1373
+
1374
+ .tcw-hotkey-row:last-child {
1375
+ border-bottom: none;
1376
+ }
1377
+
1378
+ .tcw-hotkey-keys {
1379
+ display: flex;
1380
+ align-items: center;
1381
+ gap: 4px;
1382
+ flex-shrink: 0;
1383
+ }
1384
+
1385
+ .tcw-hotkey-sep {
1386
+ font-size: 10px;
1387
+ color: var(--tcw-text-muted);
1388
+ }
1389
+
1390
+ .tcw-hotkey-label {
1391
+ font-size: 12.5px;
1392
+ color: var(--tcw-text-dim);
1393
+ text-align: right;
1394
+ letter-spacing: -0.005em;
1395
+ }
1396
+
1397
+ @media (max-width: 640px) {
1398
+ .tcw-hotkey-grid {
1399
+ grid-template-columns: 1fr;
1400
+ gap: 18px;
1401
+ }
1402
+ }
1403
+
1404
+ /* === Scrollbar (subtle, premium feel) === */
1405
+
1406
+ .tcw-dropdown::-webkit-scrollbar,
1407
+ .tcw-modal-body::-webkit-scrollbar,
1408
+ .tcw-cmd-list::-webkit-scrollbar {
1409
+ width: 8px;
1410
+ height: 8px;
1411
+ }
1412
+
1413
+ .tcw-dropdown::-webkit-scrollbar-track,
1414
+ .tcw-modal-body::-webkit-scrollbar-track,
1415
+ .tcw-cmd-list::-webkit-scrollbar-track {
1416
+ background: transparent;
1417
+ }
1418
+
1419
+ .tcw-dropdown::-webkit-scrollbar-thumb,
1420
+ .tcw-modal-body::-webkit-scrollbar-thumb,
1421
+ .tcw-cmd-list::-webkit-scrollbar-thumb {
1422
+ background: var(--tcw-border-strong);
1423
+ border-radius: 4px;
1424
+ border: 2px solid transparent;
1425
+ background-clip: padding-box;
1426
+ }
1427
+
1428
+ .tcw-dropdown::-webkit-scrollbar-thumb:hover,
1429
+ .tcw-modal-body::-webkit-scrollbar-thumb:hover,
1430
+ .tcw-cmd-list::-webkit-scrollbar-thumb:hover {
1431
+ background: var(--tcw-text-muted);
1432
+ background-clip: padding-box;
1433
+ border: 2px solid transparent;
1434
+ }
1435
+
1436
+ /* === Responsive === */
1437
+
1438
+ @media (max-width: 768px) {
1439
+ .tcw-toolbar {
1440
+ padding: 0 4px;
1441
+ height: 44px; /* Apple HIG minimum touch target */
1442
+ }
1443
+ .tcw-toolbar-sep {
1444
+ display: none;
1445
+ }
1446
+ .tcw-indicator-chips {
1447
+ display: none;
1448
+ }
1449
+ .tcw-btn,
1450
+ .tcw-dropdown-trigger {
1451
+ padding: 10px 12px; /* fatter tap target */
1452
+ font-size: 13px;
1453
+ }
1454
+ .tcw-btn-icon {
1455
+ width: 40px;
1456
+ height: 40px;
1457
+ }
1458
+ .tcw-sidebar {
1459
+ width: 44px;
1460
+ }
1461
+ .tcw-sidebar-btn {
1462
+ width: 40px;
1463
+ height: 40px;
1464
+ }
1465
+ .tcw-modal,
1466
+ .tcw-cmd-palette {
1467
+ width: 94vw;
1468
+ border-radius: var(--tcw-radius-lg);
1469
+ }
1470
+
1471
+ /* Hide the right-side watchlist on tablets too — already declared but
1472
+ * grouped here for clarity. */
1473
+ .tcw-watchlist {
1474
+ display: none;
1475
+ }
1476
+
1477
+ /* Replay scrubber compact mode */
1478
+ .tcw-replay-scrubber {
1479
+ width: 120px;
1480
+ }
1481
+ .tcw-replay-progress {
1482
+ display: none;
1483
+ }
1484
+ }
1485
+
1486
+ /* === Mobile bottom-sheet pattern ===
1487
+ * On phones, swap floating-centered modals for full-width sheets that slide
1488
+ * up from the bottom. Bigger hit targets, no awkward off-screen clipping,
1489
+ * matches how every modern iOS/Android app handles overflow UI.
1490
+ */
1491
+ @media (max-width: 640px) {
1492
+ .tcw-modal,
1493
+ .tcw-cmd-palette {
1494
+ top: auto;
1495
+ bottom: 0;
1496
+ left: 0;
1497
+ right: 0;
1498
+ transform: none;
1499
+ width: 100vw;
1500
+ max-width: 100vw;
1501
+ max-height: 92vh;
1502
+ border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;
1503
+ border-bottom: none;
1504
+ /* Grab handle */
1505
+ padding-top: 8px;
1506
+ }
1507
+
1508
+ /* Visual "grab handle" affordance — a short pill at the top of every sheet */
1509
+ .tcw-modal::before,
1510
+ .tcw-cmd-palette::before {
1511
+ content: '';
1512
+ display: block;
1513
+ width: 36px;
1514
+ height: 4px;
1515
+ border-radius: 2px;
1516
+ background: var(--tcw-border-strong);
1517
+ margin: 0 auto 8px;
1518
+ opacity: 0.7;
1519
+ }
1520
+
1521
+ /* Reuse the existing modal-in animation but slide from below instead of
1522
+ * popping from center, so the entrance reads as a sheet, not a dialog. */
1523
+ @keyframes tcw-modal-in {
1524
+ from { opacity: 0; transform: translateY(20px); }
1525
+ to { opacity: 1; transform: translateY(0); }
1526
+ }
1527
+
1528
+ .tcw-modal,
1529
+ .tcw-cmd-palette {
1530
+ animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);
1531
+ }
1532
+
1533
+ /* Safe-area-aware footer padding for iPhone notch / home indicator */
1534
+ .tcw-modal-footer,
1535
+ .tcw-cmd-footer {
1536
+ padding-bottom: max(14px, env(safe-area-inset-bottom));
1537
+ }
1538
+
1539
+ /* Larger tap targets inside sheets */
1540
+ .tcw-modal-tab {
1541
+ padding: 14px 16px;
1542
+ }
1543
+ .tcw-cmd-item {
1544
+ padding: 12px 14px;
1545
+ font-size: 14px;
1546
+ }
1547
+ .tcw-dropdown-item {
1548
+ padding: 12px 12px;
1549
+ font-size: 14px;
1550
+ }
1551
+
1552
+ /* Hotkey sheet — single column on phones */
1553
+ .tcw-hotkey-grid {
1554
+ grid-template-columns: 1fr;
1555
+ }
1556
+ }
1557
+
1558
+ /* === Price alerts panel === */
1559
+
1560
+ .tcw-alerts-panel {
1561
+ position: absolute;
1562
+ top: 50px;
1563
+ right: 12px;
1564
+ z-index: 40;
1565
+ width: 300px;
1566
+ max-width: calc(100vw - 24px);
1567
+ display: flex;
1568
+ flex-direction: column;
1569
+ background: var(--tcw-bg-elevated);
1570
+ border: 1px solid var(--tcw-border-strong);
1571
+ border-radius: var(--tcw-radius-lg);
1572
+ box-shadow: var(--tcw-shadow-lg);
1573
+ overflow: hidden;
1574
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1575
+ }
1576
+
1577
+ @keyframes tcw-alerts-in {
1578
+ from { opacity: 0; transform: translateY(-6px) scale(0.98); }
1579
+ to { opacity: 1; transform: none; }
1580
+ }
1581
+
1582
+ .tcw-alerts-header {
1583
+ display: flex;
1584
+ align-items: center;
1585
+ justify-content: space-between;
1586
+ padding: 10px 12px;
1587
+ font-weight: 600;
1588
+ font-size: 13px;
1589
+ color: var(--tcw-text);
1590
+ border-bottom: 1px solid var(--tcw-border);
1591
+ }
1592
+
1593
+ .tcw-alerts-close {
1594
+ display: inline-flex;
1595
+ align-items: center;
1596
+ justify-content: center;
1597
+ width: 26px;
1598
+ height: 26px;
1599
+ border: none;
1600
+ background: transparent;
1601
+ color: var(--tcw-text-muted);
1602
+ border-radius: var(--tcw-radius-sm);
1603
+ cursor: pointer;
1604
+ }
1605
+ .tcw-alerts-close:hover {
1606
+ background: var(--tcw-bg-surface);
1607
+ color: var(--tcw-text);
1608
+ }
1609
+
1610
+ .tcw-alerts-form {
1611
+ display: grid;
1612
+ grid-template-columns: 1fr 1fr;
1613
+ gap: 8px;
1614
+ padding: 12px;
1615
+ border-bottom: 1px solid var(--tcw-border);
1616
+ }
1617
+
1618
+ .tcw-alerts-form input,
1619
+ .tcw-alerts-form select {
1620
+ height: 32px;
1621
+ padding: 0 8px;
1622
+ font-size: 12px;
1623
+ color: var(--tcw-text);
1624
+ background: var(--tcw-bg-surface);
1625
+ border: 1px solid var(--tcw-border);
1626
+ border-radius: var(--tcw-radius-sm);
1627
+ outline: none;
1628
+ }
1629
+ .tcw-alerts-form input:focus,
1630
+ .tcw-alerts-form select:focus {
1631
+ border-color: var(--tcw-accent);
1632
+ box-shadow: 0 0 0 2px var(--tcw-accent-soft);
1633
+ }
1634
+ .tcw-alerts-message,
1635
+ .tcw-alerts-source {
1636
+ grid-column: 1 / -1;
1637
+ }
1638
+
1639
+ .tcw-alerts-add {
1640
+ grid-column: 1 / -1;
1641
+ display: inline-flex;
1642
+ align-items: center;
1643
+ justify-content: center;
1644
+ gap: 6px;
1645
+ height: 34px;
1646
+ font-size: 12px;
1647
+ font-weight: 600;
1648
+ color: #fff;
1649
+ background: var(--tcw-accent);
1650
+ border: none;
1651
+ border-radius: var(--tcw-radius-sm);
1652
+ cursor: pointer;
1653
+ }
1654
+ .tcw-alerts-add:hover {
1655
+ background: var(--tcw-accent-hover);
1656
+ }
1657
+
1658
+ .tcw-alerts-list {
1659
+ max-height: 260px;
1660
+ overflow-y: auto;
1661
+ padding: 6px;
1662
+ }
1663
+
1664
+ .tcw-alerts-empty {
1665
+ padding: 18px 12px;
1666
+ text-align: center;
1667
+ font-size: 12px;
1668
+ color: var(--tcw-text-muted);
1669
+ line-height: 1.5;
1670
+ }
1671
+
1672
+ .tcw-alerts-row {
1673
+ display: flex;
1674
+ align-items: center;
1675
+ justify-content: space-between;
1676
+ gap: 8px;
1677
+ padding: 8px 8px;
1678
+ border-radius: var(--tcw-radius-sm);
1679
+ }
1680
+ .tcw-alerts-row:hover {
1681
+ background: var(--tcw-bg-surface);
1682
+ }
1683
+ .tcw-alerts-triggered {
1684
+ background: var(--tcw-accent-soft);
1685
+ }
1686
+
1687
+ .tcw-alerts-info {
1688
+ min-width: 0;
1689
+ }
1690
+ .tcw-alerts-row-main {
1691
+ display: flex;
1692
+ align-items: center;
1693
+ gap: 8px;
1694
+ font-size: 12px;
1695
+ font-weight: 600;
1696
+ color: var(--tcw-text);
1697
+ font-variant-numeric: tabular-nums;
1698
+ }
1699
+ .tcw-alerts-row-note {
1700
+ margin-top: 2px;
1701
+ font-size: 11px;
1702
+ color: var(--tcw-text-muted);
1703
+ overflow: hidden;
1704
+ text-overflow: ellipsis;
1705
+ white-space: nowrap;
1706
+ }
1707
+ .tcw-alerts-badge {
1708
+ font-size: 9px;
1709
+ font-weight: 700;
1710
+ text-transform: uppercase;
1711
+ letter-spacing: 0.04em;
1712
+ padding: 2px 5px;
1713
+ border-radius: 999px;
1714
+ color: var(--tcw-accent);
1715
+ background: var(--tcw-accent-soft);
1716
+ }
1717
+
1718
+ .tcw-alerts-del {
1719
+ flex-shrink: 0;
1720
+ display: inline-flex;
1721
+ align-items: center;
1722
+ justify-content: center;
1723
+ width: 28px;
1724
+ height: 28px;
1725
+ border: none;
1726
+ background: transparent;
1727
+ color: var(--tcw-text-muted);
1728
+ border-radius: var(--tcw-radius-sm);
1729
+ cursor: pointer;
1730
+ }
1731
+ .tcw-alerts-del:hover {
1732
+ background: var(--tcw-red-soft);
1733
+ color: var(--tcw-red);
1734
+ }
1735
+
1736
+ @media (max-width: 640px) {
1737
+ .tcw-alerts-panel {
1738
+ top: auto;
1739
+ bottom: 0;
1740
+ left: 0;
1741
+ right: 0;
1742
+ width: 100vw;
1743
+ max-width: 100vw;
1744
+ border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;
1745
+ }
1746
+ .tcw-alerts-list {
1747
+ max-height: 40vh;
1748
+ padding-bottom: max(8px, env(safe-area-inset-bottom));
1749
+ }
1750
+ }
1751
+
1752
+ /* === Data Window === */
1753
+
1754
+ .tcw-datawin {
1755
+ position: absolute;
1756
+ top: 50px;
1757
+ right: 12px;
1758
+ z-index: 38;
1759
+ width: 200px;
1760
+ display: flex;
1761
+ flex-direction: column;
1762
+ background: var(--tcw-bg-elevated);
1763
+ border: 1px solid var(--tcw-border-strong);
1764
+ border-radius: var(--tcw-radius-lg);
1765
+ box-shadow: var(--tcw-shadow-lg);
1766
+ overflow: hidden;
1767
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1768
+ }
1769
+ .tcw-datawin-header {
1770
+ display: flex;
1771
+ align-items: center;
1772
+ justify-content: space-between;
1773
+ padding: 9px 12px;
1774
+ font-size: 12px;
1775
+ font-weight: 600;
1776
+ color: var(--tcw-text);
1777
+ border-bottom: 1px solid var(--tcw-border);
1778
+ }
1779
+ .tcw-datawin-close {
1780
+ display: inline-flex;
1781
+ align-items: center;
1782
+ justify-content: center;
1783
+ width: 24px;
1784
+ height: 24px;
1785
+ border: none;
1786
+ background: transparent;
1787
+ color: var(--tcw-text-muted);
1788
+ border-radius: var(--tcw-radius-sm);
1789
+ cursor: pointer;
1790
+ }
1791
+ .tcw-datawin-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }
1792
+ .tcw-datawin-body { padding: 6px 4px; max-height: 360px; overflow-y: auto; }
1793
+ .tcw-datawin-empty { padding: 14px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }
1794
+ .tcw-datawin-row {
1795
+ display: flex;
1796
+ align-items: center;
1797
+ justify-content: space-between;
1798
+ gap: 10px;
1799
+ padding: 3px 8px;
1800
+ font-size: 12px;
1801
+ }
1802
+ .tcw-datawin-label { color: var(--tcw-text-muted); }
1803
+ .tcw-datawin-value { color: var(--tcw-text); font-variant-numeric: tabular-nums; font-weight: 600; }
1804
+ .tcw-datawin-value.tcw-up { color: var(--tcw-green); }
1805
+ .tcw-datawin-value.tcw-down { color: var(--tcw-red); }
1806
+ .tcw-datawin-sub {
1807
+ margin: 6px 8px 2px;
1808
+ font-size: 10px;
1809
+ font-weight: 700;
1810
+ text-transform: uppercase;
1811
+ letter-spacing: 0.04em;
1812
+ color: var(--tcw-text-muted);
1813
+ border-top: 1px solid var(--tcw-border);
1814
+ padding-top: 6px;
1815
+ }
1816
+
1817
+ @media (max-width: 640px) {
1818
+ .tcw-datawin { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }
1819
+ }
1820
+
1821
+ /* === Depth-of-market ladder === */
1822
+
1823
+ .tcw-ladder {
1824
+ position: absolute;
1825
+ top: 50px;
1826
+ right: 12px;
1827
+ z-index: 41;
1828
+ width: 240px;
1829
+ display: flex;
1830
+ flex-direction: column;
1831
+ background: var(--tcw-bg-elevated);
1832
+ border: 1px solid var(--tcw-border-strong);
1833
+ border-radius: var(--tcw-radius-lg);
1834
+ box-shadow: var(--tcw-shadow-lg);
1835
+ overflow: hidden;
1836
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1837
+ }
1838
+ .tcw-ladder-header {
1839
+ display: flex;
1840
+ align-items: center;
1841
+ justify-content: space-between;
1842
+ padding: 10px 12px;
1843
+ font-size: 13px;
1844
+ font-weight: 600;
1845
+ color: var(--tcw-text);
1846
+ border-bottom: 1px solid var(--tcw-border);
1847
+ }
1848
+ .tcw-ladder-close {
1849
+ display: inline-flex;
1850
+ align-items: center;
1851
+ justify-content: center;
1852
+ width: 26px;
1853
+ height: 26px;
1854
+ border: none;
1855
+ background: transparent;
1856
+ color: var(--tcw-text-muted);
1857
+ border-radius: var(--tcw-radius-sm);
1858
+ cursor: pointer;
1859
+ }
1860
+ .tcw-ladder-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }
1861
+ .tcw-ladder-cols {
1862
+ display: grid;
1863
+ grid-template-columns: 1fr 1fr 1fr;
1864
+ padding: 4px 0;
1865
+ font-size: 10px;
1866
+ font-weight: 700;
1867
+ text-transform: uppercase;
1868
+ letter-spacing: 0.04em;
1869
+ color: var(--tcw-text-muted);
1870
+ border-bottom: 1px solid var(--tcw-border);
1871
+ }
1872
+ .tcw-ladder-cols span { text-align: center; }
1873
+ .tcw-ladder-body { max-height: 360px; overflow-y: auto; }
1874
+ .tcw-ladder-empty { padding: 18px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }
1875
+
1876
+ .tcw-ladder-row {
1877
+ display: grid;
1878
+ grid-template-columns: 1fr 1fr 1fr;
1879
+ height: 22px;
1880
+ font-variant-numeric: tabular-nums;
1881
+ }
1882
+ .tcw-ladder-cell {
1883
+ position: relative;
1884
+ display: flex;
1885
+ align-items: center;
1886
+ border: none;
1887
+ background: transparent;
1888
+ font-size: 11px;
1889
+ cursor: pointer;
1890
+ font-variant-numeric: tabular-nums;
1891
+ overflow: hidden;
1892
+ }
1893
+ .tcw-ladder-cell:disabled { cursor: default; }
1894
+ /* Depth bar grows from the centre column outward. */
1895
+ .tcw-ladder-cell::before {
1896
+ content: '';
1897
+ position: absolute;
1898
+ top: 1px; bottom: 1px;
1899
+ width: var(--w, 0%);
1900
+ }
1901
+ .tcw-ladder-bid { justify-content: flex-end; padding-right: 8px; color: var(--tcw-green); }
1902
+ .tcw-ladder-bid::before { right: 0; background: var(--tcw-green-soft); }
1903
+ .tcw-ladder-bid span, .tcw-ladder-bid { position: relative; }
1904
+ .tcw-ladder-ask { justify-content: flex-start; padding-left: 8px; color: var(--tcw-red); }
1905
+ .tcw-ladder-ask::before { left: 0; background: var(--tcw-red-soft); }
1906
+ .tcw-ladder-cell:not(:disabled):hover::before { opacity: 0.7; filter: brightness(1.4); }
1907
+ .tcw-ladder-cell > * { position: relative; }
1908
+ .tcw-ladder-price {
1909
+ display: flex;
1910
+ align-items: center;
1911
+ justify-content: center;
1912
+ font-size: 11px;
1913
+ font-weight: 600;
1914
+ color: var(--tcw-text-dim);
1915
+ border-left: 1px solid var(--tcw-border);
1916
+ border-right: 1px solid var(--tcw-border);
1917
+ }
1918
+ .tcw-ladder-price.tcw-ask { color: var(--tcw-red); }
1919
+ .tcw-ladder-price.tcw-bid { color: var(--tcw-green); }
1920
+
1921
+ @media (max-width: 640px) {
1922
+ .tcw-ladder { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }
1923
+ .tcw-ladder-body { max-height: 45vh; padding-bottom: max(0px, env(safe-area-inset-bottom)); }
1924
+ }
1925
+
1926
+ /* === Bracket order placement === */
1927
+
1928
+ .tcw-btn-long:hover { color: var(--tcw-green) !important; }
1929
+ .tcw-btn-short:hover { color: var(--tcw-red) !important; }
1930
+
1931
+ .tcw-bracket-bar {
1932
+ position: absolute;
1933
+ top: 52px;
1934
+ left: 50%;
1935
+ transform: translateX(-50%);
1936
+ z-index: 45;
1937
+ display: flex;
1938
+ align-items: center;
1939
+ gap: 10px;
1940
+ padding: 7px 8px 7px 14px;
1941
+ background: var(--tcw-bg-elevated);
1942
+ border: 1px solid var(--tcw-border-strong);
1943
+ border-radius: 999px;
1944
+ box-shadow: var(--tcw-shadow-lg);
1945
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1946
+ }
1947
+ .tcw-bracket-label {
1948
+ font-size: 12px;
1949
+ font-weight: 700;
1950
+ }
1951
+ .tcw-bracket-label[data-side='buy'] { color: var(--tcw-green); }
1952
+ .tcw-bracket-label[data-side='sell'] { color: var(--tcw-red); }
1953
+ .tcw-bracket-hint {
1954
+ font-size: 11px;
1955
+ color: var(--tcw-text-muted);
1956
+ }
1957
+ .tcw-bracket-cancel, .tcw-bracket-confirm {
1958
+ display: inline-flex;
1959
+ align-items: center;
1960
+ gap: 5px;
1961
+ height: 30px;
1962
+ padding: 0 12px;
1963
+ font-size: 12px;
1964
+ font-weight: 600;
1965
+ border: none;
1966
+ border-radius: 999px;
1967
+ cursor: pointer;
1968
+ }
1969
+ .tcw-bracket-cancel {
1970
+ color: var(--tcw-text-dim);
1971
+ background: var(--tcw-bg-surface);
1972
+ }
1973
+ .tcw-bracket-cancel:hover { color: var(--tcw-text); }
1974
+ .tcw-bracket-confirm {
1975
+ color: #fff;
1976
+ background: var(--tcw-accent);
1977
+ }
1978
+ .tcw-bracket-confirm:hover { background: var(--tcw-accent-hover); }
1979
+
1980
+ @media (max-width: 640px) {
1981
+ .tcw-bracket-bar { width: calc(100vw - 24px); justify-content: space-between; }
1982
+ .tcw-bracket-hint { display: none; }
1983
+ }
1984
+
1985
+ /* === Drawing style + templates popover === */
1986
+
1987
+ .tcw-style-panel {
1988
+ position: absolute;
1989
+ bottom: 12px;
1990
+ left: 52px;
1991
+ z-index: 40;
1992
+ width: 220px;
1993
+ display: flex;
1994
+ flex-direction: column;
1995
+ gap: 8px;
1996
+ padding: 12px;
1997
+ background: var(--tcw-bg-elevated);
1998
+ border: 1px solid var(--tcw-border-strong);
1999
+ border-radius: var(--tcw-radius-lg);
2000
+ box-shadow: var(--tcw-shadow-lg);
2001
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
2002
+ }
2003
+ .tcw-style-header {
2004
+ display: flex;
2005
+ align-items: center;
2006
+ justify-content: space-between;
2007
+ font-size: 12px;
2008
+ font-weight: 600;
2009
+ color: var(--tcw-text);
2010
+ }
2011
+ .tcw-style-close {
2012
+ display: inline-flex;
2013
+ align-items: center;
2014
+ justify-content: center;
2015
+ width: 24px;
2016
+ height: 24px;
2017
+ border: none;
2018
+ background: transparent;
2019
+ color: var(--tcw-text-muted);
2020
+ border-radius: var(--tcw-radius-sm);
2021
+ cursor: pointer;
2022
+ }
2023
+ .tcw-style-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }
2024
+
2025
+ .tcw-style-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
2026
+ .tcw-style-swatch {
2027
+ width: 18px;
2028
+ height: 18px;
2029
+ border-radius: 50%;
2030
+ border: 1px solid var(--tcw-border-strong);
2031
+ cursor: pointer;
2032
+ padding: 0;
2033
+ }
2034
+ .tcw-style-swatch.tcw-on { outline: 2px solid var(--tcw-accent); outline-offset: 1px; }
2035
+ .tcw-style-picker {
2036
+ width: 22px;
2037
+ height: 22px;
2038
+ padding: 0;
2039
+ border: 1px solid var(--tcw-border);
2040
+ border-radius: var(--tcw-radius-sm);
2041
+ background: transparent;
2042
+ cursor: pointer;
2043
+ }
2044
+ .tcw-style-width, .tcw-style-dash {
2045
+ flex: 1;
2046
+ min-width: 0;
2047
+ height: 26px;
2048
+ display: flex;
2049
+ align-items: center;
2050
+ justify-content: center;
2051
+ background: var(--tcw-bg-surface);
2052
+ border: 1px solid var(--tcw-border);
2053
+ border-radius: var(--tcw-radius-sm);
2054
+ color: var(--tcw-text-dim);
2055
+ cursor: pointer;
2056
+ font-size: 11px;
2057
+ }
2058
+ .tcw-style-width span { width: 16px; background: currentColor; border-radius: 2px; }
2059
+ .tcw-style-width.tcw-on, .tcw-style-dash.tcw-on {
2060
+ border-color: var(--tcw-accent);
2061
+ color: var(--tcw-accent);
2062
+ }
2063
+
2064
+ .tcw-style-subhead {
2065
+ font-size: 10px;
2066
+ font-weight: 700;
2067
+ text-transform: uppercase;
2068
+ letter-spacing: 0.05em;
2069
+ color: var(--tcw-text-muted);
2070
+ margin-top: 2px;
2071
+ }
2072
+ .tcw-style-save { display: flex; gap: 6px; }
2073
+ .tcw-style-name {
2074
+ flex: 1;
2075
+ min-width: 0;
2076
+ height: 28px;
2077
+ padding: 0 8px;
2078
+ font-size: 12px;
2079
+ color: var(--tcw-text);
2080
+ background: var(--tcw-bg-surface);
2081
+ border: 1px solid var(--tcw-border);
2082
+ border-radius: var(--tcw-radius-sm);
2083
+ outline: none;
2084
+ }
2085
+ .tcw-style-name:focus { border-color: var(--tcw-accent); }
2086
+ .tcw-style-savebtn {
2087
+ display: inline-flex;
2088
+ align-items: center;
2089
+ gap: 4px;
2090
+ padding: 0 10px;
2091
+ height: 28px;
2092
+ font-size: 12px;
2093
+ font-weight: 600;
2094
+ color: #fff;
2095
+ background: var(--tcw-accent);
2096
+ border: none;
2097
+ border-radius: var(--tcw-radius-sm);
2098
+ cursor: pointer;
2099
+ }
2100
+ .tcw-style-savebtn:hover { background: var(--tcw-accent-hover); }
2101
+
2102
+ .tcw-style-templates { display: flex; flex-direction: column; gap: 2px; max-height: 140px; overflow-y: auto; }
2103
+ .tcw-style-empty { font-size: 11px; color: var(--tcw-text-muted); padding: 4px 0; }
2104
+ .tcw-style-template { display: flex; align-items: center; gap: 4px; }
2105
+ .tcw-style-apply {
2106
+ flex: 1;
2107
+ min-width: 0;
2108
+ display: flex;
2109
+ align-items: center;
2110
+ gap: 7px;
2111
+ padding: 5px 7px;
2112
+ font-size: 12px;
2113
+ color: var(--tcw-text);
2114
+ background: transparent;
2115
+ border: none;
2116
+ border-radius: var(--tcw-radius-sm);
2117
+ cursor: pointer;
2118
+ text-align: left;
2119
+ }
2120
+ .tcw-style-apply:hover { background: var(--tcw-bg-surface); }
2121
+ .tcw-style-tdot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; }
2122
+ .tcw-style-tdel {
2123
+ display: inline-flex;
2124
+ align-items: center;
2125
+ justify-content: center;
2126
+ width: 26px;
2127
+ height: 26px;
2128
+ border: none;
2129
+ background: transparent;
2130
+ color: var(--tcw-text-muted);
2131
+ border-radius: var(--tcw-radius-sm);
2132
+ cursor: pointer;
2133
+ }
2134
+ .tcw-style-tdel:hover { background: var(--tcw-red-soft); color: var(--tcw-red); }
2135
+
2136
+ /* === Settings range slider === */
2137
+
2138
+ .tcw-settings-range {
2139
+ display: flex;
2140
+ align-items: center;
2141
+ gap: 8px;
2142
+ }
2143
+ .tcw-settings-range input[type='range'] {
2144
+ width: 110px;
2145
+ accent-color: var(--tcw-accent);
2146
+ cursor: pointer;
2147
+ }
2148
+ .tcw-settings-range-val {
2149
+ min-width: 38px;
2150
+ text-align: right;
2151
+ font-size: 12px;
2152
+ font-variant-numeric: tabular-nums;
2153
+ color: var(--tcw-text-dim);
2154
+ }
2155
+
2156
+ /* === Indicator settings dialog === */
2157
+
2158
+ .tcw-modal-narrow {
2159
+ max-width: 360px;
2160
+ }
2161
+ .tcw-indi-input {
2162
+ width: 110px;
2163
+ height: 30px;
2164
+ padding: 0 8px;
2165
+ font-size: 12px;
2166
+ color: var(--tcw-text);
2167
+ background: var(--tcw-bg-surface);
2168
+ border: 1px solid var(--tcw-border);
2169
+ border-radius: var(--tcw-radius-sm);
2170
+ outline: none;
2171
+ font-variant-numeric: tabular-nums;
2172
+ }
2173
+ .tcw-indi-input:focus {
2174
+ border-color: var(--tcw-accent);
2175
+ box-shadow: 0 0 0 2px var(--tcw-accent-soft);
2176
+ }
2177
+ .tcw-indi-color {
2178
+ width: 36px;
2179
+ height: 28px;
2180
+ padding: 2px;
2181
+ background: var(--tcw-bg-surface);
2182
+ border: 1px solid var(--tcw-border);
2183
+ border-radius: var(--tcw-radius-sm);
2184
+ cursor: pointer;
2185
+ }
2186
+
2187
+ /* === Object tree panel === */
2188
+
2189
+ .tcw-tree-panel {
2190
+ position: absolute;
2191
+ top: 50px;
2192
+ right: 12px;
2193
+ z-index: 39;
2194
+ width: 280px;
2195
+ max-width: calc(100vw - 24px);
2196
+ display: flex;
2197
+ flex-direction: column;
2198
+ background: var(--tcw-bg-elevated);
2199
+ border: 1px solid var(--tcw-border-strong);
2200
+ border-radius: var(--tcw-radius-lg);
2201
+ box-shadow: var(--tcw-shadow-lg);
2202
+ overflow: hidden;
2203
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
2204
+ }
2205
+
2206
+ .tcw-tree-header {
2207
+ display: flex;
2208
+ align-items: center;
2209
+ justify-content: space-between;
2210
+ padding: 10px 12px;
2211
+ font-weight: 600;
2212
+ font-size: 13px;
2213
+ color: var(--tcw-text);
2214
+ border-bottom: 1px solid var(--tcw-border);
2215
+ }
2216
+ .tcw-tree-close {
2217
+ display: inline-flex;
2218
+ align-items: center;
2219
+ justify-content: center;
2220
+ width: 26px;
2221
+ height: 26px;
2222
+ border: none;
2223
+ background: transparent;
2224
+ color: var(--tcw-text-muted);
2225
+ border-radius: var(--tcw-radius-sm);
2226
+ cursor: pointer;
2227
+ }
2228
+ .tcw-tree-close:hover {
2229
+ background: var(--tcw-bg-surface);
2230
+ color: var(--tcw-text);
2231
+ }
2232
+
2233
+ .tcw-tree-section {
2234
+ padding: 6px;
2235
+ border-bottom: 1px solid var(--tcw-border);
2236
+ }
2237
+ .tcw-tree-section:last-child {
2238
+ border-bottom: none;
2239
+ }
2240
+ .tcw-tree-section-head {
2241
+ display: flex;
2242
+ align-items: center;
2243
+ justify-content: space-between;
2244
+ padding: 6px 8px 4px;
2245
+ font-size: 10px;
2246
+ font-weight: 700;
2247
+ text-transform: uppercase;
2248
+ letter-spacing: 0.05em;
2249
+ color: var(--tcw-text-muted);
2250
+ }
2251
+ .tcw-tree-add {
2252
+ display: inline-flex;
2253
+ align-items: center;
2254
+ justify-content: center;
2255
+ width: 22px;
2256
+ height: 22px;
2257
+ border: none;
2258
+ background: transparent;
2259
+ color: var(--tcw-text-muted);
2260
+ border-radius: var(--tcw-radius-sm);
2261
+ cursor: pointer;
2262
+ }
2263
+ .tcw-tree-add:hover {
2264
+ background: var(--tcw-accent-soft);
2265
+ color: var(--tcw-accent);
2266
+ }
2267
+ .tcw-tree-dot {
2268
+ flex-shrink: 0;
2269
+ width: 8px;
2270
+ height: 8px;
2271
+ border-radius: 50%;
2272
+ }
2273
+ .tcw-tree-list {
2274
+ max-height: 200px;
2275
+ overflow-y: auto;
2276
+ }
2277
+
2278
+ .tcw-tree-row {
2279
+ display: flex;
2280
+ align-items: center;
2281
+ justify-content: space-between;
2282
+ gap: 8px;
2283
+ padding: 6px 8px;
2284
+ border-radius: var(--tcw-radius-sm);
2285
+ }
2286
+ .tcw-tree-row:hover {
2287
+ background: var(--tcw-bg-surface);
2288
+ }
2289
+ .tcw-tree-hidden .tcw-tree-name {
2290
+ opacity: 0.5;
2291
+ }
2292
+ .tcw-tree-name {
2293
+ min-width: 0;
2294
+ font-size: 12px;
2295
+ color: var(--tcw-text);
2296
+ overflow: hidden;
2297
+ text-overflow: ellipsis;
2298
+ white-space: nowrap;
2299
+ }
2300
+ .tcw-tree-actions {
2301
+ display: flex;
2302
+ align-items: center;
2303
+ gap: 2px;
2304
+ flex-shrink: 0;
2305
+ }
2306
+ .tcw-tree-btn {
2307
+ display: inline-flex;
2308
+ align-items: center;
2309
+ justify-content: center;
2310
+ width: 26px;
2311
+ height: 26px;
2312
+ border: none;
2313
+ background: transparent;
2314
+ color: var(--tcw-text-muted);
2315
+ border-radius: var(--tcw-radius-sm);
2316
+ cursor: pointer;
2317
+ }
2318
+ .tcw-tree-btn:hover {
2319
+ background: var(--tcw-bg-elevated);
2320
+ color: var(--tcw-text);
2321
+ }
2322
+ .tcw-tree-btn.tcw-tree-on {
2323
+ color: var(--tcw-accent);
2324
+ }
2325
+ .tcw-tree-btn.tcw-tree-del:hover {
2326
+ background: var(--tcw-red-soft);
2327
+ color: var(--tcw-red);
2328
+ }
2329
+ .tcw-tree-empty {
2330
+ padding: 8px;
2331
+ font-size: 12px;
2332
+ color: var(--tcw-text-muted);
2333
+ }
2334
+
2335
+ @media (max-width: 640px) {
2336
+ .tcw-tree-panel {
2337
+ top: auto;
2338
+ bottom: 0;
2339
+ left: 0;
2340
+ right: 0;
2341
+ width: 100vw;
2342
+ max-width: 100vw;
2343
+ border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;
2344
+ }
2345
+ .tcw-tree-list {
2346
+ max-height: 30vh;
2347
+ }
2348
+ .tcw-tree-section:last-child {
2349
+ padding-bottom: max(6px, env(safe-area-inset-bottom));
2350
+ }
2351
+ }
2352
+
2353
+ /* === Reduced motion === */
2354
+
2355
+ @media (prefers-reduced-motion: reduce) {
2356
+ .tcw-root *,
2357
+ .tcw-root *::before,
2358
+ .tcw-root *::after {
2359
+ animation-duration: 0.01ms !important;
2360
+ animation-iteration-count: 1 !important;
2361
+ transition-duration: 0.01ms !important;
2362
+ }
2363
+ }
2364
+ `,f=0,p=`tcw-styles`;function m(){if(f++,f>1||document.getElementById(p))return;let e=document.createElement(`style`);e.id=p,e.textContent=d,document.head.appendChild(e)}function h(){if(f--,f>0)return;let e=document.getElementById(p);e&&e.remove()}var g={cursor:`<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>`,trendingUp:`<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>`,minus:`<path d="M5 12h14"/>`,penLine:`<path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/>`,hash:`<line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/>`,square:`<rect width="18" height="18" x="3" y="3" rx="2"/>`,gitBranch:`<line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>`,ruler:`<path d="M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z"/><path d="m14.5 12.5 2-2"/><path d="m11.5 9.5 2-2"/><path d="m8.5 6.5 2-2"/><path d="m17.5 15.5 2-2"/>`,type:`<polyline points="4 7 4 4 20 4 20 7"/><line x1="9" y1="20" x2="15" y2="20"/><line x1="12" y1="4" x2="12" y2="20"/>`,magnet:`<path d="m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15"/><path d="m5 8 4 4"/><path d="m12 15 4 4"/>`,undo:`<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>`,redo:`<path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"/>`,trash:`<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/>`,camera:`<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>`,settings:`<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>`,moon:`<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>`,sun:`<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>`,chevronDown:`<path d="m6 9 6 6 6-6"/>`,chevronUp:`<path d="m18 15-6-6-6 6"/>`,barChart:`<line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/>`,x:`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`,play:`<polygon points="6 3 20 12 6 21 6 3"/>`,pause:`<rect width="4" height="16" x="6" y="4"/><rect width="4" height="16" x="14" y="4"/>`,stop:`<rect width="14" height="14" x="5" y="5" rx="1"/>`,receipt:`<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"/><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"/><path d="M12 17.5v-11"/>`,bell:`<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/>`,plus:`<path d="M5 12h14"/><path d="M12 5v14"/>`,layers:`<path d="m12 2 9 5-9 5-9-5 9-5Z"/><path d="m3 12 9 5 9-5"/><path d="m3 17 9 5 9-5"/>`,eye:`<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>`,eyeOff:`<path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c6.5 0 10 7 10 7a13.2 13.2 0 0 1-1.67 2.68"/><path d="M6.6 6.6A13.06 13.06 0 0 0 2 11s3.5 7 10 7a9.1 9.1 0 0 0 5.4-1.6"/><path d="m2 2 20 20"/>`,lock:`<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>`,unlock:`<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 9.9-1"/>`,palette:`<circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2Z"/>`,trendingDown:`<polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/>`,check:`<polyline points="20 6 9 17 4 12"/>`,ladder:`<rect x="3" y="3" width="18" height="18" rx="2"/><line x1="12" y1="3" x2="12" y2="21"/><line x1="3" y1="8" x2="21" y2="8"/><line x1="3" y1="13" x2="21" y2="13"/><line x1="3" y1="18" x2="21" y2="18"/>`};function _(e,t=14){let n=g[e];return n?`<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`:``}var v=class{trigger;panel;_isOpen=!1;onOutsideClick;onEscapeKey;onTriggerClick;constructor(e,t={}){this.trigger=e,this.panel=document.createElement(`div`),this.panel.className=`tcw-dropdown`,this.panel.style.width=t.width??`200px`,t.align===`right`?this.panel.style.right=`0`:this.panel.style.left=`0`,this.panel.style.display=`none`,e.style.position=`relative`,e.appendChild(this.panel),this.onTriggerClick=()=>{this._isOpen?this.close():this.open()},this.onOutsideClick=e=>{this.trigger.contains(e.target)||this.close()},this.onEscapeKey=e=>{e.key===`Escape`&&this.close()},e.addEventListener(`click`,this.onTriggerClick)}setContent(e){this.panel.innerHTML=e}open(){this._isOpen||(this._isOpen=!0,this.panel.style.display=``,document.addEventListener(`mousedown`,this.onOutsideClick),document.addEventListener(`keydown`,this.onEscapeKey))}close(){this._isOpen&&(this._isOpen=!1,this.panel.style.display=`none`,document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey))}isOpen(){return this._isOpen}destroy(){this.trigger.removeEventListener(`click`,this.onTriggerClick),document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey),this.panel.remove()}},y=class{config;callbacks;el;chartTypeDropdown=null;indicatorDropdown=null;tfButtons=[];chipsContainer=null;themeBtn=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-toolbar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this,r=document.createElement(`button`);r.className=`tcw-toolbar-symbol`,r.dataset.role=`symbol`,r.addEventListener(`click`,t.onSymbolClick),n.appendChild(r),n.appendChild(this.sep());let i=document.createElement(`div`);i.className=`tcw-toolbar-group`;for(let n of e.timeframes){let e=document.createElement(`button`);e.className=`tcw-btn`,e.textContent=n.label,e.dataset.tf=n.value,e.addEventListener(`click`,()=>t.onTimeframe(n.value)),i.appendChild(e),this.tfButtons.push(e)}n.appendChild(i),n.appendChild(this.sep());let a=document.createElement(`div`);a.style.position=`relative`,a.style.display=`inline-flex`;let o=document.createElement(`button`);o.className=`tcw-dropdown-trigger`,o.dataset.role=`charttype`,a.appendChild(o),n.appendChild(a),this.chartTypeDropdown=new v(a,{width:`160px`}),this.buildChartTypeMenu(),n.appendChild(this.sep());let s=document.createElement(`div`);s.style.position=`relative`,s.style.display=`inline-flex`;let c=document.createElement(`button`);if(c.className=`tcw-dropdown-trigger`,c.dataset.role=`indicators`,s.appendChild(c),n.appendChild(s),this.indicatorDropdown=new v(s,{width:`280px`}),this.buildIndicatorMenu(),this.chipsContainer=document.createElement(`div`),this.chipsContainer.className=`tcw-indicator-chips`,n.appendChild(this.chipsContainer),n.appendChild(this.spacer()),t.onToggleReplay){let e=this.iconBtn(`play`,`Bar replay`,t.onToggleReplay);e.dataset.role=`replay`,n.appendChild(e)}if(t.onBracket){let e=t.onBracket,r=this.iconBtn(`trendingUp`,`Long bracket`,()=>e(`buy`));r.dataset.role=`long`,r.classList.add(`tcw-btn-long`),n.appendChild(r);let i=this.iconBtn(`trendingDown`,`Short bracket`,()=>e(`sell`));i.dataset.role=`short`,i.classList.add(`tcw-btn-short`),n.appendChild(i)}if(t.onToggleLadder){let e=this.iconBtn(`ladder`,`Depth ladder`,t.onToggleLadder);e.dataset.role=`ladder`,n.appendChild(e)}if(t.onToggleObjects){let e=this.iconBtn(`layers`,`Objects`,t.onToggleObjects);e.dataset.role=`objects`,n.appendChild(e)}if(t.onToggleAlerts){let e=this.iconBtn(`bell`,`Price alerts`,t.onToggleAlerts);e.dataset.role=`alerts`,n.appendChild(e)}let l=this.iconBtn(`camera`,`Screenshot`,t.onScreenshot);n.appendChild(l);let u=this.iconBtn(`settings`,`Chart Settings`,t.onSettings);n.appendChild(u),this.themeBtn=this.iconBtn(`moon`,`Toggle theme`,t.onToggleTheme),this.themeBtn.dataset.role=`theme`,n.appendChild(this.themeBtn)}buildChartTypeMenu(){if(!this.chartTypeDropdown)return;let e=this.config.chartTypes.map(e=>`<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join(``);this.chartTypeDropdown.setContent(e),this.chartTypeDropdown.panel.querySelectorAll(`.tcw-dropdown-item`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ct;this.callbacks.onChartType(t),this.chartTypeDropdown?.close()})})}buildIndicatorMenu(){if(!this.indicatorDropdown)return;let{indicators:e,popularIndicatorIds:t}=this.config,n=e.filter(e=>t.includes(e.id)),r=e.filter(e=>!t.includes(e.id)),i=`<div class="tcw-dropdown-label">Popular</div>`;for(let e of n)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;i+=`<div class="tcw-dropdown-divider"></div>`,i+=`<div class="tcw-dropdown-label">All</div>`;for(let e of r)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;this.indicatorDropdown.setContent(i),this.indicatorDropdown.panel.querySelectorAll(`.tcw-dropdown-item[data-ind]`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ind;this.callbacks.onAddIndicator(t)})})}update(e){let t=this.el.querySelector(`[data-role="symbol"]`);t&&(t.textContent=e.symbol);for(let t of this.tfButtons)t.classList.toggle(`tcw-active`,t.dataset.tf===e.timeframe);let n=this.el.querySelector(`[data-role="charttype"]`);if(n){let t=this.config.chartTypes.find(t=>t.value===e.chartType)?.label??`Candles`;n.innerHTML=`${_(`barChart`,14)} ${t} ${_(`chevronDown`,12)}`}let r=this.el.querySelector(`[data-role="indicators"]`);if(r){let t=e.activeIndicators.size,n=`${_(`trendingUp`,14)} Indicators`;t>0&&(n+=` <span class="tcw-badge-count">${t}</span>`),r.innerHTML=n}if(this.chipsContainer){let t=this.getActiveIndicatorList(e);this.chipsContainer.innerHTML=``;for(let e of t){let t=document.createElement(`div`);t.className=`tcw-indicator-chip`;let n=document.createElement(`span`);n.textContent=e.label,t.appendChild(n);let r=document.createElement(`button`);r.className=`tcw-chip-remove`,r.innerHTML=_(`x`,10),r.addEventListener(`click`,()=>this.callbacks.onRemoveIndicator(e.instanceId)),t.appendChild(r),this.chipsContainer.appendChild(t)}}this.themeBtn&&(this.themeBtn.innerHTML=e.isDark?_(`moon`,14):_(`sun`,14))}getActiveIndicatorList(e){let t=[];for(let[n,r]of e.activeIndicators.entries())t.push({instanceId:r,id:n,label:n.toUpperCase()});return t}sep(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-sep`,e}spacer(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-spacer`,e}iconBtn(e,t,n){let r=document.createElement(`button`);return r.className=`tcw-btn-icon`,r.title=t,r.innerHTML=_(e,14),r.addEventListener(`click`,n),r}destroy(){this.chartTypeDropdown?.destroy(),this.indicatorDropdown?.destroy(),this.el.remove()}},ee=[`trendingUp`,`minus`,`penLine`,`hash`,`square`,`gitBranch`,`ruler`,`type`],te={trendLine:`trendingUp`,ray:`trendingUp`,extendedLine:`trendingUp`,horizontalLine:`minus`,verticalLine:`penLine`,rectangle:`square`,ellipse:`square`,triangle:`square`,arrow:`trendingUp`,parallelChannel:`gitBranch`,regressionChannel:`gitBranch`,pitchfork:`gitBranch`,fibRetracement:`hash`,fibExtension:`hash`,fibTimeZones:`hash`,gannBox:`hash`,gannFan:`gitBranch`,elliottWave:`trendingUp`,priceRange:`ruler`,dateRange:`ruler`,measure:`ruler`,textAnnotation:`type`,anchoredVWAP:`trendingUp`,volumeProfileRange:`barChart`};function ne(e){return te[e]??`penLine`}function re(e,t){for(let n of e){let e=n.tools.find(e=>e.value===t);if(e)return e.label}return t}var ie=class{config;callbacks;el;groupWraps=[];groupButtons=[];cursorBtn=null;magnetBtn=null;flyoutEl=null;favoritesEl=null;favoritesDivider=null;favorites=[];constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-sidebar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this;this.cursorBtn=document.createElement(`button`),this.cursorBtn.className=`tcw-sidebar-btn`,this.cursorBtn.title=`Cursor`,this.cursorBtn.innerHTML=_(`cursor`,14),this.cursorBtn.addEventListener(`click`,t.onCancelDrawing),n.appendChild(this.cursorBtn),n.appendChild(this.divider()),t.onToggleFavorite&&(this.favorites=[...e.favorites??[]],this.favoritesEl=document.createElement(`div`),this.favoritesEl.className=`tcw-sidebar-favorites`,n.appendChild(this.favoritesEl),this.favoritesDivider=this.divider(),n.appendChild(this.favoritesDivider),this.renderFavorites()),e.drawingToolGroups.forEach((e,r)=>{let i=document.createElement(`div`);i.className=`tcw-tool-group-wrap`;let a=document.createElement(`button`);if(a.className=`tcw-sidebar-btn`,a.title=e.label,a.innerHTML=_(ee[r]??`square`,14),e.tools.length>1){let e=document.createElement(`span`);e.className=`tcw-multi-dot`,a.appendChild(e)}a.addEventListener(`click`,()=>t.onDrawingTool(e.tools[0].value)),i.appendChild(a),i.addEventListener(`mouseenter`,()=>this.showFlyout(r)),i.addEventListener(`mouseleave`,()=>this.hideFlyout()),n.appendChild(i),this.groupWraps.push(i),this.groupButtons.push(a)});let r=document.createElement(`div`);if(r.className=`tcw-sidebar-spacer`,n.appendChild(r),n.appendChild(this.divider()),t.onToggleStyle){let e=document.createElement(`button`);e.className=`tcw-sidebar-btn`,e.title=`Drawing style & templates`,e.dataset.role=`style`,e.innerHTML=_(`palette`,14),e.addEventListener(`click`,t.onToggleStyle),n.appendChild(e)}this.magnetBtn=document.createElement(`button`),this.magnetBtn.className=`tcw-sidebar-btn`,this.magnetBtn.title=`Magnet`,this.magnetBtn.innerHTML=_(`magnet`,14),this.magnetBtn.addEventListener(`click`,t.onToggleMagnet),n.appendChild(this.magnetBtn);let i=document.createElement(`button`);i.className=`tcw-sidebar-btn`,i.title=`Undo`,i.innerHTML=_(`undo`,14),i.addEventListener(`click`,t.onUndo),n.appendChild(i);let a=document.createElement(`button`);a.className=`tcw-sidebar-btn`,a.title=`Redo`,a.innerHTML=_(`redo`,14),a.addEventListener(`click`,t.onRedo),n.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-sidebar-btn tcw-danger`,o.title=`Clear all`,o.innerHTML=_(`trash`,14),o.addEventListener(`click`,t.onClearDrawings),n.appendChild(o)}setFavorites(e){this.favorites=[...e],this.renderFavorites()}renderFavorites(){if(!this.favoritesEl)return;this.favoritesEl.replaceChildren();let e=this.favorites.length>0;this.favoritesEl.style.display=e?``:`none`,this.favoritesDivider&&(this.favoritesDivider.style.display=e?``:`none`);for(let e of this.favorites){let t=document.createElement(`button`);t.className=`tcw-sidebar-btn`,t.title=`${re(this.config.drawingToolGroups,e)} (right-click to unpin)`,t.dataset.toolValue=e,t.innerHTML=_(ne(e),14),t.addEventListener(`click`,()=>this.callbacks.onDrawingTool(e)),t.addEventListener(`contextmenu`,t=>{t.preventDefault(),this.callbacks.onToggleFavorite?.(e)}),this.favoritesEl.appendChild(t)}}showFlyout(e){let t=this.config.drawingToolGroups[e];if(!t||t.tools.length<=1)return;this.hideFlyout();let n=document.createElement(`div`);n.className=`tcw-flyout`;let r=document.createElement(`div`);r.className=`tcw-flyout-header`,r.textContent=t.label,n.appendChild(r);for(let e of t.tools){let t=document.createElement(`button`);t.className=`tcw-flyout-item`,t.textContent=e.label,t.dataset.toolValue=e.value,t.addEventListener(`click`,()=>{this.callbacks.onDrawingTool(e.value),this.hideFlyout()}),this.callbacks.onToggleFavorite&&(this.favorites.includes(e.value)&&t.classList.add(`tcw-flyout-faved`),t.title=`Right-click to pin/unpin`,t.addEventListener(`contextmenu`,t=>{t.preventDefault(),this.callbacks.onToggleFavorite?.(e.value)})),n.appendChild(t)}this.flyoutEl=n,this.groupWraps[e].appendChild(n)}hideFlyout(){this.flyoutEl&&=(this.flyoutEl.remove(),null)}update(e){this.cursorBtn&&this.cursorBtn.classList.toggle(`tcw-active`,e.activeTool===null);let{drawingToolGroups:t}=this.config;for(let n=0;n<t.length;n++){let r=t[n].tools.some(t=>t.value===e.activeTool);this.groupButtons[n].classList.toggle(`tcw-active`,r)}this.flyoutEl&&this.flyoutEl.querySelectorAll(`.tcw-flyout-item`).forEach(t=>{let n=t;n.classList.toggle(`tcw-active`,n.dataset.toolValue===e.activeTool)}),this.magnetBtn&&(this.magnetBtn.classList.toggle(`tcw-active`,e.magnetEnabled),this.magnetBtn.title=e.magnetEnabled?`Magnet ON`:`Magnet OFF`)}divider(){let e=document.createElement(`div`);return e.className=`tcw-sidebar-divider`,e}destroy(){this.hideFlyout(),this.el.remove()}},ae=[`style`,`display`,`scale`],oe=class{callbacks;backdrop=null;modal=null;currentTab=`style`;currentSettings=null;bodyEl=null;tabButtons=[];constructor(e){this.callbacks=e}open(e){this.currentSettings={...e},this.currentTab=`style`,this.buildModal()}close(){this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.bodyEl=null,this.tabButtons=[]}buildModal(){this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),document.body.appendChild(this.backdrop),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal`;let e=document.createElement(`div`);e.className=`tcw-modal-header`;let t=document.createElement(`h3`);t.textContent=`Chart Settings`,e.appendChild(t);let n=document.createElement(`button`);n.className=`tcw-modal-close`,n.innerHTML=_(`x`,16),n.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),e.appendChild(n),this.modal.appendChild(e);let r=document.createElement(`div`);r.className=`tcw-modal-tabs`,this.tabButtons=[];for(let e of ae){let t=document.createElement(`button`);t.className=`tcw-modal-tab`,t.textContent=e,t.dataset.tab=e,e===this.currentTab&&t.classList.add(`tcw-active`),t.addEventListener(`click`,()=>{this.currentTab=e,this.tabButtons.forEach(t=>t.classList.toggle(`tcw-active`,t.dataset.tab===e)),this.renderTabContent()}),r.appendChild(t),this.tabButtons.push(t)}this.modal.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`,this.modal.appendChild(this.bodyEl),this.renderTabContent();let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.callbacks.onReset()),i.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),i.appendChild(o),this.modal.appendChild(i),document.body.appendChild(this.modal);let s=e=>{e.key===`Escape`&&(document.removeEventListener(`keydown`,s),this.callbacks.onClose(),this.close())};document.addEventListener(`keydown`,s)}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.innerHTML=``,this.currentTab){case`style`:this.renderStyleTab();break;case`display`:this.renderDisplayTab();break;case`scale`:this.renderScaleTab();break}}renderStyleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section(`Candle Colors`);t.appendChild(this.colorRow(`Up Body`,e.candleUpColor,e=>this.patch({candleUpColor:e}))),t.appendChild(this.colorRow(`Down Body`,e.candleDownColor,e=>this.patch({candleDownColor:e}))),t.appendChild(this.colorRow(`Up Wick`,e.candleUpWick,e=>this.patch({candleUpWick:e}))),t.appendChild(this.colorRow(`Down Wick`,e.candleDownWick,e=>this.patch({candleDownWick:e}))),this.bodyEl.appendChild(t);let n=this.section(`Background`);n.appendChild(this.colorRow(`Background`,e.backgroundColor,e=>this.patch({backgroundColor:e}))),n.appendChild(this.colorRow(`Grid`,e.gridColor,e=>this.patch({gridColor:e}))),this.bodyEl.appendChild(n)}renderDisplayTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Grid Lines`,e.gridVisible,e=>this.patch({gridVisible:e}))),t.appendChild(this.toggleRow(`Volume`,e.volumeVisible,e=>this.patch({volumeVisible:e}))),t.appendChild(this.toggleRow(`Volume Profile`,e.volumeProfileVisible,e=>this.patch({volumeProfileVisible:e}))),t.appendChild(this.toggleRow(`Market Profile (TPO)`,e.marketProfileVisible,e=>this.patch({marketProfileVisible:e}))),t.appendChild(this.toggleRow(`MP split by session`,e.marketProfileSplit,e=>this.patch({marketProfileSplit:e}))),t.appendChild(this.toggleRow(`MP letters (TPO)`,e.marketProfileLetters,e=>this.patch({marketProfileLetters:e}))),t.appendChild(this.rangeRow(`MP buckets`,e.marketProfileBuckets,8,200,1,e=>this.patch({marketProfileBuckets:e}))),t.appendChild(this.rangeRow(`MP opacity`,e.marketProfileOpacity,.05,1,.05,e=>this.patch({marketProfileOpacity:e}),e=>`${Math.round(e*100)}%`)),t.appendChild(this.toggleRow(`Liquidity heatmap`,e.depthHeatmapVisible,e=>this.patch({depthHeatmapVisible:e}))),t.appendChild(this.rangeRow(`Heatmap opacity`,e.depthHeatmapOpacity,.1,1,.05,e=>this.patch({depthHeatmapOpacity:e}),e=>`${Math.round(e*100)}%`)),t.appendChild(this.toggleRow(`Swing markers`,e.pivotMarkersVisible,e=>this.patch({pivotMarkersVisible:e}))),t.appendChild(this.rangeRow(`Swing strength`,e.pivotStrength,2,20,1,e=>this.patch({pivotStrength:e}))),t.appendChild(this.toggleRow(`Swing structure (HH/HL)`,e.pivotStructureLabels,e=>this.patch({pivotStructureLabels:e}))),t.appendChild(this.toggleRow(`Session shading (RTH)`,e.sessionShadingVisible,e=>this.patch({sessionShadingVisible:e}))),t.appendChild(this.toggleRow(`Prior-period levels`,e.periodLevelsVisible,e=>this.patch({periodLevelsVisible:e}))),t.appendChild(this.selectRow(`Period levels basis`,e.periodLevelsPeriod,[{value:`day`,label:`Prior Day (PDH/PDL)`},{value:`week`,label:`Prior Week (PWH/PWL)`}],e=>this.patch({periodLevelsPeriod:e}))),t.appendChild(this.toggleRow(`OHLC Legend`,e.legendVisible,e=>this.patch({legendVisible:e}))),t.appendChild(this.toggleRow(`Bar Countdown`,e.barCountdown,e=>this.patch({barCountdown:e}))),t.appendChild(this.selectRow(`Crosshair Mode`,e.crosshairMode,[{label:`Magnet`,value:`magnet`},{label:`Normal`,value:`normal`},{label:`Hidden`,value:`hidden`}],e=>this.patch({crosshairMode:e}))),t.appendChild(this.selectRow(`Timezone`,e.timezone,[{value:`local`,label:`Local`},{value:`0`,label:`UTC / London`},{value:`-300`,label:`New York (UTC-5)`},{value:`-360`,label:`Chicago (UTC-6)`},{value:`60`,label:`Frankfurt (UTC+1)`},{value:`480`,label:`Singapore/HK (UTC+8)`},{value:`540`,label:`Tokyo (UTC+9)`},{value:`330`,label:`Mumbai (UTC+5:30)`}],e=>this.patch({timezone:e}))),t.appendChild(this.selectRow(`Number Locale`,e.numberLocale,[{label:`en-US (65,234.00)`,value:`en-US`},{label:`de-DE (65.234,00)`,value:`de-DE`},{label:`fr-FR (65 234,00)`,value:`fr-FR`},{label:`vi-VN (65.234,00)`,value:`vi-VN`},{label:`en-IN (65,234.00)`,value:`en-IN`},{label:`ja-JP (65,234.00)`,value:`ja-JP`}],e=>this.patch({numberLocale:e}))),this.bodyEl.appendChild(t)}renderScaleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Auto Scale`,e.autoScale,e=>this.patch({autoScale:e}))),t.appendChild(this.selectRow(`Price Scale`,e.scaleMode,[{value:`regular`,label:`Regular`},{value:`logarithmic`,label:`Logarithmic`},{value:`percentage`,label:`Percentage`},{value:`indexedTo100`,label:`Indexed to 100`}],e=>this.patch({scaleMode:e}))),this.bodyEl.appendChild(t)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}section(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n)}return t}colorRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`div`);a.className=`tcw-color-picker-wrap`;let o=document.createElement(`input`);o.type=`color`,o.value=t;let s=document.createElement(`span`);return s.className=`tcw-color-hex`,s.textContent=t,o.addEventListener(`input`,()=>{s.textContent=o.value,n(o.value)}),a.appendChild(o),a.appendChild(s),r.appendChild(a),r}toggleRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`button`);return a.className=`tcw-toggle${t?` tcw-on`:``}`,a.addEventListener(`click`,()=>{let e=!a.classList.contains(`tcw-on`);a.classList.toggle(`tcw-on`,e),n(e)}),r.appendChild(a),r}selectRow(e,t,n,r){let i=document.createElement(`div`);i.className=`tcw-settings-row`;let a=document.createElement(`span`);a.className=`tcw-settings-label`,a.textContent=e,i.appendChild(a);let o=document.createElement(`select`);o.className=`tcw-settings-select`;for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),o.appendChild(n)}return o.addEventListener(`change`,()=>r(o.value)),i.appendChild(o),i}rangeRow(e,t,n,r,i,a,o=e=>String(e)){let s=document.createElement(`div`);s.className=`tcw-settings-row`;let c=document.createElement(`span`);c.className=`tcw-settings-label`,c.textContent=e,s.appendChild(c);let l=document.createElement(`div`);l.className=`tcw-settings-range`;let u=document.createElement(`input`);u.type=`range`,u.min=String(n),u.max=String(r),u.step=String(i),u.value=String(t);let d=document.createElement(`span`);return d.className=`tcw-settings-range-val`,d.textContent=o(t),u.addEventListener(`input`,()=>{let e=Number(u.value);d.textContent=o(e),a(e)}),l.appendChild(u),l.appendChild(d),s.appendChild(l),s}destroy(){this.close()}},b=class{el;dotEl;messageEl;infoEl;constructor(e){this.el=document.createElement(`div`),this.el.className=`tcw-statusbar`;let t=document.createElement(`div`);t.className=`tcw-status-indicator`,this.dotEl=document.createElement(`span`),this.dotEl.className=`tcw-status-dot`,t.appendChild(this.dotEl),this.messageEl=document.createElement(`span`),t.appendChild(this.messageEl),this.el.appendChild(t),this.infoEl=document.createElement(`span`),this.el.appendChild(this.infoEl),e.appendChild(this.el)}update(e){this.dotEl.className=`tcw-status-dot`,e.connectionState===`connected`?this.dotEl.classList.add(`tcw-connected`):e.connectionState===`error`&&this.dotEl.classList.add(`tcw-error`),this.messageEl.textContent=e.message,this.infoEl.textContent=`${e.symbol} ${e.timeframe}`}destroy(){this.el.remove()}},x=class{backdrop=null;modal=null;input=null;list=null;items=[];filtered=[];selectedIndex=0;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=this.handleKeydown.bind(this)}open(e){if(this.backdrop)return;this.items=e,this.filtered=e,this.selectedIndex=0,this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-cmd-palette`;let t=document.createElement(`div`);t.className=`tcw-cmd-header`;let n=document.createElement(`span`);n.className=`tcw-cmd-icon`,n.textContent=`⌕`,t.appendChild(n),this.input=document.createElement(`input`),this.input.className=`tcw-cmd-input`,this.input.type=`text`,this.input.placeholder=`Search indicators, chart types, tools...`,this.input.addEventListener(`input`,()=>this.filter()),t.appendChild(this.input);let r=document.createElement(`span`);r.className=`tcw-cmd-hint`,r.textContent=`ESC`,t.appendChild(r),this.modal.appendChild(t),this.list=document.createElement(`div`),this.list.className=`tcw-cmd-list`,this.modal.appendChild(this.list);let i=document.createElement(`div`);i.className=`tcw-cmd-footer`,i.innerHTML=`<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>`,this.modal.appendChild(i),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),this.renderList(),this.input.focus(),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.input=null,this.list=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}filter(){let e=this.input?.value.toLowerCase().trim()??``;e?this.filtered=this.items.filter(t=>t.label.toLowerCase().includes(e)||t.category.toLowerCase().includes(e)||t.id.toLowerCase().includes(e)):this.filtered=this.items,this.selectedIndex=0,this.renderList()}renderList(){if(!this.list)return;if(this.list.innerHTML=``,this.filtered.length===0){let e=document.createElement(`div`);e.className=`tcw-cmd-empty`,e.textContent=`No results found`,this.list.appendChild(e);return}let e=``;for(let t=0;t<this.filtered.length;t++){let n=this.filtered[t];if(n.category!==e){e=n.category;let t=document.createElement(`div`);t.className=`tcw-cmd-category`,t.textContent=this.categoryLabel(e),this.list.appendChild(t)}let r=document.createElement(`button`);r.className=`tcw-cmd-item`,t===this.selectedIndex&&r.classList.add(`tcw-selected`),n.active&&r.classList.add(`tcw-active`),r.dataset.index=String(t);let i=document.createElement(`span`);if(i.className=`tcw-cmd-item-label`,i.textContent=n.label,r.appendChild(i),n.active){let e=document.createElement(`span`);e.className=`tcw-cmd-check`,e.textContent=`✓`,r.appendChild(e)}if(n.shortcut){let e=document.createElement(`kbd`);e.className=`tcw-cmd-kbd`,e.textContent=n.shortcut,r.appendChild(e)}r.addEventListener(`click`,()=>this.select(t)),r.addEventListener(`mouseenter`,()=>{this.selectedIndex=t,this.updateSelection()}),this.list.appendChild(r)}}updateSelection(){if(!this.list)return;let e=this.list.querySelectorAll(`.tcw-cmd-item`);e.forEach((e,t)=>{e.classList.toggle(`tcw-selected`,t===this.selectedIndex)}),e[this.selectedIndex]?.scrollIntoView({block:`nearest`})}select(e){let t=this.filtered[e];if(t){switch(t.category){case`indicator`:this.callbacks.onIndicator(t.id);break;case`chartType`:this.callbacks.onChartType(t.id);break;case`drawing`:this.callbacks.onDrawingTool(t.id);break;case`timeframe`:this.callbacks.onTimeframe(t.id);break;case`action`:this.callbacks.onAction(t.id);break}this.close()}}handleKeydown(e){switch(e.key){case`Escape`:e.preventDefault(),this.close();break;case`ArrowDown`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex+1)%this.filtered.length,this.updateSelection());break;case`ArrowUp`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex-1+this.filtered.length)%this.filtered.length,this.updateSelection());break;case`Enter`:e.preventDefault(),this.select(this.selectedIndex);break}}categoryLabel(e){switch(e){case`indicator`:return`Indicators`;case`chartType`:return`Chart Types`;case`drawing`:return`Drawing Tools`;case`timeframe`:return`Timeframes`;case`action`:return`Actions`;default:return e}}destroy(){this.close()}},S=class{backdrop=null;modal=null;input=null;list=null;symbols=[];current=``;filtered=[];selectedIndex=0;callbacks;boundKeydown;pickOverride=null;constructor(e){this.callbacks=e,this.boundKeydown=this.handleKeydown.bind(this)}open(e,t,n){if(this.backdrop)return;this.pickOverride=n??null,this.symbols=e,this.current=t,this.filtered=e.map(e=>({symbol:e,score:0})),this.selectedIndex=Math.max(0,e.indexOf(t)),this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-cmd-palette`;let r=document.createElement(`div`);r.className=`tcw-cmd-header`;let i=document.createElement(`span`);i.className=`tcw-cmd-icon`,i.innerHTML=E(),r.appendChild(i),this.input=document.createElement(`input`),this.input.className=`tcw-cmd-input`,this.input.type=`text`,this.input.placeholder=`Search symbol… (e.g. BTC, ETH, AAPL)`,this.input.autocomplete=`off`,this.input.spellcheck=!1,this.input.addEventListener(`input`,()=>this.filter()),r.appendChild(this.input);let a=document.createElement(`span`);a.className=`tcw-cmd-hint`,a.textContent=`ESC`,r.appendChild(a),this.modal.appendChild(r),this.list=document.createElement(`div`),this.list.className=`tcw-cmd-list`,this.modal.appendChild(this.list);let o=document.createElement(`div`);o.className=`tcw-cmd-footer`,o.innerHTML=`<span>↑↓ Navigate</span><span>⏎ Open</span><span>Esc Close</span>`,this.modal.appendChild(o),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),this.renderList(),this.input.focus(),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.input=null,this.list=null,this.pickOverride=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}destroy(){this.close()}filter(){let e=(this.input?.value??``).toUpperCase().trim();e?this.filtered=this.symbols.map(t=>({symbol:t,score:C(t.toUpperCase(),e)})).filter(e=>e.score>0).sort((e,t)=>t.score-e.score):this.filtered=this.symbols.map(e=>({symbol:e,score:0})),this.selectedIndex=0,this.renderList()}renderList(){if(!this.list)return;if(this.list.innerHTML=``,this.filtered.length===0){let e=document.createElement(`div`);e.className=`tcw-cmd-empty`,e.textContent=`No symbols match`,this.list.appendChild(e);return}let e=(this.input?.value??``).toUpperCase().trim();for(let t=0;t<this.filtered.length;t++){let{symbol:n}=this.filtered[t],r=document.createElement(`button`);r.className=`tcw-cmd-item`,t===this.selectedIndex&&r.classList.add(`tcw-selected`),n===this.current&&r.classList.add(`tcw-active`);let i=document.createElement(`span`);if(i.className=`tcw-cmd-item-label`,i.innerHTML=w(n,e),r.appendChild(i),n===this.current){let e=document.createElement(`span`);e.className=`tcw-cmd-check`,e.textContent=`✓`,r.appendChild(e)}r.addEventListener(`click`,()=>this.pick(t)),r.addEventListener(`mouseenter`,()=>{this.selectedIndex=t,this.updateSelection()}),this.list.appendChild(r)}}updateSelection(){if(!this.list)return;let e=this.list.querySelectorAll(`.tcw-cmd-item`);e.forEach((e,t)=>e.classList.toggle(`tcw-selected`,t===this.selectedIndex)),e[this.selectedIndex]?.scrollIntoView({block:`nearest`})}pick(e){let t=this.filtered[e];if(!t)return;let n=this.pickOverride;n?n(t.symbol):this.callbacks.onPick(t.symbol),this.close()}handleKeydown(e){switch(e.key){case`Escape`:e.preventDefault(),this.close();break;case`ArrowDown`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex+1)%this.filtered.length,this.updateSelection());break;case`ArrowUp`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex-1+this.filtered.length)%this.filtered.length,this.updateSelection());break;case`Enter`:e.preventDefault(),this.pick(this.selectedIndex);break}}};function C(e,t){if(e===t)return 1e3;if(e.startsWith(t))return 500+(50-Math.min(50,e.length-t.length));if(e.includes(t))return 200+(50-Math.min(50,e.length-t.length));let n=0,r=-1,i=0;for(let a=0;a<e.length&&n<t.length;a++)e[a]===t[n]&&(r>=0&&(i+=a-r-1),r=a,n++);return n<t.length?0:100-Math.min(99,i)}function w(e,t){if(!t)return T(e);let n=e.toUpperCase(),r=``,i=0;for(let a=0;a<e.length;a++)i<t.length&&n[a]===t[i]?(r+=`<mark style="background:transparent;color:var(--tcw-accent);font-weight:700">${T(e[a])}</mark>`,i++):r+=T(e[a]);return r}function T(e){return e.replace(/[&<>"']/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`})[e])}function E(){return`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>`}var D=typeof navigator<`u`&&/mac|iphone|ipad|ipod/i.test(navigator.platform||navigator.userAgent)?`⌘`:`Ctrl`,O=[{title:`Search & navigation`,entries:[{keys:[D,`K`],label:`Command palette`},{keys:[D,`P`],label:`Symbol search`},{keys:[`?`],label:`Show this sheet`}]},{title:`Chart manipulation`,entries:[{keys:[`Shift`,`Drag`],label:`Measure tool (bars × price Δ)`},{keys:[`Drag`,`Price axis`],label:`Compress / expand vertical scale`},{keys:[`Drag`,`Time axis`],label:`Zoom time axis`},{keys:[`Double-click`,`Price axis`],label:`Re-enable auto-scale`},{keys:[`Double-click`,`Time axis`],label:`Fit content`},{keys:[`Scroll`],label:`Zoom around cursor`}]},{title:`Touch (mobile / tablet)`,entries:[{keys:[`1 finger`,`Drag`],label:`Pan / move crosshair`},{keys:[`2 fingers`,`Pinch`],label:`Zoom around midpoint`},{keys:[`Long-press`],label:`Pin OHLC tooltip at bar`},{keys:[`Drag`,`Axis strip`],label:`Scale price / time axis`}]},{title:`Keyboard`,entries:[{keys:[`←`,`→`],label:`Pan one bar`},{keys:[`+`,`−`],label:`Zoom in / out`},{keys:[`Home`],label:`Scroll to start`},{keys:[`End`],label:`Scroll to end (live edge)`},{keys:[`F`],label:`Fit content`}]},{title:`Drawing`,entries:[{keys:[D,`Z`],label:`Undo`},{keys:[D,`Shift`,`Z`],label:`Redo`},{keys:[`Esc`],label:`Cancel active drawing`}]}],k=class{backdrop=null;modal=null;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=e=>{e.key===`Escape`&&(e.preventDefault(),this.close())}}open(){if(this.backdrop)return;this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal tcw-hotkey-sheet`,this.modal.style.width=`640px`;let e=document.createElement(`div`);e.className=`tcw-modal-header`,e.innerHTML=`<h3>Keyboard shortcuts</h3>`;let t=document.createElement(`button`);t.className=`tcw-modal-close`,t.setAttribute(`aria-label`,`Close`),t.innerHTML=`×`,t.addEventListener(`click`,()=>this.close()),e.appendChild(t),this.modal.appendChild(e);let n=document.createElement(`div`);n.className=`tcw-modal-body`;let r=document.createElement(`div`);r.className=`tcw-hotkey-grid`;for(let e of O){let t=document.createElement(`section`);t.className=`tcw-hotkey-section`;let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e.title,t.appendChild(n);for(let n of e.entries){let e=document.createElement(`div`);e.className=`tcw-hotkey-row`;let r=document.createElement(`div`);r.className=`tcw-hotkey-keys`;for(let e=0;e<n.keys.length;e++){if(e>0){let e=document.createElement(`span`);e.className=`tcw-hotkey-sep`,e.textContent=`+`,r.appendChild(e)}let t=document.createElement(`kbd`);t.className=`tcw-cmd-kbd`,t.textContent=n.keys[e],r.appendChild(t)}e.appendChild(r);let i=document.createElement(`span`);i.className=`tcw-hotkey-label`,i.textContent=n.label,e.appendChild(i),t.appendChild(e)}r.appendChild(t)}n.appendChild(r),this.modal.appendChild(n);let i=document.createElement(`div`);i.className=`tcw-modal-footer`,i.innerHTML=`<span style="font-size:11px;color:var(--tcw-text-muted)">Press ? anytime to show this sheet</span>`;let a=document.createElement(`button`);a.className=`tcw-done-btn`,a.textContent=`Got it`,a.addEventListener(`click`,()=>this.close()),i.appendChild(a),this.modal.appendChild(i),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}destroy(){this.close()}},A=[.5,1,2,5,10,20,50,100],j=class{root=null;scrubber=null;progressLabel=null;playBtn=null;state=`stopped`;total=0;speed=5;callbacks;constructor(e){this.callbacks=e}mount(e,t){this.root||(this.total=Math.max(0,t.total),this.speed=t.speed??5,this.state=`paused`,this.root=document.createElement(`div`),this.root.className=`tcw-replay-bar`,this.root.innerHTML=this.markup(),e.appendChild(this.root),this.wireEvents(),this.syncUi())}unmount(){this.root?.remove(),this.root=null,this.scrubber=null,this.progressLabel=null,this.playBtn=null,this.state=`stopped`}isMounted(){return this.root!==null}setState(e){this.state=e,this.syncUi()}setProgress(e,t){this.total=t,this.scrubber&&(this.scrubber.max=String(Math.max(0,t-1)),this.scrubber.value=String(e)),this.progressLabel&&(this.progressLabel.textContent=`${e+1} / ${t}`)}destroy(){this.unmount()}markup(){let e=A.map(e=>`<option value="${e}"${e===this.speed?` selected`:``}>${e}× bars/s</option>`).join(``);return`
2365
+ <button class="tcw-replay-btn" data-act="close" title="Exit replay" aria-label="Exit replay">${I()}</button>
2366
+ <button class="tcw-replay-btn" data-act="stepBack" title="Step back" aria-label="Step back">${P()}</button>
2367
+ <button class="tcw-replay-btn tcw-replay-play" data-act="play" title="Play / pause" aria-label="Play / pause">${M()}</button>
2368
+ <button class="tcw-replay-btn" data-act="stepForward" title="Step forward" aria-label="Step forward">${F()}</button>
2369
+ <input type="range" class="tcw-replay-scrubber" data-act="seek" min="0" max="${Math.max(0,this.total-1)}" value="0" step="1" />
2370
+ <span class="tcw-replay-progress" data-tcw="progress">1 / ${this.total}</span>
2371
+ <select class="tcw-replay-speed" data-act="speed">${e}</select>
2372
+ `}wireEvents(){this.root&&(this.scrubber=this.root.querySelector(`input[data-act="seek"]`),this.progressLabel=this.root.querySelector(`[data-tcw="progress"]`),this.playBtn=this.root.querySelector(`button[data-act="play"]`),this.root.querySelector(`[data-act="close"]`)?.addEventListener(`click`,()=>this.callbacks.onClose()),this.root.querySelector(`[data-act="stepBack"]`)?.addEventListener(`click`,()=>this.callbacks.onStepBack()),this.root.querySelector(`[data-act="stepForward"]`)?.addEventListener(`click`,()=>this.callbacks.onStepForward()),this.playBtn?.addEventListener(`click`,()=>{this.state===`playing`?this.callbacks.onPause():this.callbacks.onPlay()}),this.scrubber?.addEventListener(`input`,()=>{let e=Number(this.scrubber.value);this.callbacks.onSeek(e)}),this.root.querySelector(`[data-act="speed"]`)?.addEventListener(`change`,e=>{let t=Number(e.target.value);this.speed=t,this.callbacks.onSpeedChange(t)}))}syncUi(){this.playBtn&&(this.playBtn.innerHTML=this.state===`playing`?N():M(),this.playBtn.title=this.state===`playing`?`Pause`:`Play`)}};function M(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7L8 5z"/></svg>`}function N(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>`}function P(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M6 6h2v12H6zM20 6L9 12l11 6V6z"/></svg>`}function F(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M4 6l11 6L4 18V6zM16 6h2v12h-2z"/></svg>`}function I(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg>`}var L=class{el;listEl;rowMap=new Map;entries=new Map;active=null;callbacks;constructor(e,t,n){this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-watchlist`;let r=document.createElement(`div`);r.className=`tcw-watchlist-header`,r.textContent=`Watchlist`,this.el.appendChild(r),this.listEl=document.createElement(`div`),this.listEl.className=`tcw-watchlist-list`,this.el.appendChild(this.listEl);for(let e of t)this.entries.set(e,{symbol:e}),this.appendRow(e);e.appendChild(this.el)}setSymbols(e){let t=new Set(e);for(let e of this.rowMap.keys())t.has(e)||this.removeRow(e);for(let t of e)this.rowMap.has(t)||(this.entries.set(t,this.entries.get(t)??{symbol:t}),this.appendRow(t))}setActive(e){if(this.active===e)return;this.active&&this.rowMap.has(this.active)&&this.rowMap.get(this.active).row.classList.remove(`tcw-watchlist-active`),this.active=e;let t=this.rowMap.get(e);t&&t.row.classList.add(`tcw-watchlist-active`)}setEntry(e,t){let n={...this.entries.get(e)??{symbol:e},...t};this.entries.set(e,n),this.renderRow(e)}destroy(){this.el.remove(),this.rowMap.clear(),this.entries.clear()}appendRow(e){let t=document.createElement(`div`);t.className=`tcw-watchlist-row`,t.tabIndex=0;let n=document.createElement(`div`);n.className=`tcw-watchlist-symbol`,n.textContent=R(e);let r=document.createElement(`canvas`);r.className=`tcw-watchlist-spark`,r.width=64,r.height=22;let i=document.createElement(`div`);i.className=`tcw-watchlist-stats`;let a=document.createElement(`span`);a.className=`tcw-watchlist-price`,a.textContent=`—`;let o=document.createElement(`span`);o.className=`tcw-watchlist-change`,o.textContent=``,i.appendChild(a),i.appendChild(o),t.appendChild(n),t.appendChild(r),t.appendChild(i),t.addEventListener(`click`,()=>this.callbacks.onSelect(e)),t.addEventListener(`keydown`,t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),this.callbacks.onSelect(e))}),this.listEl.appendChild(t),this.rowMap.set(e,{row:t,priceEl:a,changeEl:o,sparkCanvas:r}),e===this.active&&t.classList.add(`tcw-watchlist-active`)}removeRow(e){let t=this.rowMap.get(e);t&&(t.row.remove(),this.rowMap.delete(e))}renderRow(e){let t=this.rowMap.get(e),n=this.entries.get(e);if(!(!t||!n)){if(n.lastPrice!==void 0&&(t.priceEl.textContent=z(n.lastPrice)),n.lastPrice!==void 0&&n.refPrice!==void 0&&n.refPrice!==0){let e=n.lastPrice-n.refPrice,r=e/n.refPrice*100,i=e>=0?`+`:``;t.changeEl.textContent=`${i}${r.toFixed(2)}%`,t.changeEl.className=`tcw-watchlist-change ${e>=0?`tcw-up`:`tcw-down`}`}else t.changeEl.textContent=``;n.sparkline&&n.sparkline.length>=2&&B(t.sparkCanvas,n.sparkline,n.refPrice??n.sparkline[0])}}};function R(e){for(let t of[`USDT`,`USD`,`BTC`,`ETH`,`EUR`])if(e.length>t.length&&e.endsWith(t))return e.slice(0,-t.length)+`/`+t;return e}function z(e){if(e===0)return`0`;let t=Math.abs(e);return t>=1e3?e.toFixed(2):t>=1?e.toFixed(4):e.toPrecision(4)}function B(e,t,n){let r=e.getContext(`2d`);if(!r)return;let i=window.devicePixelRatio||1;e.width!==e.clientWidth*i&&(e.width=(e.clientWidth||64)*i,e.height=(e.clientHeight||22)*i);let a=e.width,o=e.height,s=1/0,c=-1/0;for(let e of t)e<s&&(s=e),e>c&&(c=e);let l=Math.max(c-s,1e-9),u=t[t.length-1]>=n?`#26a17b`:`#f23645`;r.clearRect(0,0,a,o),r.lineWidth=1.4*i,r.strokeStyle=u,r.beginPath();let d=a/(t.length-1);for(let e=0;e<t.length;e++){let n=e*d,i=o-(t[e]-s)/l*(o-4)-2;e===0?r.moveTo(n,i):r.lineTo(n,i)}r.stroke()}var V=[{value:`crossing`,label:`Crossing`},{value:`crossingUp`,label:`Crossing up`},{value:`crossingDown`,label:`Crossing down`},{value:`greaterThan`,label:`Greater than`},{value:`lessThan`,label:`Less than`}],H=new Map(V.map(e=>[e.value,e.label]));function U(e){return Math.round(e*1e6)/1e6}function W(e){let t=Math.abs(e);return t>=1e3||t>=1?e.toFixed(2):e.toPrecision(4)}var G=class{el;listEl;priceInput;conditionSelect;sourceSelect;messageInput;emptyEl;callbacks;open=!1;alerts=[];sources=[{channel:`price`,label:`Price`}];constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-alerts-panel`,this.el.hidden=!0;let n=document.createElement(`div`);n.className=`tcw-alerts-header`;let r=document.createElement(`span`);r.textContent=`Price Alerts`;let i=document.createElement(`button`);i.className=`tcw-alerts-close`,i.type=`button`,i.setAttribute(`aria-label`,`Close alerts`),i.innerHTML=_(`x`,14),i.addEventListener(`click`,()=>this.close()),n.appendChild(r),n.appendChild(i),this.el.appendChild(n);let a=document.createElement(`form`);a.className=`tcw-alerts-form`,this.sourceSelect=document.createElement(`select`),this.sourceSelect.className=`tcw-alerts-source`,this.sourceSelect.addEventListener(`change`,()=>this.prefillPrice()),this.priceInput=document.createElement(`input`),this.priceInput.type=`number`,this.priceInput.step=`any`,this.priceInput.placeholder=`Value`,this.priceInput.className=`tcw-alerts-price`,this.priceInput.required=!0,this.conditionSelect=document.createElement(`select`),this.conditionSelect.className=`tcw-alerts-condition`;for(let e of V){let t=document.createElement(`option`);t.value=e.value,t.textContent=e.label,this.conditionSelect.appendChild(t)}this.messageInput=document.createElement(`input`),this.messageInput.type=`text`,this.messageInput.placeholder=`Note (optional)`,this.messageInput.className=`tcw-alerts-message`;let o=document.createElement(`button`);o.type=`submit`,o.className=`tcw-alerts-add`,o.innerHTML=`${_(`plus`,14)}<span>Add alert</span>`,a.appendChild(this.sourceSelect),a.appendChild(this.priceInput),a.appendChild(this.conditionSelect),a.appendChild(this.messageInput),a.appendChild(o),a.addEventListener(`submit`,e=>{e.preventDefault(),this.submitForm()}),this.el.appendChild(a),this.listEl=document.createElement(`div`),this.listEl.className=`tcw-alerts-list`,this.el.appendChild(this.listEl),this.emptyEl=document.createElement(`div`),this.emptyEl.className=`tcw-alerts-empty`,this.emptyEl.textContent=`No alerts yet. Add one above, or right-click the chart.`,this.listEl.appendChild(this.emptyEl),this.renderSources(),e.appendChild(this.el)}setSources(e){this.sources=e.length>0?e:[{channel:`price`,label:`Price`}],this.renderSources()}renderSources(){let e=this.sourceSelect.value||`price`;this.sourceSelect.replaceChildren();for(let e of this.sources){let t=document.createElement(`option`);t.value=e.channel,t.textContent=e.label,this.sourceSelect.appendChild(t)}this.sourceSelect.value=this.sources.some(t=>t.channel===e)?e:`price`}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1,this.priceInput.value===``&&this.prefillPrice()}prefillPrice(){let e=this.callbacks.getChannelValue(this.sourceSelect.value||`price`);this.priceInput.value=e===null?``:String(U(e))}close(){this.open=!1,this.el.hidden=!0}setAlerts(e){this.alerts=e,this.renderList()}destroy(){this.el.remove()}submitForm(){let e=Number(this.priceInput.value);if(!Number.isFinite(e))return;let t=this.conditionSelect.value,n=this.messageInput.value.trim()||void 0,r=this.sourceSelect.value||`price`,i=this.sources.find(e=>e.channel===r)?.label??`Price`;this.callbacks.onAdd(e,t,n,r,i),this.messageInput.value=``,this.prefillPrice()}renderList(){if(this.listEl.replaceChildren(),this.alerts.length===0){this.listEl.appendChild(this.emptyEl);return}for(let e of[...this.alerts].reverse()){let t=document.createElement(`div`);t.className=`tcw-alerts-row`+(e.triggered?` tcw-alerts-triggered`:``);let n=document.createElement(`div`);n.className=`tcw-alerts-info`;let r=document.createElement(`div`);r.className=`tcw-alerts-row-main`;let i=H.get(e.condition)??e.condition,a=e.channel&&e.channel!==`price`,o=a?W(e.price):this.callbacks.formatPrice(e.price);if(r.textContent=`${a&&e.label?`${e.label} `:``}${i} ${o}`,n.appendChild(r),e.message){let t=document.createElement(`div`);t.className=`tcw-alerts-row-note`,t.textContent=e.message,n.appendChild(t)}if(e.triggered){let e=document.createElement(`span`);e.className=`tcw-alerts-badge`,e.textContent=`triggered`,r.appendChild(e)}let s=document.createElement(`button`);s.type=`button`,s.className=`tcw-alerts-del`,s.setAttribute(`aria-label`,`Delete alert`),s.innerHTML=_(`trash`,14),s.addEventListener(`click`,()=>this.callbacks.onRemove(e.id)),t.appendChild(n),t.appendChild(s),this.listEl.appendChild(t)}}},K=class{el;indicatorsEl;drawingsEl;compareEl=null;callbacks;open=!1;constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-tree-panel`,this.el.hidden=!0;let n=document.createElement(`div`);n.className=`tcw-tree-header`;let r=document.createElement(`span`);r.textContent=`Objects`;let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-tree-close`,i.setAttribute(`aria-label`,`Close objects`),i.innerHTML=_(`x`,14),i.addEventListener(`click`,()=>this.close()),n.appendChild(r),n.appendChild(i),this.el.appendChild(n),this.indicatorsEl=this.makeSection(`Indicators`),this.drawingsEl=this.makeSection(`Drawings`),this.callbacks.onAddCompare&&(this.compareEl=this.makeSection(`Compare`,()=>this.callbacks.onAddCompare?.())),e.appendChild(this.el)}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1}close(){this.open=!1,this.el.hidden=!0}destroy(){this.el.remove()}setObjects(e,t,n=[]){this.renderIndicators(e),this.renderDrawings(t),this.renderCompares(n)}makeSection(e,t){let n=document.createElement(`div`);n.className=`tcw-tree-section`;let r=document.createElement(`div`);r.className=`tcw-tree-section-head`;let i=document.createElement(`span`);if(i.textContent=e,r.appendChild(i),t){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-tree-add`,n.setAttribute(`aria-label`,`Add ${e.toLowerCase()}`),n.title=`Add ${e.toLowerCase()}`,n.innerHTML=_(`plus`,13),n.addEventListener(`click`,t),r.appendChild(n)}let a=document.createElement(`div`);return a.className=`tcw-tree-list`,n.appendChild(r),n.appendChild(a),this.el.appendChild(n),a}renderIndicators(e){if(this.indicatorsEl.replaceChildren(),e.length===0){this.indicatorsEl.appendChild(this.emptyRow(`No indicators`));return}for(let t of e){let e=this.row(t.name);t.visible||e.classList.add(`tcw-tree-hidden`);let n=document.createElement(`div`);n.className=`tcw-tree-actions`,this.callbacks.onToggleIndicatorVisible&&n.appendChild(this.iconButton(t.visible?`eye`:`eyeOff`,t.visible?`Hide`:`Show`,``,()=>this.callbacks.onToggleIndicatorVisible?.(t.instanceId,!t.visible))),this.callbacks.onConfigureIndicator&&n.appendChild(this.iconButton(`settings`,`Indicator settings`,``,()=>this.callbacks.onConfigureIndicator?.(t.instanceId))),n.appendChild(this.iconButton(`trash`,`Remove indicator`,`tcw-tree-del`,()=>this.callbacks.onRemoveIndicator(t.instanceId))),e.appendChild(n),this.indicatorsEl.appendChild(e)}}renderDrawings(e){if(this.drawingsEl.replaceChildren(),e.length===0){this.drawingsEl.appendChild(this.emptyRow(`No drawings`));return}for(let t of e){let e=this.row(t.label);t.visible||e.classList.add(`tcw-tree-hidden`);let n=document.createElement(`div`);n.className=`tcw-tree-actions`,n.appendChild(this.iconButton(t.visible?`eye`:`eyeOff`,t.visible?`Hide`:`Show`,``,()=>this.callbacks.onToggleDrawingVisible(t.id,!t.visible))),n.appendChild(this.iconButton(t.locked?`lock`:`unlock`,t.locked?`Unlock`:`Lock`,t.locked?`tcw-tree-on`:``,()=>this.callbacks.onToggleDrawingLocked(t.id,!t.locked))),n.appendChild(this.iconButton(`trash`,`Remove drawing`,`tcw-tree-del`,()=>this.callbacks.onRemoveDrawing(t.id))),e.appendChild(n),this.drawingsEl.appendChild(e)}}renderCompares(e){if(this.compareEl){if(this.compareEl.replaceChildren(),e.length===0){this.compareEl.appendChild(this.emptyRow(`No comparisons`));return}for(let t of e){let e=this.row(t.label),n=document.createElement(`span`);n.className=`tcw-tree-dot`,n.style.background=t.color,e.insertBefore(n,e.firstChild),this.callbacks.onRemoveCompare&&e.appendChild(this.iconButton(`trash`,`Remove comparison`,`tcw-tree-del`,()=>this.callbacks.onRemoveCompare?.(t.id))),this.compareEl.appendChild(e)}}}row(e){let t=document.createElement(`div`);t.className=`tcw-tree-row`;let n=document.createElement(`span`);return n.className=`tcw-tree-name`,n.textContent=e,n.title=e,t.appendChild(n),t}emptyRow(e){let t=document.createElement(`div`);return t.className=`tcw-tree-empty`,t.textContent=e,t}iconButton(e,t,n,r){let i=document.createElement(`button`);return i.type=`button`,i.className=`tcw-tree-btn ${n}`.trim(),i.setAttribute(`aria-label`,t),i.title=t,i.innerHTML=_(e,14),i.addEventListener(`click`,r),i}},q={trendLine:`Trend Line`,ray:`Ray`,extendedLine:`Extended Line`,horizontalLine:`Horizontal Line`,verticalLine:`Vertical Line`,rectangle:`Rectangle`,ellipse:`Ellipse`,triangle:`Triangle`,arrow:`Arrow`,parallelChannel:`Parallel Channel`,regressionChannel:`Regression Channel`,pitchfork:`Pitchfork`,fibRetracement:`Fib Retracement`,fibExtension:`Fib Extension`,fibTimeZones:`Fib Time Zones`,gannBox:`Gann Box`,gannFan:`Gann Fan`,elliottWave:`Elliott Wave`,priceRange:`Price Range`,dateRange:`Date Range`,measure:`Measure`,textAnnotation:`Text`,anchoredVWAP:`Anchored VWAP`,volumeProfileRange:`Volume Profile`};function se(e){return q[e]??e}var ce=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function le(e){return e.replace(/_/g,` `).replace(/([a-z0-9])([A-Z])/g,`$1 $2`).replace(/^./,e=>e.toUpperCase())}var ue=class{backdrop;modal;bodyEl;titleEl;callbacks;target=null;draft={};constructor(e,t){this.callbacks=t,this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.hidden=!0,this.backdrop.addEventListener(`click`,e=>{e.target===this.backdrop&&this.close()}),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal tcw-modal-narrow`;let n=document.createElement(`div`);n.className=`tcw-modal-header`,this.titleEl=document.createElement(`h3`),this.titleEl.textContent=`Indicator`;let r=document.createElement(`button`);r.className=`tcw-modal-close`,r.setAttribute(`aria-label`,`Close`),r.innerHTML=_(`x`,16),r.addEventListener(`click`,()=>this.close()),n.appendChild(this.titleEl),n.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`;let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.resetDefaults());let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>this.close()),i.appendChild(a),i.appendChild(o),this.modal.appendChild(n),this.modal.appendChild(this.bodyEl),this.modal.appendChild(i),this.backdrop.appendChild(this.modal),e.appendChild(this.backdrop)}open(e){this.target=e,this.titleEl.textContent=`${e.name} settings`,this.draft={},this.renderFields(),this.backdrop.hidden=!1}close(){this.backdrop.hidden=!0,this.target=null,this.callbacks.onClose()}isOpen(){return!this.backdrop.hidden}destroy(){this.backdrop.remove()}currentValue(e){if(e in this.draft)return this.draft[e];let t=this.target?.params[e],n=this.target?.defaults[e];return t??n}setValue(e,t){this.target&&(this.draft[e]=t,this.callbacks.onApply(this.target.instanceId,{...this.draft}))}resetDefaults(){if(!this.target)return;let e={};for(let[t,n]of Object.entries(this.target.defaults))e[t]=n;this.draft=e,this.callbacks.onApply(this.target.instanceId,{...e}),this.renderFields()}renderFields(){if(this.bodyEl.replaceChildren(),!this.target)return;let e=document.createElement(`div`);e.className=`tcw-settings-section`;let t=Object.keys(this.target.defaults);if(t.length===0){let t=document.createElement(`div`);t.className=`tcw-settings-label`,t.textContent=`This indicator has no adjustable parameters.`,e.appendChild(t)}for(let n of t)e.appendChild(this.fieldRow(n));this.bodyEl.appendChild(e)}fieldRow(e){let t=document.createElement(`div`);t.className=`tcw-settings-row`;let n=document.createElement(`span`);n.className=`tcw-settings-label`,n.textContent=le(e),t.appendChild(n);let r=this.currentValue(e),i=typeof(this.target?.defaults[e]??r);return i===`boolean`?t.appendChild(this.toggleControl(e,!!r)):i===`number`?t.appendChild(this.numberControl(e,Number(r))):typeof r==`string`&&ce.test(r)?t.appendChild(this.colorControl(e,r)):t.appendChild(this.textControl(e,String(r??``))),t}toggleControl(e,t){let n=document.createElement(`button`);return n.className=`tcw-toggle${t?` tcw-on`:``}`,n.type=`button`,n.addEventListener(`click`,()=>{let t=!n.classList.contains(`tcw-on`);n.classList.toggle(`tcw-on`,t),this.setValue(e,t)}),n}numberControl(e,t){let n=document.createElement(`input`);return n.type=`number`,n.className=`tcw-indi-input`,n.value=String(t),n.step=Number.isInteger(t)?`1`:`0.1`,n.addEventListener(`change`,()=>{let t=Number(n.value);Number.isFinite(t)&&this.setValue(e,t)}),n}colorControl(e,t){let n=document.createElement(`input`);return n.type=`color`,n.className=`tcw-indi-color`,n.value=t.length===4?de(t):t,n.addEventListener(`input`,()=>this.setValue(e,n.value)),n}textControl(e,t){let n=document.createElement(`input`);return n.type=`text`,n.className=`tcw-indi-input`,n.value=t,n.addEventListener(`change`,()=>this.setValue(e,n.value)),n}};function de(e){let t=e[1],n=e[2],r=e[3];return`#${t}${t}${n}${n}${r}${r}`}function fe(){try{return typeof localStorage<`u`?localStorage:null}catch{return null}}var pe=[`color`,`lineWidth`,`lineStyle`,`fillColor`,`fillOpacity`,`fontSize`];function J(e){if(!e||typeof e!=`object`)return{};let t={},n=e;for(let e of pe)n[e]!==void 0&&(t[e]=n[e]);return t}var me=class{templates=[];constructor(e=`tcw:draw-templates`,t=fe()){this.storageKey=e,this.storage=t,this.load()}list(){return this.templates.map(e=>({name:e.name,style:{...e.style}}))}get(e){let t=this.templates.find(t=>t.name===e);return t?{name:t.name,style:{...t.style}}:null}save(e,t){let n=e.trim();if(!n)return;let r=J(t);this.templates=this.templates.filter(e=>e.name!==n),this.templates.push({name:n,style:r}),this.persist()}remove(e){let t=this.templates.filter(t=>t.name!==e);t.length!==this.templates.length&&(this.templates=t,this.persist())}clear(){this.templates=[],this.persist()}load(){if(this.storage)try{let e=this.storage.getItem(this.storageKey);if(!e)return;let t=JSON.parse(e);if(!Array.isArray(t))return;this.templates=t.filter(e=>e&&typeof e.name==`string`).map(e=>({name:e.name,style:J(e.style)}))}catch{}}persist(){if(this.storage)try{this.storage.setItem(this.storageKey,JSON.stringify(this.templates))}catch{}}},he=[`#2962ff`,`#089981`,`#f23645`,`#ff9800`,`#ab47bc`,`#26c6da`,`#ffffff`,`#787b86`],ge=[1,2,3,4],_e=[`solid`,`dashed`,`dotted`],ve=class{el;templatesEl;nameInput;callbacks;store;open=!1;constructor(e,t,n){this.callbacks=t,this.store=n,this.el=document.createElement(`div`),this.el.className=`tcw-style-panel`,this.el.hidden=!0;let r=document.createElement(`div`);r.className=`tcw-style-header`;let i=document.createElement(`span`);i.textContent=`Drawing Style`;let a=document.createElement(`button`);a.type=`button`,a.className=`tcw-style-close`,a.setAttribute(`aria-label`,`Close`),a.innerHTML=_(`x`,14),a.addEventListener(`click`,()=>this.close()),r.appendChild(i),r.appendChild(a),this.el.appendChild(r),this.el.appendChild(this.colorRow()),this.el.appendChild(this.widthRow()),this.el.appendChild(this.lineStyleRow());let o=document.createElement(`div`);o.className=`tcw-style-subhead`,o.textContent=`Templates`,this.el.appendChild(o);let s=document.createElement(`div`);s.className=`tcw-style-save`,this.nameInput=document.createElement(`input`),this.nameInput.type=`text`,this.nameInput.placeholder=`Template name`,this.nameInput.className=`tcw-style-name`;let c=document.createElement(`button`);c.type=`button`,c.className=`tcw-style-savebtn`,c.innerHTML=`${_(`plus`,13)}<span>Save</span>`,c.addEventListener(`click`,()=>this.saveTemplate()),s.appendChild(this.nameInput),s.appendChild(c),this.el.appendChild(s),this.templatesEl=document.createElement(`div`),this.templatesEl.className=`tcw-style-templates`,this.el.appendChild(this.templatesEl),e.appendChild(this.el),this.renderTemplates()}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1,this.syncActiveControls(),this.renderTemplates()}close(){this.open=!1,this.el.hidden=!0}destroy(){this.el.remove()}colorRow(){let e=document.createElement(`div`);e.className=`tcw-style-row tcw-style-colors`;for(let t of he){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-swatch`,n.style.background=t,n.dataset.color=t,n.setAttribute(`aria-label`,t),n.addEventListener(`click`,()=>this.applyStyle({color:t})),e.appendChild(n)}let t=document.createElement(`input`);return t.type=`color`,t.className=`tcw-style-picker`,t.addEventListener(`input`,()=>this.applyStyle({color:t.value})),e.appendChild(t),e}widthRow(){let e=document.createElement(`div`);e.className=`tcw-style-row tcw-style-widths`;for(let t of ge){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-width`,n.dataset.width=String(t);let r=document.createElement(`span`);r.style.height=`${t}px`,n.appendChild(r),n.addEventListener(`click`,()=>this.applyStyle({lineWidth:t})),e.appendChild(n)}return e}lineStyleRow(){let e=document.createElement(`div`);e.className=`tcw-style-row tcw-style-dashes`;for(let t of _e){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-dash`,n.dataset.linestyle=t,n.textContent=t===`solid`?`──`:t===`dashed`?`╌╌`:`┄┄`,n.title=t,n.addEventListener(`click`,()=>this.applyStyle({lineStyle:t})),e.appendChild(n)}return e}applyStyle(e){this.callbacks.onStyleChange(e),this.syncActiveControls()}syncActiveControls(){let e=this.callbacks.getStyle();this.el.querySelectorAll(`.tcw-style-swatch`).forEach(t=>{t.classList.toggle(`tcw-on`,t.dataset.color?.toLowerCase()===e.color?.toLowerCase())}),this.el.querySelectorAll(`.tcw-style-width`).forEach(t=>{t.classList.toggle(`tcw-on`,Number(t.dataset.width)===e.lineWidth)}),this.el.querySelectorAll(`.tcw-style-dash`).forEach(t=>{t.classList.toggle(`tcw-on`,t.dataset.linestyle===e.lineStyle)})}saveTemplate(){let e=this.nameInput.value.trim();e&&(this.store.save(e,this.callbacks.getStyle()),this.nameInput.value=``,this.renderTemplates())}renderTemplates(){this.templatesEl.replaceChildren();let e=this.store.list();if(e.length===0){let e=document.createElement(`div`);e.className=`tcw-style-empty`,e.textContent=`No saved templates`,this.templatesEl.appendChild(e);return}for(let t of e){let e=document.createElement(`div`);e.className=`tcw-style-template`;let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-apply`;let r=document.createElement(`span`);r.className=`tcw-style-tdot`,r.style.background=t.style.color??`var(--tcw-text-muted)`;let i=document.createElement(`span`);i.textContent=t.name,n.appendChild(r),n.appendChild(i),n.addEventListener(`click`,()=>{this.callbacks.onStyleChange({...t.style}),this.syncActiveControls()});let a=document.createElement(`button`);a.type=`button`,a.className=`tcw-style-tdel`,a.setAttribute(`aria-label`,`Delete template`),a.innerHTML=_(`trash`,13),a.addEventListener(`click`,()=>{this.store.remove(t.name),this.renderTemplates()}),e.appendChild(n),e.appendChild(a),this.templatesEl.appendChild(e)}}};function ye(){try{return typeof localStorage<`u`?localStorage:null}catch{return null}}var be=class{favorites=[];constructor(e=`tcw:draw-favorites`,t=ye()){this.storageKey=e,this.storage=t,this.load()}list(){return[...this.favorites]}has(e){return this.favorites.includes(e)}add(e){!e||this.favorites.includes(e)||(this.favorites=[...this.favorites,e],this.persist())}remove(e){this.favorites.includes(e)&&(this.favorites=this.favorites.filter(t=>t!==e),this.persist())}toggle(e){return this.has(e)?(this.remove(e),!1):(this.add(e),!0)}seedDefaults(e){this.favorites.length>0||(this.favorites=[...new Set(e.filter(Boolean))],this.persist())}load(){if(this.storage)try{let e=this.storage.getItem(this.storageKey);if(!e)return;let t=JSON.parse(e);Array.isArray(t)&&(this.favorites=[...new Set(t.filter(e=>typeof e==`string`))])}catch{}}persist(){if(this.storage)try{this.storage.setItem(this.storageKey,JSON.stringify(this.favorites))}catch{}}},xe=class{el;labelEl;callbacks;visible=!1;constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-bracket-bar`,this.el.hidden=!0,this.labelEl=document.createElement(`span`),this.labelEl.className=`tcw-bracket-label`,this.el.appendChild(this.labelEl);let n=document.createElement(`span`);n.className=`tcw-bracket-hint`,n.textContent=`drag lines to adjust`,this.el.appendChild(n);let r=document.createElement(`button`);r.type=`button`,r.className=`tcw-bracket-cancel`,r.innerHTML=`${_(`x`,14)}<span>Cancel</span>`,r.addEventListener(`click`,()=>this.callbacks.onCancel());let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-bracket-confirm`,i.innerHTML=`${_(`check`,14)}<span>Place</span>`,i.addEventListener(`click`,()=>this.callbacks.onConfirm()),this.el.appendChild(r),this.el.appendChild(i),e.appendChild(this.el)}show(e){this.visible=!0,this.labelEl.textContent=e===`buy`?`Long bracket`:`Short bracket`,this.labelEl.dataset.side=e,this.el.hidden=!1}hide(){this.visible=!1,this.el.hidden=!0}isVisible(){return this.visible}destroy(){this.el.remove()}},Se=class{options;audioCtx=null;audioEl=null;permissionAsked=!1;constructor(e={}){if(this.options=e,typeof e.sound==`string`)try{this.audioEl=new Audio(e.sound),this.audioEl.preload=`auto`}catch{this.audioEl=null}e.desktop&&this.ensurePermission()}setOptions(e){this.options={...this.options,...e}}notify(e){this.options.sound&&this.playSound(),this.options.desktop&&this.showDesktop(e)}playSound(){if(this.audioEl){this.audioEl.currentTime=0,this.audioEl.play().catch(()=>{});return}this.beep()}beep(){try{let e=window.AudioContext??window.webkitAudioContext;if(!e)return;this.audioCtx||=new e;let t=this.audioCtx,n=t.currentTime,r=t.createGain();r.gain.setValueAtTime(1e-4,n),r.gain.exponentialRampToValueAtTime(.2,n+.01),r.gain.exponentialRampToValueAtTime(1e-4,n+.35),r.connect(t.destination);let i=t.createOscillator();i.type=`sine`,i.frequency.setValueAtTime(880,n),i.frequency.setValueAtTime(1320,n+.16),i.connect(r),i.start(n),i.stop(n+.36)}catch{}}ensurePermission(){this.permissionAsked||(this.permissionAsked=!0,!(typeof Notification>`u`)&&Notification.permission===`default`&&Notification.requestPermission().catch(()=>{}))}showDesktop(e){if(!(typeof Notification>`u`)){if(Notification.permission!==`granted`){this.ensurePermission();return}try{new Notification(this.options.title??`Price alert`,{body:e})}catch{}}}destroy(){try{this.audioCtx?.close()}catch{}this.audioCtx=null,this.audioEl=null}};function Ce(e,t=12){let n=[...e.asks].sort((e,t)=>e.price-t.price).slice(0,t),r=[...e.bids].sort((e,t)=>t.price-e.price).slice(0,t),i=n.length>0?n[0].price:null,a=r.length>0?r[0].price:null,o=i!==null&&a!==null?(i+a)/2:null,s=new Map,c=e=>{let t=s.get(e);return t||(t={price:e,bidVolume:0,askVolume:0},s.set(e,t)),t};for(let e of n)c(e.price).askVolume+=e.volume;for(let e of r)c(e.price).bidVolume+=e.volume;let l=[...s.values()].sort((e,t)=>t.price-e.price),u=0;for(let e of l)u=Math.max(u,e.bidVolume,e.askVolume);return{rows:l,maxVolume:u,mid:o}}var we=class{el;bodyEl;callbacks;open=!1;levels;constructor(e,t,n=12){this.callbacks=t,this.levels=n,this.el=document.createElement(`div`),this.el.className=`tcw-ladder`,this.el.hidden=!0;let r=document.createElement(`div`);r.className=`tcw-ladder-header`;let i=document.createElement(`span`);i.textContent=`Depth Ladder`;let a=document.createElement(`button`);a.type=`button`,a.className=`tcw-ladder-close`,a.setAttribute(`aria-label`,`Close`),a.innerHTML=_(`x`,14),a.addEventListener(`click`,()=>this.close()),r.appendChild(i),r.appendChild(a),this.el.appendChild(r);let o=document.createElement(`div`);o.className=`tcw-ladder-cols`,o.innerHTML=`<span>Bid</span><span>Price</span><span>Ask</span>`,this.el.appendChild(o),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-ladder-body`,this.el.appendChild(this.bodyEl),e.appendChild(this.el)}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1}close(){this.open=!1,this.el.hidden=!0}setData(e){if(!e){this.renderEmpty();return}this.render(Ce(e,this.levels))}destroy(){this.el.remove()}renderEmpty(){this.bodyEl.replaceChildren();let e=document.createElement(`div`);e.className=`tcw-ladder-empty`,e.textContent=`No order-book data`,this.bodyEl.appendChild(e)}render(e){if(this.bodyEl.replaceChildren(),e.rows.length===0){this.renderEmpty();return}let t=e.maxVolume>0?1/e.maxVolume:0;for(let n of e.rows){let e=n.askVolume>0,r=document.createElement(`div`);r.className=`tcw-ladder-row`;let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-ladder-cell tcw-ladder-bid`,n.bidVolume>0?(i.textContent=Y(n.bidVolume),i.style.setProperty(`--w`,`${(n.bidVolume*t*100).toFixed(1)}%`),i.title=`Sell @ ${this.callbacks.formatPrice(n.price)}`,i.addEventListener(`click`,()=>this.callbacks.onTrade(`sell`,n.price))):i.disabled=!0;let a=document.createElement(`div`);a.className=`tcw-ladder-price ${e?`tcw-ask`:`tcw-bid`}`,a.textContent=this.callbacks.formatPrice(n.price);let o=document.createElement(`button`);o.type=`button`,o.className=`tcw-ladder-cell tcw-ladder-ask`,n.askVolume>0?(o.textContent=Y(n.askVolume),o.style.setProperty(`--w`,`${(n.askVolume*t*100).toFixed(1)}%`),o.title=`Buy @ ${this.callbacks.formatPrice(n.price)}`,o.addEventListener(`click`,()=>this.callbacks.onTrade(`buy`,n.price))):o.disabled=!0,r.appendChild(i),r.appendChild(a),r.appendChild(o),this.bodyEl.appendChild(r)}}};function Y(e){return e>=1e3?(e/1e3).toFixed(1)+`k`:e>=1?e.toFixed(2).replace(/\.00$/,``):e.toPrecision(2)}var Te=class{el;bodyEl;callbacks;open=!1;constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-datawin`,this.el.hidden=!0;let n=document.createElement(`div`);n.className=`tcw-datawin-header`;let r=document.createElement(`span`);r.textContent=`Data Window`;let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-datawin-close`,i.setAttribute(`aria-label`,`Close`),i.innerHTML=_(`x`,14),i.addEventListener(`click`,()=>this.close()),n.appendChild(r),n.appendChild(i),this.el.appendChild(n),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-datawin-body`,this.el.appendChild(this.bodyEl),e.appendChild(this.el)}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1}close(){this.open=!1,this.el.hidden=!0}destroy(){this.el.remove()}render(e){if(!this.open)return;if(this.bodyEl.replaceChildren(),!e.ohlc){let e=document.createElement(`div`);e.className=`tcw-datawin-empty`,e.textContent=`Hover the chart`,this.bodyEl.appendChild(e);return}let t=this.callbacks.formatPrice,n=e.ohlc;this.bodyEl.appendChild(this.row(`Open`,t(n.open))),this.bodyEl.appendChild(this.row(`High`,t(n.high))),this.bodyEl.appendChild(this.row(`Low`,t(n.low))),this.bodyEl.appendChild(this.row(`Close`,t(n.close)));let r=e.change>0?`up`:e.change<0?`down`:``,i=e.change>0?`+`:``;this.bodyEl.appendChild(this.row(`Change`,`${i}${t(e.change)} (${i}${e.changePct.toFixed(2)}%)`,r)),this.bodyEl.appendChild(this.row(`Volume`,De(n.volume)));for(let t of e.indicators){let e=document.createElement(`div`);e.className=`tcw-datawin-sub`,e.textContent=t.name,this.bodyEl.appendChild(e);for(let e of t.values)this.bodyEl.appendChild(this.row(e.key,Ee(e.value)))}}row(e,t,n=``){let r=document.createElement(`div`);r.className=`tcw-datawin-row`;let i=document.createElement(`span`);i.className=`tcw-datawin-label`,i.textContent=e;let a=document.createElement(`span`);return a.className=`tcw-datawin-value${n?` tcw-${n}`:``}`,a.textContent=t,r.appendChild(i),r.appendChild(a),r}};function Ee(e){if(!Number.isFinite(e))return`—`;let t=Math.abs(e);return t>=1e3?e.toFixed(2):t>=1?e.toFixed(4):e.toPrecision(4)}function De(e){return e>=1e9?(e/1e9).toFixed(2)+`B`:e>=1e6?(e/1e6).toFixed(2)+`M`:e>=1e3?(e/1e3).toFixed(2)+`K`:e.toFixed(0)}var X=globalThis.Buffer;function Oe(e){if(X)return X.from(e,`utf8`).toString(`base64`);let t=new TextEncoder().encode(e),n=``;for(let e of t)n+=String.fromCharCode(e);return btoa(n)}function ke(e){if(X)return X.from(e,`base64`).toString(`utf8`);let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return new TextDecoder().decode(n)}function Z(e){return e.replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function Ae(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);return t+(t.length%4==0?``:`=`.repeat(4-t.length%4))}function je(e){return Z(Oe(JSON.stringify(e)))}function Me(e){if(!e)return null;try{let t=ke(Ae(e)),n=JSON.parse(t);return!n||n.v!==1||typeof n.symbol!=`string`?null:{v:1,symbol:n.symbol,timeframe:n.timeframe,chartType:n.chartType,scaleMode:n.scaleMode??`regular`,indicators:Array.isArray(n.indicators)?n.indicators:[],drawings:Array.isArray(n.drawings)?n.drawings:[]}}catch{return null}}var Q=`tcw`;function Ne(e){let t=e.startsWith(`#`)?e.slice(1):e;for(let e of t.split(`&`)){let t=e.indexOf(`=`);if(t>0&&e.slice(0,t)===Q)return decodeURIComponent(e.slice(t+1))}return null}function Pe(e,t){let[n]=e.split(`#`);return`${n}#${Q}=${t}`}var $=[`#f7931a`,`#627eea`,`#26a17b`,`#e84142`,`#8247e5`,`#f3ba2f`],Fe=class{chart;state;toolbar=null;sidebar=null;settings=null;statusBar=null;commandPalette=null;symbolSearch=null;hotkeySheet=null;replayBar=null;dragDrop=null;alertsPanel=null;objectTree=null;indicatorSettings=null;drawingStyle=null;bracketBar=null;alertNotifier=null;depthLadder=null;dataWindow=null;lastHoverIndex=null;favoritesStore=new be;watchlist=null;watchlistSparkBuffer=new Map;sessionRefPrice=null;watchlistInterval=null;replayOriginalData=null;replayPollInterval=null;replaySpeed=5;layoutKeyPrefix=null;layoutDebounceMs=1500;activeLayoutKey=null;root;chartContainer;destroyed=!1;options;symbols;settingsState;adapter=null;boundGlobalKeydown=null;baseSeries=null;baseTimeframeMs=0;compares=[];constructor(t,n={}){if(this.options=n,this.symbols=n.symbols??l,this.settingsState={...u},n.persistLayouts){let e=n.persistLayouts===!0?{}:n.persistLayouts;this.layoutKeyPrefix=e.keyPrefix??`tcw:layout:`,this.layoutDebounceMs=e.debounceMs??1500}let r=this.resolveIsDark(n.theme),d=this.resolveTheme(n.theme);this.state={symbol:n.symbol??this.symbols[0]??`BTCUSDT`,timeframe:n.timeframe??`5m`,chartType:n.chartOptions?.chartType??`candlestick`,isDark:r,activeIndicators:new Map,activeTool:null,magnetEnabled:!0,connectionState:`connecting`,connectionMessage:`Connecting...`},m(),this.root=document.createElement(`div`),this.root.className=`tcw-root`,this.root.dataset.tcwTheme=r?`dark`:`light`,t.appendChild(this.root),n.toolbar!==!1&&(this.toolbar=new y(this.root,{symbols:this.symbols,timeframes:n.timeframes?i.filter(e=>n.timeframes.includes(e.value)):i,chartTypes:n.chartTypes?a.filter(e=>n.chartTypes.includes(e.value)):a,indicators:s,popularIndicatorIds:c},{onSymbolClick:()=>this.handleSymbolClick(),onTimeframe:e=>this.handleTimeframe(e),onChartType:e=>this.handleChartType(e),onAddIndicator:e=>this.handleAddIndicator(e),onRemoveIndicator:e=>this.handleRemoveIndicator(e),onScreenshot:()=>this.chart.screenshot(),onSettings:()=>this.openSettings(),onToggleTheme:()=>this.handleToggleTheme(),onToggleReplay:()=>this.toggleReplay(),onToggleAlerts:n.alerts===!1?void 0:()=>this.toggleAlerts(),onToggleObjects:n.objectTree===!1?void 0:()=>this.toggleObjects(),onBracket:n.trading===!1?void 0:e=>this.startBracket(e),onToggleLadder:n.trading!==!1&&n.depthLadder?()=>this.depthLadder?.toggle():void 0}));let f=document.createElement(`div`);if(f.className=`tcw-body`,n.drawingTools!==!1&&(n.drawingFavorites&&this.favoritesStore.seedDefaults(n.drawingFavorites),this.sidebar=new ie(f,{drawingToolGroups:o,favorites:this.favoritesStore.list()},{onDrawingTool:e=>this.handleDrawingTool(e),onCancelDrawing:()=>this.handleCancelDrawing(),onToggleMagnet:()=>this.handleToggleMagnet(),onToggleFavorite:e=>this.handleToggleFavorite(e),onUndo:()=>this.chart.undo(),onRedo:()=>this.chart.redo(),onClearDrawings:()=>{this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI()},onToggleStyle:()=>this.drawingStyle?.toggle()})),this.chartContainer=document.createElement(`div`),this.chartContainer.className=`tcw-chart-container`,f.appendChild(this.chartContainer),n.watchlist&&(this.watchlist=new L(f,this.symbols,{onSelect:e=>{this.setSymbol(e)}}),this.watchlist.setActive(this.state.symbol)),this.root.appendChild(f),this.chart=new e.r(this.chartContainer,{chartType:this.state.chartType,theme:d,autoScale:!0,crosshair:{mode:`magnet`},features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:n.trading!==!1,tradingContextMenu:n.trading!==!1,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0},...n.chartOptions}),n.dragDropImport!==!1&&(this.dragDrop=new e.t(this.chartContainer,{onData:(e,t,n)=>{this.setData(e),this.toast(`Loaded ${t.data.length} bars from ${n.name}`+(t.skipped>0?` (${t.skipped} skipped)`:``))},onError:(e,t)=>{this.toast(`${t.name}: ${e.message}`,`error`)}}),this.dragDrop.attach()),n.statusBar!==!1&&(this.statusBar=new b(this.root)),n.settings!==!1&&(this.settings=new oe({onChange:e=>this.applySettings(e),onReset:()=>this.resetSettings(),onClose:()=>{}})),this.symbolSearch=new S({onPick:e=>{this.setSymbol(e)},onClose:()=>{}}),this.hotkeySheet=new k({onClose:()=>{}}),this.chart.on(`barClick`,e=>{if(!this.replayBar?.isMounted())return;let t=e.payload.barIndex;typeof t==`number`&&(this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(t),this.replayBar.setState(`paused`))}),this.dataWindow=new Te(this.root,{formatPrice:e=>this.formatAlertPrice(e)}),this.chart.on(`crosshairMove`,e=>{let t=e.payload;this.lastHoverIndex=typeof t.barIndex==`number`?t.barIndex:null,this.dataWindow?.isOpen()&&this.dataWindow.render(this.buildDataWindowModel())}),n.drawingTools!==!1&&(this.drawingStyle=new ve(this.root,{onStyleChange:e=>{this.chart.setDrawingStyle(e),this.chart.setSelectedDrawingStyle(e)},getStyle:()=>this.chart.getDrawingStyle()},new me)),n.trading!==!1&&(this.bracketBar=new xe(this.root,{onConfirm:()=>this.chart.confirmBracket(),onCancel:()=>{this.chart.cancelBracket(),this.bracketBar?.hide()}}),this.chart.on(`bracketPlace`,e=>{let t=e.payload;this.bracketBar?.hide(),this.toast(`${t.side===`buy`?`Long`:`Short`} bracket placed · ${t.riskReward.toFixed(2)}R`)}),n.depthLadder&&(this.depthLadder=new we(this.root,{onTrade:(e,t)=>{this.chart.placeOrderIntent({side:e,type:`limit`,price:t}),this.toast(`${e===`buy`?`Buy`:`Sell`} limit @ ${this.formatAlertPrice(t)}`)},formatPrice:e=>this.formatAlertPrice(e)})),this.chart.on(`dataUpdate`,e=>{let t=e.payload;t&&t.bracket===`cancelled`&&this.bracketBar?.hide()})),n.alerts!==!1&&(this.alertsPanel=new G(this.root,{onAdd:(e,t,n,r,i)=>{this.chart.addAlert(e,t,n,r,i)},onRemove:e=>this.chart.removeAlert(e),onClear:()=>this.chart.clearAlerts(),getChannelValue:e=>this.getAlertChannelValue(e),formatPrice:e=>this.formatAlertPrice(e)}),this.chart.on(`alertAdd`,()=>this.refreshAlerts()),this.chart.on(`alertRemove`,()=>this.refreshAlerts()),this.chart.on(`alertUpdate`,()=>this.refreshAlerts()),n.alertNotifications&&(this.alertNotifier=new Se(n.alertNotifications)),this.chart.on(`alertTriggered`,e=>{let t=e.payload,n=`Price ${this.formatAlertPrice(t.price)}${t.message?` — ${t.message}`:``}`;this.toast(`🔔 Alert: ${n}`,`info`),this.alertNotifier?.notify(n),this.refreshAlerts()})),n.objectTree!==!1){this.indicatorSettings=new ue(this.root,{onApply:(e,t)=>this.chart.updateIndicator(e,t),onClose:()=>{}}),this.objectTree=new K(this.root,{onRemoveIndicator:e=>this.handleRemoveIndicator(e),onConfigureIndicator:e=>this.openIndicatorSettings(e),onToggleIndicatorVisible:(e,t)=>{this.chart.setIndicatorVisible(e,t),this.refreshObjects()},onRemoveDrawing:e=>{this.chart.removeDrawing(e),this.refreshObjects()},onToggleDrawingVisible:(e,t)=>{this.chart.setDrawingVisible(e,t),this.refreshObjects()},onToggleDrawingLocked:(e,t)=>{this.chart.setDrawingLocked(e,t),this.refreshObjects()},onAddCompare:()=>this.handleAddCompare(),onRemoveCompare:e=>this.handleRemoveCompare(e)});let e=()=>{this.objectTree?.isOpen()&&this.refreshObjects()};this.chart.on(`drawingCreate`,e),this.chart.on(`drawingRemove`,e),this.chart.on(`indicatorAdd`,e),this.chart.on(`indicatorRemove`,e)}if(this.commandPalette=new x({onIndicator:e=>this.handleAddIndicator(e),onChartType:e=>this.handleChartType(e),onDrawingTool:e=>this.handleDrawingTool(e),onTimeframe:e=>this.handleTimeframe(e),onAction:e=>this.handleAction(e),onClose:()=>{}}),this.boundGlobalKeydown=e=>{if((e.ctrlKey||e.metaKey)&&e.key===`k`)e.preventDefault(),this.toggleCommandPalette();else if((e.ctrlKey||e.metaKey)&&(e.key===`p`||e.key===`P`))e.preventDefault(),this.symbolSearch?.open(this.symbols,this.state.symbol);else if(e.key===`?`&&!e.ctrlKey&&!e.metaKey&&!e.altKey){let t=document.activeElement;if(t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.isContentEditable))return;e.preventDefault(),this.hotkeySheet?.open()}},document.addEventListener(`keydown`,this.boundGlobalKeydown),n.adapter&&(this.adapter=n.adapter,this.connectStream()),this.watchlist&&(this.watchlistInterval=setInterval(()=>this.tickWatchlist(),1e3)),this.updateUI(),n.onReady?.(this.chart),n.shareUrl&&typeof location<`u`){let e=Ne(location.hash);e&&this.importState(e)}}setSymbols(e){this.symbols=e,this.watchlist?.setSymbols(e)}async setSymbol(e){this.flushActiveLayout(),this.state={...this.state,symbol:e},this.sessionRefPrice=null,this.options.onSymbolChange?.(e),this.updateUI(),this.watchlist?.setActive(e),this.adapter&&await this.connectStream()}setWatchlistEntry(e,t){this.watchlist?.setEntry(e,t)}tickWatchlist(){if(!this.watchlist)return;let e=this.chart.getData();if(e.length===0)return;let t=e[e.length-1];this.sessionRefPrice===null&&(this.sessionRefPrice=e[0].open);let n=this.watchlistSparkBuffer.get(this.state.symbol)??[];n.push(t.close),n.length>40&&n.shift(),this.watchlistSparkBuffer.set(this.state.symbol,n),this.watchlist.setEntry(this.state.symbol,{lastPrice:t.close,refPrice:this.sessionRefPrice,sparkline:n.slice()})}async setTimeframe(e){if(this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter){await this.connectStream();return}this.options.resampleTimeframes!==!1&&this.applyTimeframeData()}setTheme(e){let t=this.resolveIsDark(e),n=this.resolveTheme(e);this.state={...this.state,isDark:t},this.root.dataset.tcwTheme=t?`dark`:`light`,this.chart.setTheme(n),this.updateUI()}getChart(){return this.chart}destroy(){this.destroyed||(this.destroyed=!0,this.boundGlobalKeydown&&document.removeEventListener(`keydown`,this.boundGlobalKeydown),this.flushActiveLayout(),this.commandPalette?.destroy(),this.symbolSearch?.destroy(),this.hotkeySheet?.destroy(),this.replayPollInterval&&clearInterval(this.replayPollInterval),this.replayBar?.destroy(),this.dragDrop?.detach(),this.alertsPanel?.destroy(),this.objectTree?.destroy(),this.indicatorSettings?.destroy(),this.drawingStyle?.destroy(),this.bracketBar?.destroy(),this.alertNotifier?.destroy(),this.depthLadder?.destroy(),this.dataWindow?.destroy(),this.watchlistInterval&&clearInterval(this.watchlistInterval),this.watchlist?.destroy(),this.toolbar?.destroy(),this.sidebar?.destroy(),this.settings?.destroy(),this.statusBar?.destroy(),this.chart.destroy(),this.root.remove(),h())}handleSymbolClick(){this.symbolSearch?.open(this.symbols,this.state.symbol)}handleTimeframe(e){if(this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter){this.connectStream();return}if(this.options.resampleTimeframes!==!1){if(!this.baseSeries){let e=this.chart.getData();e.length>0&&(this.baseSeries=e,this.baseTimeframeMs=r(e))}this.applyTimeframeData()}}setData(e){this.baseSeries=e,this.baseTimeframeMs=r(e),this.applyTimeframeData()}applyTimeframeData(){if(!this.baseSeries)return;let e=(0,t.timeframeToMs)(this.state.timeframe);if(this.baseTimeframeMs>0&&e>this.baseTimeframeMs){let e=this.options.weekStartsOn??1;this.chart.setData(n(this.baseSeries,this.state.timeframe,{weekStartsOn:e}))}else this.chart.setData(this.baseSeries)}toggleAlerts(){this.alertsPanel&&(this.alertsPanel.toggle(),this.alertsPanel.isOpen()&&this.refreshAlerts())}handleToggleFavorite(e){let t=this.favoritesStore.toggle(e);this.sidebar?.setFavorites(this.favoritesStore.list()),this.toast(t?`Pinned to favorites`:`Unpinned`)}exportState(){let e=this.chart.getActiveIndicators().map(e=>({id:e.id,params:e.params}));return je({v:1,symbol:this.state.symbol,timeframe:this.state.timeframe,chartType:this.state.chartType,scaleMode:this.chart.getScaleMode(),indicators:e,drawings:this.chart.getDrawings()})}async importState(e){let t=Me(e);if(!t)return!1;t.symbol&&t.symbol!==this.state.symbol&&await this.setSymbol(t.symbol),t.timeframe&&t.timeframe!==this.state.timeframe&&await this.setTimeframe(t.timeframe),t.chartType&&this.handleChartType(t.chartType),this.chart.setScaleMode(t.scaleMode);for(let[,e]of this.state.activeIndicators)this.chart.removeIndicator(e);let n=new Map;for(let e of t.indicators){let t=this.chart.addIndicator(e.id,e.params);t&&n.set(e.id,t)}return this.state={...this.state,activeIndicators:n},this.chart.setDrawings(t.drawings),this.updateUI(),!0}async copyChartImage(){let e=await this.chart.copyScreenshot();this.toast(e?`Chart image copied`:`Copy failed — image clipboard unavailable`,e?`info`:`error`)}async copyShareLink(){let e=Pe(typeof location<`u`?location.href:``,this.exportState());try{await navigator.clipboard.writeText(e),this.toast(`Share link copied`)}catch{this.toast(`Copy failed — clipboard unavailable`,`error`)}}setDepth(e){this.chart.setDepthData(e),this.depthLadder?.setData(e),e&&this.chart.pushDepthSnapshot(e)}startBracket(e){this.chart.startBracket(e)&&this.bracketBar?.show(e)}buildDataWindowModel(){let e=this.chart.getData(),t=this.lastHoverIndex;if(t===null||t<0||t>=e.length)return{ohlc:null,change:0,changePct:0,indicators:[]};let n=e[t],r=t>0?e[t-1].close:n.open,i=n.close-r,a=r===0?0:i/r*100,o=this.chart.getActiveIndicators().map(e=>{let n=this.chart.getIndicatorOutput(e.instanceId)?.series?.[t]??null,r=n?Object.entries(n).filter(([,e])=>typeof e==`number`&&Number.isFinite(e)).map(([e,t])=>({key:e,value:t})):[];return{name:e.descriptor.name,values:r}}).filter(e=>e.values.length>0);return{ohlc:{open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume},change:i,changePct:a,indicators:o}}toggleDataWindow(){this.dataWindow&&(this.dataWindow.toggle(),this.dataWindow.isOpen()&&this.dataWindow.render(this.buildDataWindowModel()))}toggleObjects(){this.objectTree&&(this.objectTree.toggle(),this.objectTree.isOpen()&&this.refreshObjects())}openIndicatorSettings(e){if(!this.indicatorSettings)return;let t=this.chart.getActiveIndicators().find(t=>t.instanceId===e);t&&this.indicatorSettings.open({instanceId:e,name:t.descriptor.name,defaults:t.descriptor.defaultConfig,params:t.params})}refreshObjects(){if(!this.objectTree)return;let e=this.chart.getActiveIndicators().map(e=>({instanceId:e.instanceId,name:e.descriptor.name,visible:e.visible})),t=this.chart.getDrawings().map(e=>({id:e.id,label:se(e.type),visible:e.visible,locked:e.locked})),n=this.compares.map(e=>({id:e.id,label:e.symbol,color:e.color}));this.objectTree.setObjects(e,t,n)}async handleAddCompare(){if(!this.adapter){this.toast(`Comparison needs a live data adapter`,`error`);return}let e=new Set([this.state.symbol,...this.compares.map(e=>e.symbol)]),t=this.symbols.filter(t=>!e.has(t));this.symbolSearch?.open(t.length?t:this.symbols,this.state.symbol,e=>{this.addCompareSymbol(e)})}async addCompareSymbol(e){if(!this.adapter||this.compares.some(t=>t.symbol===e))return;let t=$[this.compares.length%$.length],n=`cmp_${e}`;try{let r=await this.adapter.fetchHistory(e,this.state.timeframe,this.options.historyLimit??500);this.compares.length===0&&this.chart.setCompareMode(`percent`),this.chart.addCompareSymbol(n,e,r,t),this.compares=[...this.compares,{id:n,symbol:e,color:t}],this.refreshObjects(),this.toast(`Comparing ${e}`)}catch(t){this.toast(`${e}: ${t instanceof Error?t.message:`failed to load`}`,`error`)}}handleRemoveCompare(e){this.chart.removeCompareSymbol(e),this.compares=this.compares.filter(t=>t.id!==e),this.refreshObjects()}async refetchCompares(){if(!this.adapter||this.compares.length===0)return;let e=this.compares.filter(e=>e.symbol===this.state.symbol);for(let t of e)this.handleRemoveCompare(t.id);for(let e of this.compares)try{let t=await this.adapter.fetchHistory(e.symbol,this.state.timeframe,this.options.historyLimit??500);this.chart.updateCompareData(e.id,t)}catch{}}refreshAlerts(){this.alertsPanel&&(this.alertsPanel.setSources(this.buildAlertSources()),this.alertsPanel.setAlerts(this.chart.getAlerts().map(e=>({id:e.id,price:e.price,condition:e.condition,message:e.message,triggered:e.triggered,channel:e.channel,label:e.label}))))}buildAlertSources(){let e=[{channel:`price`,label:`Price`}];for(let t of this.chart.getActiveIndicators()){let n=this.chart.getIndicatorOutput(t.instanceId)?.series,r=n&&n.length>0?n[n.length-1]:null,i=r?Object.keys(r).filter(e=>typeof r[e]==`number`):[];for(let n of i){let r=i.length>1?`${t.descriptor.name} ${n}`:t.descriptor.name;e.push({channel:`${t.instanceId}:${n}`,label:r})}}return e}getAlertChannelValue(e){let t=this.chart.getData();if(e===`price`)return t.length>0?t[t.length-1].close:null;let n=e.indexOf(`:`);if(n<0||t.length===0)return null;let r=e.slice(0,n),i=e.slice(n+1),a=this.chart.getIndicatorOutput(r)?.series?.[t.length-1]?.[i];return typeof a==`number`&&Number.isFinite(a)?a:null}formatAlertPrice(e){let t=Math.abs(e),n=t>=1e3?2:t>=1?4:6,r=this.settingsState.numberLocale||void 0;return e.toLocaleString(r,{minimumFractionDigits:2,maximumFractionDigits:n})}handleChartType(e){this.state={...this.state,chartType:e},this.chart.setChartType(e),this.updateUI()}handleAddIndicator(e){if(this.state.activeIndicators.has(e)){let t=this.state.activeIndicators.get(e);this.chart.removeIndicator(t);let n=new Map(this.state.activeIndicators);n.delete(e),this.state={...this.state,activeIndicators:n}}else{let t=this.chart.addIndicator(e);if(t){let n=new Map(this.state.activeIndicators);n.set(e,t),this.state={...this.state,activeIndicators:n}}}this.updateUI()}handleRemoveIndicator(e){this.chart.removeIndicator(e);let t=new Map(this.state.activeIndicators);for(let[n,r]of t.entries())if(r===e){t.delete(n);break}this.state={...this.state,activeIndicators:t},this.updateUI()}toggleCommandPalette(){if(this.commandPalette?.isOpen()){this.commandPalette.close();return}this.commandPalette?.open(this.buildCommandItems())}buildCommandItems(){let e=[];for(let t of s)e.push({id:t.id,label:t.name,category:`indicator`,active:this.state.activeIndicators.has(t.id)});for(let t of a)e.push({id:t.value,label:t.label,category:`chartType`,active:this.state.chartType===t.value});for(let t of o)for(let n of t.tools)e.push({id:n.value,label:n.label,category:`drawing`,active:this.state.activeTool===n.value});for(let t of i)e.push({id:t.value,label:t.label,category:`timeframe`,active:this.state.timeframe===t.value});return e.push({id:`screenshot`,label:`Screenshot`,category:`action`,shortcut:``},{id:`copyImage`,label:`Copy Chart Image`,category:`action`},{id:`toggleTheme`,label:`Toggle Theme`,category:`action`},{id:`settings`,label:`Settings`,category:`action`},{id:`shareView`,label:`Share View (copy link)`,category:`action`},{id:`autoFib`,label:`Auto Fibonacci (visible swing)`,category:`action`},{id:`dataWindow`,label:`Toggle Data Window`,category:`action`},{id:`clearDrawings`,label:`Clear All Drawings`,category:`action`}),e}handleAction(e){switch(e){case`screenshot`:this.chart.screenshot();break;case`toggleTheme`:this.handleToggleTheme();break;case`settings`:this.openSettings();break;case`copyImage`:this.copyChartImage();break;case`shareView`:this.copyShareLink();break;case`autoFib`:{let e=this.chart.autoFib();this.toast(e?`Auto Fibonacci added`:`No clear swing in view`);break}case`dataWindow`:this.toggleDataWindow();break;case`clearDrawings`:this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI();break}}handleDrawingTool(e){this.state={...this.state,activeTool:e},this.chart.setDrawingTool(e),this.updateUI()}handleCancelDrawing(){this.state={...this.state,activeTool:null},this.chart.setDrawingTool(null),this.updateUI()}handleToggleMagnet(){let e=!this.state.magnetEnabled;this.state={...this.state,magnetEnabled:e},this.chart.setDrawingMagnet(e),this.updateUI()}handleToggleTheme(){let e=!this.state.isDark;this.state={...this.state,isDark:e},this.root.dataset.tcwTheme=e?`dark`:`light`,this.chart.setTheme(e?t.DARK_THEME:t.LIGHT_THEME),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:e?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.updateUI()}openSettings(){this.settings?.open(this.settingsState)}toast(e,t=`info`){let n=document.createElement(`div`);n.className=`tcw-toast ${t===`error`?`tcw-toast-error`:``}`,n.textContent=e,this.root.appendChild(n),requestAnimationFrame(()=>n.classList.add(`tcw-toast-in`)),setTimeout(()=>{n.classList.remove(`tcw-toast-in`),n.addEventListener(`transitionend`,()=>n.remove(),{once:!0}),setTimeout(()=>n.remove(),400)},3500)}clearSavedLayout(e){if(!this.layoutKeyPrefix)return;let t=e??this.state.symbol;try{localStorage.removeItem(this.layoutKeyPrefix+t)}catch{}}applySymbolLayout(e){if(!this.layoutKeyPrefix)return;let t=this.layoutKeyPrefix+e;this.activeLayoutKey=t;try{this.chart.loadStateFromStorage(t)&&this.rebuildActiveIndicatorsMapFromChart()}catch{}this.chart.setAutoSave(t,this.layoutDebounceMs)}flushActiveLayout(){if(this.activeLayoutKey){try{this.chart.saveState(this.activeLayoutKey)}catch{}this.chart.disableAutoSave(),this.activeLayoutKey=null}}rebuildActiveIndicatorsMapFromChart(){let e=new Map;for(let t of this.chart.getActiveIndicators())e.set(t.id,t.instanceId);this.state={...this.state,activeIndicators:e},this.updateUI()}toggleReplay(){this.replayBar?.isMounted()?this.exitReplay():this.enterReplay()}enterReplay(){let e=this.chart.getData();e.length<2||(this.replayOriginalData=e.slice(),this.replayBar=new j({onPlay:()=>{this.chart.getReplayState()===`paused`?this.chart.replayResume():this.chart.replay({speed:this.replaySpeed,interval:200}),this.replayBar?.setState(`playing`)},onPause:()=>{this.chart.replayPause(),this.replayBar?.setState(`paused`)},onStop:()=>{this.chart.replayStop(),this.replayBar?.setState(`paused`)},onStepBack:()=>{let e=this.chart.getReplayProgress();this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(Math.max(0,e.current-1)),this.replayBar?.setState(`paused`)},onStepForward:()=>{let e=this.chart.getReplayProgress();this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(Math.min(e.total-1,e.current+1)),this.replayBar?.setState(`paused`)},onSeek:e=>{this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(e),this.replayBar?.setState(`paused`)},onSpeedChange:e=>{this.replaySpeed=e,this.chart.setReplaySpeed(e)},onClose:()=>this.exitReplay()}),this.replayBar.mount(this.chartContainer,{total:e.length,speed:this.replaySpeed}),this.chart.replay({speed:this.replaySpeed,interval:200,startIndex:1}),this.chart.replayPause(),this.replayBar.setState(`paused`),this.replayPollInterval=setInterval(()=>{if(!this.replayBar?.isMounted())return;let e=this.chart.getReplayProgress();this.replayBar.setProgress(e.current,e.total);let t=this.chart.getReplayState();t===`stopped`?this.replayBar.setState(`paused`):this.replayBar.setState(t)},150))}exitReplay(){this.replayPollInterval&&=(clearInterval(this.replayPollInterval),null),this.chart.replayStop(),this.replayBar?.unmount(),this.replayBar=null,this.replayOriginalData&&=(this.chart.setData(this.replayOriginalData),null)}applySettings(e){this.settingsState={...this.settingsState,...e},e.gridVisible!==void 0&&this.chart.setGridVisible(e.gridVisible),e.volumeVisible!==void 0&&this.chart.setVolumeVisible(e.volumeVisible),e.volumeProfileVisible!==void 0&&this.chart.setVolumeProfileVisible(e.volumeProfileVisible),e.marketProfileVisible!==void 0&&this.chart.setMarketProfileVisible(e.marketProfileVisible),e.marketProfileSplit!==void 0&&this.chart.setMarketProfileConfig({splitBySession:e.marketProfileSplit}),e.marketProfileLetters!==void 0&&this.chart.setMarketProfileConfig({letters:e.marketProfileLetters}),e.marketProfileBuckets!==void 0&&this.chart.setMarketProfileConfig({buckets:e.marketProfileBuckets}),e.marketProfileOpacity!==void 0&&this.chart.setMarketProfileConfig({opacity:e.marketProfileOpacity}),e.depthHeatmapVisible!==void 0&&this.chart.setDepthHeatmapVisible(e.depthHeatmapVisible),e.depthHeatmapOpacity!==void 0&&this.chart.setDepthHeatmapConfig({opacity:e.depthHeatmapOpacity}),e.sessionShadingVisible!==void 0&&this.chart.setSessionShadingVisible(e.sessionShadingVisible),e.pivotMarkersVisible!==void 0&&this.chart.setPivotMarkersVisible(e.pivotMarkersVisible),e.pivotStrength!==void 0&&this.chart.setPivotMarkersConfig({left:e.pivotStrength,right:e.pivotStrength}),e.pivotStructureLabels!==void 0&&this.chart.setPivotMarkersConfig({structureLabels:e.pivotStructureLabels}),e.periodLevelsVisible!==void 0&&this.chart.setPeriodLevelsVisible(e.periodLevelsVisible),e.periodLevelsPeriod!==void 0&&this.chart.setPeriodLevelsPeriod(e.periodLevelsPeriod),e.crosshairMode!==void 0&&this.chart.setCrosshairMode(e.crosshairMode),e.autoScale!==void 0&&this.chart.setAutoScale(e.autoScale),e.scaleMode===void 0?e.logScale!==void 0&&(this.chart.setLogScale(e.logScale),this.settingsState={...this.settingsState,scaleMode:e.logScale?`logarithmic`:`regular`}):(this.chart.setScaleMode(e.scaleMode),this.settingsState={...this.settingsState,logScale:e.scaleMode===`logarithmic`}),e.numberLocale!==void 0&&this.chart.setNumberLocale(e.numberLocale),e.timezone!==void 0&&this.chart.setTimezoneOffset(e.timezone===`local`?null:Number(e.timezone));let t={...this.chart.getTheme()},n=!1;e.candleUpColor!==void 0&&(t.candleUp=e.candleUpColor,n=!0),e.candleDownColor!==void 0&&(t.candleDown=e.candleDownColor,n=!0),e.candleUpWick!==void 0&&(t.candleUpWick=e.candleUpWick,n=!0),e.candleDownWick!==void 0&&(t.candleDownWick=e.candleDownWick,n=!0),e.backgroundColor!==void 0&&(t.background=e.backgroundColor,n=!0),e.gridColor!==void 0&&(t.grid=e.gridColor,n=!0),n&&this.chart.setTheme(t)}resetSettings(){this.settingsState={...u},this.applySettings(this.settingsState)}async connectStream(){if(this.adapter){this.state={...this.state,connectionState:`connecting`,connectionMessage:`Connecting...`},this.updateUI();try{this.chart.disconnectStream(),await this.chart.connect({adapter:this.adapter,symbol:this.state.symbol,timeframe:this.state.timeframe,historyLimit:this.options.historyLimit??500}),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:this.state.isDark?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.applySymbolLayout(this.state.symbol),this.state={...this.state,connectionState:`connected`,connectionMessage:`Live`},this.refetchCompares()}catch(e){this.state={...this.state,connectionState:`error`,connectionMessage:e instanceof Error?e.message:`Connection failed`}}this.updateUI()}}updateUI(){this.toolbar?.update(this.state),this.sidebar?.update(this.state),this.statusBar?.update({connectionState:this.state.connectionState,message:this.state.connectionMessage,symbol:this.state.symbol,timeframe:this.state.timeframe})}resolveIsDark(e){return e===void 0||e===`dark`?!0:e===`light`?!1:typeof e==`object`&&e.background?this.isColorDark(e.background):!0}resolveTheme(e){return e===void 0||e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:typeof e==`object`?e:t.DARK_THEME}isColorDark(e){if(e.startsWith(`#`)&&e.length>=7){let t=parseInt(e.slice(1,3),16),n=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return t+n+r<384}return!0}};exports.ChartWidget=Fe;
878
2373
  //# sourceMappingURL=index.cjs.map