@tradecanvas/chart 1.1.0 → 1.3.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 (52) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +100 -26
  3. package/dist/Chart.d.ts +45 -0
  4. package/dist/Chart.d.ts.map +1 -1
  5. package/dist/DataManager.d.ts.map +1 -1
  6. package/dist/DragDropImporter-BazeSQPD.cjs +2 -0
  7. package/dist/DragDropImporter-BazeSQPD.cjs.map +1 -0
  8. package/dist/{DragDropImporter-CLtRQjKD.js → DragDropImporter-cURSpfUb.js} +390 -253
  9. package/dist/DragDropImporter-cURSpfUb.js.map +1 -0
  10. package/dist/charts/IndicatorPriceRange.d.ts +7 -3
  11. package/dist/charts/IndicatorPriceRange.d.ts.map +1 -1
  12. package/dist/index.cjs +1 -1
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +4 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +29 -29
  17. package/dist/index.js.map +1 -1
  18. package/dist/interaction/verticalPanGate.d.ts +22 -0
  19. package/dist/interaction/verticalPanGate.d.ts.map +1 -0
  20. package/dist/layout/LayoutManager.d.ts +3 -0
  21. package/dist/layout/LayoutManager.d.ts.map +1 -1
  22. package/dist/layout/priceAxisWidth.d.ts +22 -0
  23. package/dist/layout/priceAxisWidth.d.ts.map +1 -0
  24. package/dist/widget/ChartWidget.d.ts +24 -1
  25. package/dist/widget/ChartWidget.d.ts.map +1 -1
  26. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -1
  27. package/dist/widget/WidgetHotkeySheet.d.ts +4 -2
  28. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -1
  29. package/dist/widget/WidgetLoadingOverlay.d.ts +43 -0
  30. package/dist/widget/WidgetLoadingOverlay.d.ts.map +1 -0
  31. package/dist/widget/WidgetObjectTree.d.ts +1 -1
  32. package/dist/widget/WidgetObjectTree.d.ts.map +1 -1
  33. package/dist/widget/WidgetSettings.d.ts +3 -1
  34. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  35. package/dist/widget/WidgetToolbar.d.ts +4 -1
  36. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  37. package/dist/widget/WidgetWatchlist.d.ts +4 -1
  38. package/dist/widget/WidgetWatchlist.d.ts.map +1 -1
  39. package/dist/widget/i18n.d.ts +70 -0
  40. package/dist/widget/i18n.d.ts.map +1 -0
  41. package/dist/widget/icons.d.ts.map +1 -1
  42. package/dist/widget/index.cjs +2554 -2380
  43. package/dist/widget/index.cjs.map +1 -1
  44. package/dist/widget/index.js +725 -258
  45. package/dist/widget/index.js.map +1 -1
  46. package/dist/widget/types.d.ts +10 -0
  47. package/dist/widget/types.d.ts.map +1 -1
  48. package/dist/widget/widgetConfig.d.ts.map +1 -1
  49. package/package.json +6 -3
  50. package/dist/DragDropImporter-CLtRQjKD.js.map +0 -1
  51. package/dist/DragDropImporter-pPS0fl5H.cjs +0 -2
  52. package/dist/DragDropImporter-pPS0fl5H.cjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { r as e, t } from "../DragDropImporter-CLtRQjKD.js";
1
+ import { r as e, t } from "../DragDropImporter-cURSpfUb.js";
2
2
  import { DARK_THEME as n, LIGHT_THEME as r, timeframeBucketStart as i, timeframeToMs as a } from "@tradecanvas/commons";
3
3
  //#region src/io/resampleOHLCV.ts
4
4
  function o(e, t, n = {}) {
@@ -124,18 +124,37 @@ var c = [
124
124
  {
125
125
  label: "Extended Line",
126
126
  value: "extendedLine"
127
+ },
128
+ {
129
+ label: "Info Line",
130
+ value: "infoLine"
131
+ },
132
+ {
133
+ label: "Trend Angle",
134
+ value: "trendAngle"
127
135
  }
128
136
  ]
129
137
  },
130
138
  {
131
139
  label: "Horizontal/Vertical",
132
- tools: [{
133
- label: "Horizontal Line",
134
- value: "horizontalLine"
135
- }, {
136
- label: "Vertical Line",
137
- value: "verticalLine"
138
- }]
140
+ tools: [
141
+ {
142
+ label: "Horizontal Line",
143
+ value: "horizontalLine"
144
+ },
145
+ {
146
+ label: "Horizontal Ray",
147
+ value: "horizontalRay"
148
+ },
149
+ {
150
+ label: "Vertical Line",
151
+ value: "verticalLine"
152
+ },
153
+ {
154
+ label: "Cross Line",
155
+ value: "crossLine"
156
+ }
157
+ ]
139
158
  },
140
159
  {
141
160
  label: "Channels",
@@ -149,13 +168,28 @@ var c = [
149
168
  },
150
169
  {
151
170
  label: "Fibonacci",
152
- tools: [{
153
- label: "Fib Retracement",
154
- value: "fibRetracement"
155
- }, {
156
- label: "Fib Extension",
157
- value: "fibExtension"
158
- }]
171
+ tools: [
172
+ {
173
+ label: "Fib Retracement",
174
+ value: "fibRetracement"
175
+ },
176
+ {
177
+ label: "Fib Extension",
178
+ value: "fibExtension"
179
+ },
180
+ {
181
+ label: "Fib Channel",
182
+ value: "fibChannel"
183
+ },
184
+ {
185
+ label: "Fib Time Zones",
186
+ value: "fibTimeZones"
187
+ },
188
+ {
189
+ label: "Fib Speed Resistance Fan",
190
+ value: "fibSpeedResistanceFan"
191
+ }
192
+ ]
159
193
  },
160
194
  {
161
195
  label: "Shapes",
@@ -164,6 +198,10 @@ var c = [
164
198
  label: "Rectangle",
165
199
  value: "rectangle"
166
200
  },
201
+ {
202
+ label: "Circle",
203
+ value: "circle"
204
+ },
167
205
  {
168
206
  label: "Ellipse",
169
207
  value: "ellipse"
@@ -175,12 +213,20 @@ var c = [
175
213
  ]
176
214
  },
177
215
  {
178
- label: "Gann & Advanced",
216
+ label: "Gann & Pitchforks",
179
217
  tools: [
180
218
  {
181
219
  label: "Pitchfork",
182
220
  value: "pitchfork"
183
221
  },
222
+ {
223
+ label: "Schiff Pitchfork",
224
+ value: "schiffPitchfork"
225
+ },
226
+ {
227
+ label: "Modified Schiff Pitchfork",
228
+ value: "modifiedSchiffPitchfork"
229
+ },
184
230
  {
185
231
  label: "Gann Fan",
186
232
  value: "gannFan"
@@ -189,6 +235,27 @@ var c = [
189
235
  label: "Gann Box",
190
236
  value: "gannBox"
191
237
  },
238
+ {
239
+ label: "Cyclic Lines",
240
+ value: "cyclicLines"
241
+ }
242
+ ]
243
+ },
244
+ {
245
+ label: "Patterns",
246
+ tools: [
247
+ {
248
+ label: "XABCD Pattern",
249
+ value: "xabcdPattern"
250
+ },
251
+ {
252
+ label: "ABCD Pattern",
253
+ value: "abcdPattern"
254
+ },
255
+ {
256
+ label: "Head and Shoulders",
257
+ value: "headAndShoulders"
258
+ },
192
259
  {
193
260
  label: "Elliott Wave",
194
261
  value: "elliottWave"
@@ -206,6 +273,10 @@ var c = [
206
273
  label: "Date Range",
207
274
  value: "dateRange"
208
275
  },
276
+ {
277
+ label: "Date and Price Range",
278
+ value: "dateAndPriceRange"
279
+ },
209
280
  {
210
281
  label: "Measure",
211
282
  value: "measure"
@@ -214,13 +285,37 @@ var c = [
214
285
  },
215
286
  {
216
287
  label: "Annotation",
217
- tools: [{
218
- label: "Text",
219
- value: "text"
220
- }, {
221
- label: "Arrow",
222
- value: "arrow"
223
- }]
288
+ tools: [
289
+ {
290
+ label: "Text",
291
+ value: "text"
292
+ },
293
+ {
294
+ label: "Price Label",
295
+ value: "priceLabel"
296
+ },
297
+ {
298
+ label: "Arrow",
299
+ value: "arrow"
300
+ }
301
+ ]
302
+ },
303
+ {
304
+ label: "Forecasting",
305
+ tools: [
306
+ {
307
+ label: "Long/Short Position",
308
+ value: "riskReward"
309
+ },
310
+ {
311
+ label: "Anchored VWAP",
312
+ value: "anchoredVWAP"
313
+ },
314
+ {
315
+ label: "Fixed Range Volume Profile",
316
+ value: "volumeProfileRange"
317
+ }
318
+ ]
224
319
  }
225
320
  ], d = [
226
321
  {
@@ -233,6 +328,21 @@ var c = [
233
328
  name: "EMA",
234
329
  type: "overlay"
235
330
  },
331
+ {
332
+ id: "tema",
333
+ name: "Triple EMA",
334
+ type: "overlay"
335
+ },
336
+ {
337
+ id: "vwma",
338
+ name: "VWMA",
339
+ type: "overlay"
340
+ },
341
+ {
342
+ id: "wma",
343
+ name: "Weighted MA",
344
+ type: "overlay"
345
+ },
236
346
  {
237
347
  id: "hma",
238
348
  name: "Hull MA",
@@ -248,6 +358,11 @@ var c = [
248
358
  name: "Bollinger Bands",
249
359
  type: "overlay"
250
360
  },
361
+ {
362
+ id: "envelope",
363
+ name: "Envelope",
364
+ type: "overlay"
365
+ },
251
366
  {
252
367
  id: "vwap",
253
368
  name: "VWAP",
@@ -570,12 +685,12 @@ var c = [
570
685
  "SOLUSDT",
571
686
  "BNBUSDT"
572
687
  ], p = {
573
- candleUpColor: "#26A69A",
574
- candleDownColor: "#EF5350",
575
- candleUpWick: "#26A69A",
576
- candleDownWick: "#EF5350",
577
- backgroundColor: "#131722",
578
- gridColor: "#1E222D",
688
+ candleUpColor: n.candleUp,
689
+ candleDownColor: n.candleDown,
690
+ candleUpWick: n.candleUpWick,
691
+ candleDownWick: n.candleDownWick,
692
+ backgroundColor: n.background,
693
+ gridColor: n.grid,
579
694
  gridVisible: !0,
580
695
  volumeVisible: !0,
581
696
  volumeProfileVisible: !1,
@@ -600,7 +715,7 @@ var c = [
600
715
  crosshairMode: "magnet",
601
716
  numberLocale: "en-US",
602
717
  timezone: "local"
603
- }, te = "/* === TradeCanvas Widget — Premium Styles === */\n\n/*\n * The HTML `hidden` attribute only sets `display: none` via the UA stylesheet,\n * which any author `display` rule (e.g. `.tcw-alerts-panel { display: flex }`)\n * silently overrides — leaving panels stuck open when JS sets `el.hidden = true`.\n * Force `hidden` to win for every namespaced widget element. Scoped to `tcw-`\n * so it never touches the host page.\n */\n[class^=\"tcw-\"][hidden],\n[class*=\" tcw-\"][hidden] {\n display: none !important;\n}\n\n.tcw-root {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;\n font-feature-settings: 'cv11', 'ss01', 'ss03';\n font-size: 13px;\n line-height: 1.4;\n color: #d1d4dc;\n background: #0d0f17;\n position: relative;\n overflow: hidden;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n\n /* --- Dark theme tokens (default) --- */\n --tcw-bg: #0d0f17;\n --tcw-bg-surface: #131722;\n --tcw-bg-elevated: #1a1e2d;\n --tcw-bg-overlay: #20253480;\n --tcw-border: #2a2e39;\n --tcw-border-strong: #363a45;\n --tcw-text: #e9ebf0;\n --tcw-text-dim: #b2b5be;\n --tcw-text-muted: #6b6f7a;\n\n --tcw-accent: #4f88ff;\n --tcw-accent-hover: #6b9aff;\n --tcw-accent-soft: rgba(79, 136, 255, 0.14);\n --tcw-accent-glow: rgba(79, 136, 255, 0.22);\n --tcw-accent-line: rgba(79, 136, 255, 0.55);\n\n --tcw-red: #f23645;\n --tcw-red-soft: rgba(242, 54, 69, 0.12);\n --tcw-green: #26a17b;\n --tcw-green-soft: rgba(38, 161, 123, 0.12);\n --tcw-amber: #ff9f43;\n\n --tcw-hover-bg: rgba(255, 255, 255, 0.05);\n --tcw-active-bg: rgba(255, 255, 255, 0.08);\n --tcw-divider: rgba(255, 255, 255, 0.06);\n\n /* Motion */\n --tcw-ease: cubic-bezier(0.2, 0, 0, 1);\n --tcw-ease-out: cubic-bezier(0.16, 1, 0.3, 1);\n --tcw-dur-fast: 120ms;\n --tcw-dur-normal: 180ms;\n --tcw-dur-slow: 260ms;\n\n /* Shape */\n --tcw-radius-sm: 4px;\n --tcw-radius: 6px;\n --tcw-radius-lg: 10px;\n --tcw-radius-xl: 14px;\n\n /* Elevation */\n --tcw-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);\n --tcw-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.2);\n --tcw-shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3);\n --tcw-shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.55), 0 12px 24px rgba(0, 0, 0, 0.35);\n --tcw-ring: 0 0 0 2px rgba(79, 136, 255, 0.45);\n\n /* Type */\n --tcw-font-mono: 'JetBrains Mono', 'SF Mono', 'Cascadia Code', 'Fira Code', 'Consolas', ui-monospace, monospace;\n}\n\n.tcw-root[data-tcw-theme='light'] {\n color: #131722;\n background: #fcfcfd;\n\n --tcw-bg: #fcfcfd;\n --tcw-bg-surface: #ffffff;\n --tcw-bg-elevated: #ffffff;\n --tcw-bg-overlay: rgba(255, 255, 255, 0.75);\n --tcw-border: #e7e9ef;\n --tcw-border-strong: #d4d7e0;\n --tcw-text: #131722;\n --tcw-text-dim: #50545e;\n --tcw-text-muted: #8b8f99;\n\n --tcw-accent: #2962ff;\n --tcw-accent-hover: #1e4fd6;\n --tcw-accent-soft: rgba(41, 98, 255, 0.10);\n --tcw-accent-glow: rgba(41, 98, 255, 0.16);\n --tcw-accent-line: rgba(41, 98, 255, 0.45);\n\n --tcw-hover-bg: rgba(0, 0, 0, 0.04);\n --tcw-active-bg: rgba(41, 98, 255, 0.08);\n --tcw-divider: rgba(0, 0, 0, 0.06);\n\n --tcw-shadow-sm: 0 1px 2px rgba(20, 28, 56, 0.05);\n --tcw-shadow-md: 0 4px 12px rgba(20, 28, 56, 0.08), 0 1px 3px rgba(20, 28, 56, 0.04);\n --tcw-shadow-lg: 0 12px 36px rgba(20, 28, 56, 0.14), 0 4px 12px rgba(20, 28, 56, 0.08);\n --tcw-shadow-xl: 0 24px 64px rgba(20, 28, 56, 0.18), 0 12px 24px rgba(20, 28, 56, 0.1);\n}\n\n/* === Toolbar === */\n\n.tcw-toolbar {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 10px;\n height: 44px;\n border-bottom: 1px solid var(--tcw-border);\n background:\n linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);\n flex-shrink: 0;\n position: relative;\n z-index: 20;\n box-shadow: var(--tcw-shadow-sm);\n}\n\n.tcw-toolbar-symbol {\n font-size: 14px;\n font-weight: 650;\n color: var(--tcw-text);\n padding: 6px 12px;\n white-space: nowrap;\n letter-spacing: -0.015em;\n cursor: pointer;\n border: none;\n background: transparent;\n font-family: inherit;\n border-radius: var(--tcw-radius);\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-toolbar-symbol:hover {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-toolbar-sep {\n width: 1px;\n height: 22px;\n background: var(--tcw-border);\n flex-shrink: 0;\n margin: 0 4px;\n}\n\n.tcw-toolbar-group {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 0 4px;\n}\n\n.tcw-toolbar-spacer {\n flex: 1;\n}\n\n.tcw-btn {\n padding: 6px 10px;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n color var(--tcw-dur-fast) var(--tcw-ease),\n transform var(--tcw-dur-fast) var(--tcw-ease);\n white-space: nowrap;\n line-height: 1;\n letter-spacing: -0.005em;\n}\n\n.tcw-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-btn:active {\n transform: translateY(0.5px);\n}\n\n.tcw-btn.tcw-active {\n background: var(--tcw-accent-soft);\n color: var(--tcw-accent);\n font-weight: 600;\n box-shadow: inset 0 0 0 1px var(--tcw-accent-line);\n}\n\n.tcw-btn:focus-visible,\n.tcw-btn-icon:focus-visible,\n.tcw-sidebar-btn:focus-visible,\n.tcw-dropdown-trigger:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-btn-icon {\n width: 32px;\n height: 32px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n color var(--tcw-dur-fast) var(--tcw-ease);\n line-height: 1;\n position: relative;\n}\n\n.tcw-btn-icon:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-btn-icon svg {\n display: block;\n}\n\n.tcw-badge-count {\n font-size: 10px;\n font-weight: 600;\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n padding: 1px 5px;\n border-radius: 9px;\n font-family: var(--tcw-font-mono);\n}\n\n.tcw-indicator-chips {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 0 4px;\n flex-wrap: nowrap;\n overflow: hidden;\n}\n\n.tcw-indicator-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 6px 3px 9px;\n font-size: 11px;\n font-weight: 500;\n background: var(--tcw-accent-soft);\n color: var(--tcw-accent);\n border-radius: 9999px;\n white-space: nowrap;\n line-height: 1.4;\n letter-spacing: -0.005em;\n border: 1px solid transparent;\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-indicator-chip:hover {\n border-color: var(--tcw-accent-line);\n}\n\n.tcw-chip-remove {\n cursor: pointer;\n opacity: 0.55;\n padding: 0 2px;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n border: none;\n background: transparent;\n color: inherit;\n display: inline-flex;\n align-items: center;\n}\n\n.tcw-chip-remove:hover {\n opacity: 1;\n}\n\n/* === Dropdown === */\n\n.tcw-dropdown-trigger {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 6px 10px;\n font-size: 12px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n white-space: nowrap;\n line-height: 1;\n}\n\n.tcw-dropdown-trigger:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-dropdown {\n position: absolute;\n top: 100%;\n margin-top: 6px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n z-index: 50;\n padding: 6px;\n max-height: 420px;\n overflow-y: auto;\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n@keyframes tcw-pop-in {\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n.tcw-dropdown-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 7px 10px;\n font-size: 12.5px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n width: 100%;\n border: none;\n background: transparent;\n font-family: inherit;\n text-align: left;\n border-radius: var(--tcw-radius-sm);\n gap: 12px;\n}\n\n.tcw-dropdown-item:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-dropdown-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: 600;\n}\n\n.tcw-dropdown-label {\n text-transform: uppercase;\n font-size: 10px;\n color: var(--tcw-text-muted);\n letter-spacing: 0.08em;\n padding: 8px 10px 4px;\n font-weight: 600;\n}\n\n.tcw-dropdown-divider {\n border-top: 1px solid var(--tcw-divider);\n margin: 6px 4px;\n}\n\n.tcw-tag {\n font-size: 10px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n padding: 2px 6px;\n border-radius: 4px;\n background: var(--tcw-hover-bg);\n letter-spacing: 0.02em;\n}\n\n/* === Body === */\n\n.tcw-body {\n display: flex;\n flex: 1;\n min-height: 0;\n background: var(--tcw-bg);\n}\n\n.tcw-chart-container {\n flex: 1;\n min-width: 0;\n min-height: 0;\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n/* === Sidebar === */\n\n.tcw-sidebar {\n width: 40px;\n flex-shrink: 0;\n background: linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);\n border-right: 1px solid var(--tcw-border);\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 6px 0;\n overflow: visible;\n box-shadow: var(--tcw-shadow-sm);\n}\n\n.tcw-tool-group-wrap {\n position: relative;\n}\n\n.tcw-sidebar-btn {\n width: 32px;\n height: 32px;\n margin: 1px 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n font-family: inherit;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n color var(--tcw-dur-fast) var(--tcw-ease);\n position: relative;\n flex-shrink: 0;\n line-height: 1;\n border-radius: var(--tcw-radius);\n}\n\n.tcw-sidebar-btn:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-sidebar-btn.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n box-shadow: inset 2px 0 0 var(--tcw-accent);\n}\n\n.tcw-sidebar-btn.tcw-danger:hover {\n color: var(--tcw-red);\n background: var(--tcw-red-soft);\n}\n\n.tcw-multi-dot {\n position: absolute;\n bottom: 3px;\n right: 3px;\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n opacity: 0.7;\n}\n\n.tcw-sidebar-divider {\n width: 22px;\n height: 1px;\n background: var(--tcw-divider);\n margin: 6px 0;\n flex-shrink: 0;\n}\n\n.tcw-sidebar-spacer {\n flex: 1;\n}\n\n/* === Flyout === */\n\n.tcw-flyout {\n position: absolute;\n left: 100%;\n top: 0;\n margin-left: 6px;\n min-width: 180px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n z-index: 30;\n padding: 6px;\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n animation: tcw-slide-right var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n@keyframes tcw-slide-right {\n from { opacity: 0; transform: translateX(-4px); }\n to { opacity: 1; transform: translateX(0); }\n}\n\n.tcw-flyout-header {\n text-transform: uppercase;\n font-size: 10px;\n color: var(--tcw-text-muted);\n letter-spacing: 0.08em;\n padding: 6px 10px 4px;\n font-weight: 600;\n}\n\n.tcw-flyout-item {\n padding: 7px 10px;\n font-size: 12.5px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n width: 100%;\n display: block;\n border: none;\n background: transparent;\n text-align: left;\n font-family: inherit;\n border-radius: var(--tcw-radius-sm);\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-flyout-item:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-flyout-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: 600;\n}\n\n/* Pinned (favorited) flyout item — a star marker on the right. */\n.tcw-flyout-item.tcw-flyout-faved::after {\n content: '★';\n float: right;\n color: var(--tcw-accent);\n font-size: 11px;\n line-height: 1.4;\n}\n\n/* Favorites strip — pinned drawing tools above the tool groups. */\n.tcw-sidebar-favorites {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n.tcw-sidebar-favorites .tcw-sidebar-btn {\n position: relative;\n}\n.tcw-sidebar-favorites .tcw-sidebar-btn::before {\n content: '';\n position: absolute;\n top: 3px;\n right: 3px;\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background: var(--tcw-accent);\n opacity: 0.7;\n}\n\n/* === Modal === */\n\n.tcw-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(8, 10, 18, 0.55);\n backdrop-filter: blur(6px) saturate(140%);\n -webkit-backdrop-filter: blur(6px) saturate(140%);\n z-index: 100;\n animation: tcw-fade-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n@keyframes tcw-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.tcw-modal {\n position: fixed;\n z-index: 101;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-xl);\n width: 520px;\n max-width: 92vw;\n max-height: 82vh;\n display: flex;\n flex-direction: column;\n box-shadow: var(--tcw-shadow-xl);\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\n}\n\n@keyframes tcw-modal-in {\n from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }\n to { opacity: 1; transform: translate(-50%, -50%) scale(1); }\n}\n\n.tcw-modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 22px;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-modal-header h3 {\n font-size: 15px;\n font-weight: 650;\n margin: 0;\n color: var(--tcw-text);\n letter-spacing: -0.015em;\n}\n\n.tcw-modal-close {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n border-radius: var(--tcw-radius);\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-modal-close:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-modal-tabs {\n display: flex;\n gap: 4px;\n padding: 0 18px;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-modal-tab {\n padding: 11px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--tcw-text-muted);\n border: none;\n background: transparent;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n font-family: inherit;\n text-transform: capitalize;\n letter-spacing: -0.005em;\n}\n\n.tcw-modal-tab:hover {\n color: var(--tcw-text-dim);\n}\n\n.tcw-modal-tab.tcw-active {\n color: var(--tcw-accent);\n border-bottom-color: var(--tcw-accent);\n font-weight: 600;\n}\n\n.tcw-modal-body {\n padding: 20px 22px;\n overflow-y: auto;\n flex: 1;\n}\n\n.tcw-settings-section {\n margin-bottom: 22px;\n}\n\n.tcw-settings-section:last-child {\n margin-bottom: 0;\n}\n\n.tcw-settings-section-title {\n font-size: 10.5px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.09em;\n color: var(--tcw-text-muted);\n margin-bottom: 12px;\n}\n\n.tcw-settings-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 0;\n}\n\n.tcw-settings-row + .tcw-settings-row {\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-settings-label {\n font-size: 13px;\n color: var(--tcw-text-dim);\n letter-spacing: -0.005em;\n}\n\n.tcw-color-picker-wrap {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.tcw-color-picker-wrap input[type='color'] {\n width: 28px;\n height: 28px;\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n cursor: pointer;\n padding: 2px;\n}\n\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch {\n border: none;\n border-radius: 2px;\n}\n\n.tcw-color-hex {\n font-size: 11px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n min-width: 64px;\n letter-spacing: 0.01em;\n}\n\n.tcw-toggle {\n width: 36px;\n height: 20px;\n background: rgba(255, 255, 255, 0.12);\n border-radius: 10px;\n position: relative;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n border: none;\n padding: 0;\n flex-shrink: 0;\n}\n\n.tcw-toggle::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n transition:\n left var(--tcw-dur-normal) var(--tcw-ease-out),\n background var(--tcw-dur-fast) var(--tcw-ease);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\n}\n\n.tcw-toggle.tcw-on {\n background: var(--tcw-accent);\n box-shadow: 0 0 0 2px var(--tcw-accent-glow);\n}\n\n.tcw-toggle.tcw-on::after {\n left: 18px;\n background: #fff;\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle {\n background: rgba(0, 0, 0, 0.12);\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle::after {\n background: #999;\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on {\n background: var(--tcw-accent);\n}\n\n.tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on::after {\n background: #fff;\n}\n\n.tcw-settings-select {\n padding: 6px 10px;\n font-size: 12px;\n font-family: inherit;\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius);\n color: var(--tcw-text);\n cursor: pointer;\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-settings-select:hover {\n border-color: var(--tcw-border-strong);\n}\n\n.tcw-settings-select:focus-visible {\n outline: none;\n border-color: var(--tcw-accent);\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-modal-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 22px;\n border-top: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n border-radius: 0 0 var(--tcw-radius-xl) var(--tcw-radius-xl);\n}\n\n.tcw-reset-link {\n font-size: 12px;\n color: var(--tcw-text-muted);\n cursor: pointer;\n border: none;\n background: transparent;\n font-family: inherit;\n text-decoration: underline;\n text-underline-offset: 2px;\n text-decoration-color: var(--tcw-border-strong);\n transition: color var(--tcw-dur-fast) var(--tcw-ease), text-decoration-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-reset-link:hover {\n color: var(--tcw-text-dim);\n text-decoration-color: currentColor;\n}\n\n.tcw-done-btn {\n padding: 8px 18px;\n font-size: 12.5px;\n font-weight: 600;\n background: var(--tcw-accent);\n color: #fff;\n border: none;\n border-radius: var(--tcw-radius);\n cursor: pointer;\n font-family: inherit;\n transition:\n background var(--tcw-dur-fast) var(--tcw-ease),\n transform var(--tcw-dur-fast) var(--tcw-ease),\n box-shadow var(--tcw-dur-fast) var(--tcw-ease);\n letter-spacing: -0.005em;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.15);\n}\n\n.tcw-done-btn:hover {\n background: var(--tcw-accent-hover);\n box-shadow: var(--tcw-shadow-md), 0 0 0 3px var(--tcw-accent-glow);\n}\n\n.tcw-done-btn:active {\n transform: translateY(0.5px);\n}\n\n/* === Status Bar === */\n\n.tcw-statusbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 7px 16px;\n border-top: 1px solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n font-size: 11px;\n color: var(--tcw-text-muted);\n flex-shrink: 0;\n font-feature-settings: 'tnum';\n}\n\n.tcw-status-indicator {\n display: flex;\n align-items: center;\n gap: 7px;\n font-weight: 500;\n}\n\n.tcw-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n transition: background var(--tcw-dur-normal) var(--tcw-ease), box-shadow var(--tcw-dur-normal) var(--tcw-ease);\n position: relative;\n}\n\n.tcw-status-dot.tcw-connected {\n background: var(--tcw-green);\n box-shadow: 0 0 0 3px rgba(38, 161, 123, 0.18);\n}\n\n.tcw-status-dot.tcw-connected::after {\n content: '';\n position: absolute;\n inset: -3px;\n border-radius: 50%;\n border: 2px solid var(--tcw-green);\n opacity: 0;\n animation: tcw-pulse 2.2s ease-out infinite;\n}\n\n@keyframes tcw-pulse {\n 0% { opacity: 0.6; transform: scale(0.6); }\n 100% { opacity: 0; transform: scale(2.2); }\n}\n\n.tcw-status-dot.tcw-error {\n background: var(--tcw-red);\n box-shadow: 0 0 0 3px rgba(242, 54, 69, 0.2);\n}\n\n/* === Command Palette === */\n\n.tcw-cmd-palette {\n position: fixed;\n z-index: 102;\n top: 18%;\n left: 50%;\n transform: translateX(-50%);\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-xl);\n width: 560px;\n max-width: 92vw;\n max-height: 62vh;\n display: flex;\n flex-direction: column;\n box-shadow: var(--tcw-shadow-xl);\n overflow: hidden;\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\n}\n\n.tcw-cmd-header {\n display: flex;\n align-items: center;\n padding: 14px 18px;\n border-bottom: 1px solid var(--tcw-divider);\n gap: 12px;\n}\n\n.tcw-cmd-icon {\n font-size: 18px;\n color: var(--tcw-text-muted);\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n}\n\n.tcw-cmd-input {\n flex: 1;\n background: transparent;\n border: none;\n outline: none;\n font-size: 14.5px;\n font-family: inherit;\n color: var(--tcw-text);\n caret-color: var(--tcw-accent);\n letter-spacing: -0.005em;\n}\n\n.tcw-cmd-input::placeholder {\n color: var(--tcw-text-muted);\n}\n\n.tcw-cmd-hint {\n font-size: 10px;\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n border: 1px solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n padding: 3px 7px;\n border-radius: 4px;\n flex-shrink: 0;\n box-shadow: inset 0 -1px 0 var(--tcw-border);\n}\n\n.tcw-cmd-list {\n overflow-y: auto;\n flex: 1;\n padding: 6px;\n max-height: 380px;\n}\n\n.tcw-cmd-category {\n text-transform: uppercase;\n font-size: 10px;\n color: var(--tcw-text-muted);\n letter-spacing: 0.09em;\n padding: 10px 10px 4px;\n font-weight: 600;\n}\n\n.tcw-cmd-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 9px 12px;\n font-size: 13px;\n color: var(--tcw-text-dim);\n cursor: pointer;\n width: 100%;\n border: none;\n background: transparent;\n font-family: inherit;\n text-align: left;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n gap: 10px;\n border-radius: var(--tcw-radius);\n letter-spacing: -0.005em;\n}\n\n.tcw-cmd-item:hover,\n.tcw-cmd-item.tcw-selected {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-cmd-item.tcw-selected {\n box-shadow: inset 2px 0 0 var(--tcw-accent);\n}\n\n.tcw-cmd-item.tcw-active .tcw-cmd-item-label {\n color: var(--tcw-accent);\n font-weight: 600;\n}\n\n.tcw-cmd-item-label {\n flex: 1;\n}\n\n.tcw-cmd-check {\n color: var(--tcw-accent);\n font-size: 14px;\n font-weight: 700;\n}\n\n.tcw-cmd-kbd {\n font-size: 10px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n padding: 2px 6px;\n border-radius: 4px;\n box-shadow: inset 0 -1px 0 var(--tcw-border);\n}\n\n.tcw-cmd-empty {\n padding: 32px 16px;\n text-align: center;\n color: var(--tcw-text-muted);\n font-size: 13px;\n}\n\n.tcw-cmd-footer {\n display: flex;\n align-items: center;\n gap: 18px;\n padding: 10px 18px;\n border-top: 1px solid var(--tcw-divider);\n font-size: 11px;\n color: var(--tcw-text-muted);\n background: var(--tcw-bg-surface);\n}\n\n/* === Watchlist === */\n\n.tcw-watchlist {\n width: 220px;\n flex-shrink: 0;\n background: var(--tcw-bg-surface);\n border-left: 1px solid var(--tcw-border);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n box-shadow: var(--tcw-shadow-sm);\n}\n\n.tcw-watchlist-header {\n padding: 10px 14px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--tcw-text-muted);\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-watchlist-list {\n flex: 1;\n overflow-y: auto;\n padding: 4px 0;\n}\n\n.tcw-watchlist-row {\n display: grid;\n grid-template-columns: 1fr auto auto;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n border-left: 2px solid transparent;\n outline: none;\n}\n\n.tcw-watchlist-row:hover {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-watchlist-row:focus-visible {\n background: var(--tcw-hover-bg);\n border-left-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-row.tcw-watchlist-active {\n background: var(--tcw-accent-soft);\n border-left-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-symbol {\n font-size: 12.5px;\n font-weight: 600;\n color: var(--tcw-text);\n letter-spacing: -0.005em;\n white-space: nowrap;\n}\n\n.tcw-watchlist-spark {\n width: 56px;\n height: 22px;\n align-self: center;\n}\n\n.tcw-watchlist-stats {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 1px;\n font-variant-numeric: tabular-nums;\n font-family: var(--tcw-font-mono);\n}\n\n.tcw-watchlist-price {\n font-size: 12px;\n color: var(--tcw-text);\n font-weight: 500;\n}\n\n.tcw-watchlist-change {\n font-size: 10.5px;\n color: var(--tcw-text-muted);\n font-weight: 500;\n}\n\n.tcw-watchlist-change.tcw-up {\n color: var(--tcw-green);\n}\n\n.tcw-watchlist-change.tcw-down {\n color: var(--tcw-red);\n}\n\n@media (max-width: 768px) {\n .tcw-watchlist {\n display: none;\n }\n}\n\n/* === Toast === */\n\n.tcw-toast {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translate(-50%, 12px);\n z-index: 40;\n padding: 9px 14px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: 9999px;\n box-shadow: var(--tcw-shadow-lg);\n font-size: 12.5px;\n font-weight: 500;\n color: var(--tcw-text);\n opacity: 0;\n transition: opacity var(--tcw-dur-normal) var(--tcw-ease-out), transform var(--tcw-dur-normal) var(--tcw-ease-out);\n pointer-events: none;\n max-width: calc(100% - 32px);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n letter-spacing: -0.005em;\n}\n\n.tcw-toast.tcw-toast-in {\n opacity: 1;\n transform: translate(-50%, 0);\n}\n\n.tcw-toast-error {\n border-color: var(--tcw-red);\n color: var(--tcw-red);\n}\n\n/* === Replay scrubber === */\n\n.tcw-replay-bar {\n position: absolute;\n left: 50%;\n bottom: 16px;\n transform: translateX(-50%);\n z-index: 25;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border);\n border-radius: 9999px;\n box-shadow: var(--tcw-shadow-lg);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n font-size: 12px;\n color: var(--tcw-text);\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n.tcw-replay-btn {\n width: 28px;\n height: 28px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n color: var(--tcw-text-dim);\n border-radius: 9999px;\n cursor: pointer;\n font-family: inherit;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-replay-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-replay-btn.tcw-replay-play {\n background: var(--tcw-accent);\n color: #fff;\n width: 32px;\n height: 32px;\n box-shadow: 0 0 0 3px var(--tcw-accent-glow);\n}\n\n.tcw-replay-btn.tcw-replay-play:hover {\n background: var(--tcw-accent-hover);\n}\n\n.tcw-replay-scrubber {\n appearance: none;\n -webkit-appearance: none;\n width: 220px;\n height: 4px;\n background: var(--tcw-border-strong);\n border-radius: 2px;\n outline: none;\n cursor: pointer;\n}\n\n.tcw-replay-scrubber::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--tcw-accent);\n border: 2px solid var(--tcw-bg-elevated);\n box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n}\n\n.tcw-replay-scrubber::-moz-range-thumb {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--tcw-accent);\n border: 2px solid var(--tcw-bg-elevated);\n box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n}\n\n.tcw-replay-progress {\n font-size: 11px;\n font-family: var(--tcw-font-mono);\n color: var(--tcw-text-muted);\n min-width: 64px;\n text-align: center;\n font-feature-settings: 'tnum';\n}\n\n.tcw-replay-speed {\n padding: 4px 8px;\n font-size: 11px;\n font-family: var(--tcw-font-mono);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius);\n color: var(--tcw-text-dim);\n cursor: pointer;\n}\n\n.tcw-replay-speed:hover {\n border-color: var(--tcw-border-strong);\n}\n\n@media (max-width: 640px) {\n .tcw-replay-scrubber {\n width: 140px;\n }\n .tcw-replay-progress {\n display: none;\n }\n}\n\n/* === Hotkey sheet === */\n\n.tcw-hotkey-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 24px 32px;\n}\n\n.tcw-hotkey-section .tcw-settings-section-title {\n margin-bottom: 8px;\n}\n\n.tcw-hotkey-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 6px 0;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-hotkey-row:last-child {\n border-bottom: none;\n}\n\n.tcw-hotkey-keys {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.tcw-hotkey-sep {\n font-size: 10px;\n color: var(--tcw-text-muted);\n}\n\n.tcw-hotkey-label {\n font-size: 12.5px;\n color: var(--tcw-text-dim);\n text-align: right;\n letter-spacing: -0.005em;\n}\n\n@media (max-width: 640px) {\n .tcw-hotkey-grid {\n grid-template-columns: 1fr;\n gap: 18px;\n }\n}\n\n/* === Scrollbar (subtle, premium feel) === */\n\n.tcw-dropdown::-webkit-scrollbar,\n.tcw-modal-body::-webkit-scrollbar,\n.tcw-cmd-list::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n\n.tcw-dropdown::-webkit-scrollbar-track,\n.tcw-modal-body::-webkit-scrollbar-track,\n.tcw-cmd-list::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.tcw-dropdown::-webkit-scrollbar-thumb,\n.tcw-modal-body::-webkit-scrollbar-thumb,\n.tcw-cmd-list::-webkit-scrollbar-thumb {\n background: var(--tcw-border-strong);\n border-radius: 4px;\n border: 2px solid transparent;\n background-clip: padding-box;\n}\n\n.tcw-dropdown::-webkit-scrollbar-thumb:hover,\n.tcw-modal-body::-webkit-scrollbar-thumb:hover,\n.tcw-cmd-list::-webkit-scrollbar-thumb:hover {\n background: var(--tcw-text-muted);\n background-clip: padding-box;\n border: 2px solid transparent;\n}\n\n/* === Responsive === */\n\n@media (max-width: 768px) {\n .tcw-toolbar {\n padding: 0 4px;\n height: 44px; /* Apple HIG minimum touch target */\n }\n .tcw-toolbar-sep {\n display: none;\n }\n .tcw-indicator-chips {\n display: none;\n }\n .tcw-btn,\n .tcw-dropdown-trigger {\n padding: 10px 12px; /* fatter tap target */\n font-size: 13px;\n }\n .tcw-btn-icon {\n width: 40px;\n height: 40px;\n }\n .tcw-sidebar {\n width: 44px;\n }\n .tcw-sidebar-btn {\n width: 40px;\n height: 40px;\n }\n .tcw-modal,\n .tcw-cmd-palette {\n width: 94vw;\n border-radius: var(--tcw-radius-lg);\n }\n\n /* Hide the right-side watchlist on tablets too — already declared but\n * grouped here for clarity. */\n .tcw-watchlist {\n display: none;\n }\n\n /* Replay scrubber compact mode */\n .tcw-replay-scrubber {\n width: 120px;\n }\n .tcw-replay-progress {\n display: none;\n }\n}\n\n/* === Mobile bottom-sheet pattern ===\n * On phones, swap floating-centered modals for full-width sheets that slide\n * up from the bottom. Bigger hit targets, no awkward off-screen clipping,\n * matches how every modern iOS/Android app handles overflow UI.\n */\n@media (max-width: 640px) {\n .tcw-modal,\n .tcw-cmd-palette {\n top: auto;\n bottom: 0;\n left: 0;\n right: 0;\n transform: none;\n width: 100vw;\n max-width: 100vw;\n max-height: 92vh;\n border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;\n border-bottom: none;\n /* Grab handle */\n padding-top: 8px;\n }\n\n /* Visual \"grab handle\" affordance — a short pill at the top of every sheet */\n .tcw-modal::before,\n .tcw-cmd-palette::before {\n content: '';\n display: block;\n width: 36px;\n height: 4px;\n border-radius: 2px;\n background: var(--tcw-border-strong);\n margin: 0 auto 8px;\n opacity: 0.7;\n }\n\n /* Reuse the existing modal-in animation but slide from below instead of\n * popping from center, so the entrance reads as a sheet, not a dialog. */\n @keyframes tcw-modal-in {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n .tcw-modal,\n .tcw-cmd-palette {\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\n }\n\n /* Safe-area-aware footer padding for iPhone notch / home indicator */\n .tcw-modal-footer,\n .tcw-cmd-footer {\n padding-bottom: max(14px, env(safe-area-inset-bottom));\n }\n\n /* Larger tap targets inside sheets */\n .tcw-modal-tab {\n padding: 14px 16px;\n }\n .tcw-cmd-item {\n padding: 12px 14px;\n font-size: 14px;\n }\n .tcw-dropdown-item {\n padding: 12px 12px;\n font-size: 14px;\n }\n\n /* Hotkey sheet — single column on phones */\n .tcw-hotkey-grid {\n grid-template-columns: 1fr;\n }\n}\n\n/* === Price alerts panel === */\n\n.tcw-alerts-panel {\n position: absolute;\n top: 50px;\n right: 12px;\n z-index: 40;\n width: 300px;\n max-width: calc(100vw - 24px);\n display: flex;\n flex-direction: column;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n overflow: hidden;\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n\n@keyframes tcw-alerts-in {\n from { opacity: 0; transform: translateY(-6px) scale(0.98); }\n to { opacity: 1; transform: none; }\n}\n\n.tcw-alerts-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n font-weight: 600;\n font-size: 13px;\n color: var(--tcw-text);\n border-bottom: 1px solid var(--tcw-border);\n}\n\n.tcw-alerts-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-alerts-close:hover {\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n}\n\n.tcw-alerts-form {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n padding: 12px;\n border-bottom: 1px solid var(--tcw-border);\n}\n\n.tcw-alerts-form input,\n.tcw-alerts-form select {\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n height: 32px;\n padding: 0 8px;\n font-size: 12px;\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-sm);\n outline: none;\n}\n.tcw-alerts-form input:focus,\n.tcw-alerts-form select:focus {\n border-color: var(--tcw-accent);\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\n}\n.tcw-alerts-message,\n.tcw-alerts-source {\n grid-column: 1 / -1;\n}\n\n.tcw-alerts-add {\n grid-column: 1 / -1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 34px;\n font-size: 12px;\n font-weight: 600;\n color: #fff;\n background: var(--tcw-accent);\n border: none;\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-alerts-add:hover {\n background: var(--tcw-accent-hover);\n}\n\n.tcw-alerts-list {\n max-height: 260px;\n overflow-y: auto;\n padding: 6px;\n}\n\n.tcw-alerts-empty {\n padding: 18px 12px;\n text-align: center;\n font-size: 12px;\n color: var(--tcw-text-muted);\n line-height: 1.5;\n}\n\n.tcw-alerts-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 8px;\n border-radius: var(--tcw-radius-sm);\n}\n.tcw-alerts-row:hover {\n background: var(--tcw-bg-surface);\n}\n.tcw-alerts-triggered {\n background: var(--tcw-accent-soft);\n}\n\n.tcw-alerts-info {\n min-width: 0;\n}\n.tcw-alerts-row-main {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--tcw-text);\n font-variant-numeric: tabular-nums;\n}\n.tcw-alerts-row-note {\n margin-top: 2px;\n font-size: 11px;\n color: var(--tcw-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.tcw-alerts-badge {\n font-size: 9px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px 5px;\n border-radius: 999px;\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n}\n\n.tcw-alerts-del {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-alerts-del:hover {\n background: var(--tcw-red-soft);\n color: var(--tcw-red);\n}\n\n@media (max-width: 640px) {\n .tcw-alerts-panel {\n top: auto;\n bottom: 0;\n left: 0;\n right: 0;\n width: 100vw;\n max-width: 100vw;\n border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;\n }\n .tcw-alerts-list {\n max-height: 40vh;\n padding-bottom: max(8px, env(safe-area-inset-bottom));\n }\n}\n\n/* === Data Window === */\n\n.tcw-datawin {\n position: absolute;\n top: 50px;\n right: 12px;\n z-index: 38;\n width: 200px;\n display: flex;\n flex-direction: column;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n overflow: hidden;\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-datawin-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 9px 12px;\n font-size: 12px;\n font-weight: 600;\n color: var(--tcw-text);\n border-bottom: 1px solid var(--tcw-border);\n}\n.tcw-datawin-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-datawin-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\n.tcw-datawin-body { padding: 6px 4px; max-height: 360px; overflow-y: auto; }\n.tcw-datawin-empty { padding: 14px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }\n.tcw-datawin-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n padding: 3px 8px;\n font-size: 12px;\n}\n.tcw-datawin-label { color: var(--tcw-text-muted); }\n.tcw-datawin-value { color: var(--tcw-text); font-variant-numeric: tabular-nums; font-weight: 600; }\n.tcw-datawin-value.tcw-up { color: var(--tcw-green); }\n.tcw-datawin-value.tcw-down { color: var(--tcw-red); }\n.tcw-datawin-sub {\n margin: 6px 8px 2px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--tcw-text-muted);\n border-top: 1px solid var(--tcw-border);\n padding-top: 6px;\n}\n\n@media (max-width: 640px) {\n .tcw-datawin { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }\n}\n\n/* === Depth-of-market ladder === */\n\n.tcw-ladder {\n position: absolute;\n top: 50px;\n right: 12px;\n z-index: 41;\n width: 240px;\n display: flex;\n flex-direction: column;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n overflow: hidden;\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-ladder-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n font-size: 13px;\n font-weight: 600;\n color: var(--tcw-text);\n border-bottom: 1px solid var(--tcw-border);\n}\n.tcw-ladder-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-ladder-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\n.tcw-ladder-cols {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n padding: 4px 0;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--tcw-text-muted);\n border-bottom: 1px solid var(--tcw-border);\n}\n.tcw-ladder-cols span { text-align: center; }\n.tcw-ladder-body { max-height: 360px; overflow-y: auto; }\n.tcw-ladder-empty { padding: 18px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }\n\n.tcw-ladder-row {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n height: 22px;\n font-variant-numeric: tabular-nums;\n}\n.tcw-ladder-cell {\n position: relative;\n display: flex;\n align-items: center;\n border: none;\n background: transparent;\n font-size: 11px;\n cursor: pointer;\n font-variant-numeric: tabular-nums;\n overflow: hidden;\n}\n.tcw-ladder-cell:disabled { cursor: default; }\n/* Depth bar grows from the centre column outward. */\n.tcw-ladder-cell::before {\n content: '';\n position: absolute;\n top: 1px; bottom: 1px;\n width: var(--w, 0%);\n}\n.tcw-ladder-bid { justify-content: flex-end; padding-right: 8px; color: var(--tcw-green); }\n.tcw-ladder-bid::before { right: 0; background: var(--tcw-green-soft); }\n.tcw-ladder-bid span, .tcw-ladder-bid { position: relative; }\n.tcw-ladder-ask { justify-content: flex-start; padding-left: 8px; color: var(--tcw-red); }\n.tcw-ladder-ask::before { left: 0; background: var(--tcw-red-soft); }\n.tcw-ladder-cell:not(:disabled):hover::before { opacity: 0.7; filter: brightness(1.4); }\n.tcw-ladder-cell > * { position: relative; }\n.tcw-ladder-price {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 600;\n color: var(--tcw-text-dim);\n border-left: 1px solid var(--tcw-border);\n border-right: 1px solid var(--tcw-border);\n}\n.tcw-ladder-price.tcw-ask { color: var(--tcw-red); }\n.tcw-ladder-price.tcw-bid { color: var(--tcw-green); }\n\n@media (max-width: 640px) {\n .tcw-ladder { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }\n .tcw-ladder-body { max-height: 45vh; padding-bottom: max(0px, env(safe-area-inset-bottom)); }\n}\n\n/* === Bracket order placement === */\n\n.tcw-btn-long:hover { color: var(--tcw-green) !important; }\n.tcw-btn-short:hover { color: var(--tcw-red) !important; }\n\n.tcw-bracket-bar {\n position: absolute;\n top: 52px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 45;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 7px 8px 7px 14px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: 999px;\n box-shadow: var(--tcw-shadow-lg);\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-bracket-label {\n font-size: 12px;\n font-weight: 700;\n}\n.tcw-bracket-label[data-side='buy'] { color: var(--tcw-green); }\n.tcw-bracket-label[data-side='sell'] { color: var(--tcw-red); }\n.tcw-bracket-hint {\n font-size: 11px;\n color: var(--tcw-text-muted);\n}\n.tcw-bracket-cancel, .tcw-bracket-confirm {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 30px;\n padding: 0 12px;\n font-size: 12px;\n font-weight: 600;\n border: none;\n border-radius: 999px;\n cursor: pointer;\n}\n.tcw-bracket-cancel {\n color: var(--tcw-text-dim);\n background: var(--tcw-bg-surface);\n}\n.tcw-bracket-cancel:hover { color: var(--tcw-text); }\n.tcw-bracket-confirm {\n color: #fff;\n background: var(--tcw-accent);\n}\n.tcw-bracket-confirm:hover { background: var(--tcw-accent-hover); }\n\n@media (max-width: 640px) {\n .tcw-bracket-bar { width: calc(100vw - 24px); justify-content: space-between; }\n .tcw-bracket-hint { display: none; }\n}\n\n/* === Drawing style + templates popover === */\n\n.tcw-style-panel {\n position: absolute;\n bottom: 12px;\n left: 52px;\n z-index: 40;\n width: 220px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-style-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 12px;\n font-weight: 600;\n color: var(--tcw-text);\n}\n.tcw-style-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-style-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\n\n.tcw-style-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.tcw-style-swatch {\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: 1px solid var(--tcw-border-strong);\n cursor: pointer;\n padding: 0;\n}\n.tcw-style-swatch.tcw-on { outline: 2px solid var(--tcw-accent); outline-offset: 1px; }\n.tcw-style-picker {\n width: 22px;\n height: 22px;\n padding: 0;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n cursor: pointer;\n}\n.tcw-style-width, .tcw-style-dash {\n flex: 1;\n min-width: 0;\n height: 26px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-sm);\n color: var(--tcw-text-dim);\n cursor: pointer;\n font-size: 11px;\n}\n.tcw-style-width span { width: 16px; background: currentColor; border-radius: 2px; }\n.tcw-style-width.tcw-on, .tcw-style-dash.tcw-on {\n border-color: var(--tcw-accent);\n color: var(--tcw-accent);\n}\n\n.tcw-style-subhead {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--tcw-text-muted);\n margin-top: 2px;\n}\n.tcw-style-save { display: flex; gap: 6px; }\n.tcw-style-name {\n flex: 1;\n min-width: 0;\n height: 28px;\n padding: 0 8px;\n font-size: 12px;\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-sm);\n outline: none;\n}\n.tcw-style-name:focus { border-color: var(--tcw-accent); }\n.tcw-style-savebtn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 10px;\n height: 28px;\n font-size: 12px;\n font-weight: 600;\n color: #fff;\n background: var(--tcw-accent);\n border: none;\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-style-savebtn:hover { background: var(--tcw-accent-hover); }\n\n.tcw-style-templates { display: flex; flex-direction: column; gap: 2px; max-height: 140px; overflow-y: auto; }\n.tcw-style-empty { font-size: 11px; color: var(--tcw-text-muted); padding: 4px 0; }\n.tcw-style-template { display: flex; align-items: center; gap: 4px; }\n.tcw-style-apply {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 5px 7px;\n font-size: 12px;\n color: var(--tcw-text);\n background: transparent;\n border: none;\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n text-align: left;\n}\n.tcw-style-apply:hover { background: var(--tcw-bg-surface); }\n.tcw-style-tdot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; }\n.tcw-style-tdel {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-style-tdel:hover { background: var(--tcw-red-soft); color: var(--tcw-red); }\n\n/* === Settings range slider === */\n\n.tcw-settings-range {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.tcw-settings-range input[type='range'] {\n width: 110px;\n accent-color: var(--tcw-accent);\n cursor: pointer;\n}\n.tcw-settings-range-val {\n min-width: 38px;\n text-align: right;\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-dim);\n}\n\n/* === Indicator settings dialog === */\n\n.tcw-modal-narrow {\n max-width: 360px;\n}\n.tcw-indi-input {\n width: 110px;\n height: 30px;\n padding: 0 8px;\n font-size: 12px;\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-sm);\n outline: none;\n font-variant-numeric: tabular-nums;\n}\n.tcw-indi-input:focus {\n border-color: var(--tcw-accent);\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\n}\n.tcw-indi-color {\n width: 36px;\n height: 28px;\n padding: 2px;\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n\n/* === Object tree panel === */\n\n.tcw-tree-panel {\n position: absolute;\n top: 50px;\n right: 12px;\n z-index: 39;\n width: 280px;\n max-width: calc(100vw - 24px);\n display: flex;\n flex-direction: column;\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-lg);\n box-shadow: var(--tcw-shadow-lg);\n overflow: hidden;\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n\n.tcw-tree-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n font-weight: 600;\n font-size: 13px;\n color: var(--tcw-text);\n border-bottom: 1px solid var(--tcw-border);\n}\n.tcw-tree-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-tree-close:hover {\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n}\n\n.tcw-tree-section {\n padding: 6px;\n border-bottom: 1px solid var(--tcw-border);\n}\n.tcw-tree-section:last-child {\n border-bottom: none;\n}\n.tcw-tree-section-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 8px 4px;\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--tcw-text-muted);\n}\n.tcw-tree-add {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-tree-add:hover {\n background: var(--tcw-accent-soft);\n color: var(--tcw-accent);\n}\n.tcw-tree-dot {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n}\n.tcw-tree-list {\n max-height: 200px;\n overflow-y: auto;\n}\n\n.tcw-tree-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 8px;\n border-radius: var(--tcw-radius-sm);\n}\n.tcw-tree-row:hover {\n background: var(--tcw-bg-surface);\n}\n.tcw-tree-hidden .tcw-tree-name {\n opacity: 0.5;\n}\n.tcw-tree-name {\n min-width: 0;\n font-size: 12px;\n color: var(--tcw-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.tcw-tree-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n.tcw-tree-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n}\n.tcw-tree-btn:hover {\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text);\n}\n.tcw-tree-btn.tcw-tree-on {\n color: var(--tcw-accent);\n}\n.tcw-tree-btn.tcw-tree-del:hover {\n background: var(--tcw-red-soft);\n color: var(--tcw-red);\n}\n.tcw-tree-empty {\n padding: 8px;\n font-size: 12px;\n color: var(--tcw-text-muted);\n}\n\n@media (max-width: 640px) {\n .tcw-tree-panel {\n top: auto;\n bottom: 0;\n left: 0;\n right: 0;\n width: 100vw;\n max-width: 100vw;\n border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;\n }\n .tcw-tree-list {\n max-height: 30vh;\n }\n .tcw-tree-section:last-child {\n padding-bottom: max(6px, env(safe-area-inset-bottom));\n }\n}\n\n/* === Reduced motion === */\n\n@media (prefers-reduced-motion: reduce) {\n .tcw-root *,\n .tcw-root *::before,\n .tcw-root *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n", m = 0, h = "tcw-styles";
718
+ }, te = "/* === TradeCanvas Widget — Premium Styles === */\r\n\r\n/*\r\n * The HTML `hidden` attribute only sets `display: none` via the UA stylesheet,\r\n * which any author `display` rule (e.g. `.tcw-alerts-panel { display: flex }`)\r\n * silently overrides — leaving panels stuck open when JS sets `el.hidden = true`.\r\n * Force `hidden` to win for every namespaced widget element. Scoped to `tcw-`\r\n * so it never touches the host page.\r\n */\r\n[class^=\"tcw-\"][hidden],\r\n[class*=\" tcw-\"][hidden] {\r\n display: none !important;\r\n}\r\n\r\n.tcw-root {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;\r\n font-feature-settings: 'cv11', 'ss01', 'ss03';\r\n font-size: 13px;\r\n line-height: 1.4;\r\n color: #d9dde4;\r\n background: #080b10;\r\n position: relative;\r\n overflow: hidden;\r\n -webkit-font-smoothing: antialiased;\r\n -moz-osx-font-smoothing: grayscale;\r\n\r\n /* --- Dark theme tokens (default) --- */\r\n --tcw-bg: #080b10;\r\n --tcw-bg-surface: #0c1016;\r\n --tcw-bg-elevated: #141922;\r\n --tcw-bg-overlay: rgba(20, 25, 34, 0.5);\r\n --tcw-border: #1f2630;\r\n --tcw-border-strong: #2a323e;\r\n --tcw-text: #e7e9ee;\r\n --tcw-text-dim: #aab1bd;\r\n --tcw-text-muted: #758091;\r\n\r\n /* TradeCanvas amber. --tcw-accent-ink is the text colour on an accent fill. */\r\n --tcw-accent: #f2a93b;\r\n --tcw-accent-hover: #f5b95c;\r\n --tcw-accent-ink: #1a1204;\r\n --tcw-accent-soft: rgba(242, 169, 59, 0.14);\r\n --tcw-accent-glow: rgba(242, 169, 59, 0.22);\r\n --tcw-accent-line: rgba(242, 169, 59, 0.55);\r\n\r\n --tcw-red: #e8505b;\r\n --tcw-red-soft: rgba(232, 80, 91, 0.12);\r\n --tcw-green: #1fa874;\r\n --tcw-green-soft: rgba(31, 168, 116, 0.12);\r\n --tcw-amber: #ff9f43;\r\n\r\n --tcw-hover-bg: rgba(255, 255, 255, 0.05);\r\n --tcw-active-bg: rgba(255, 255, 255, 0.08);\r\n --tcw-divider: rgba(255, 255, 255, 0.06);\r\n\r\n /* Motion */\r\n --tcw-ease: cubic-bezier(0.2, 0, 0, 1);\r\n --tcw-ease-out: cubic-bezier(0.16, 1, 0.3, 1);\r\n --tcw-dur-fast: 120ms;\r\n --tcw-dur-normal: 180ms;\r\n --tcw-dur-slow: 260ms;\r\n\r\n /* Shape */\r\n --tcw-radius-sm: 4px;\r\n --tcw-radius: 6px;\r\n --tcw-radius-lg: 10px;\r\n --tcw-radius-xl: 14px;\r\n\r\n /* Elevation */\r\n --tcw-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);\r\n --tcw-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.2);\r\n --tcw-shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3);\r\n --tcw-shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.55), 0 12px 24px rgba(0, 0, 0, 0.35);\r\n --tcw-ring: 0 0 0 2px rgba(242, 169, 59, 0.45);\r\n\r\n /* Type */\r\n --tcw-font-mono: 'JetBrains Mono', 'SF Mono', 'Cascadia Code', 'Fira Code', 'Consolas', ui-monospace, monospace;\r\n}\r\n\r\n.tcw-root[data-tcw-theme='light'] {\r\n color: #0c1016;\r\n background: #fcfcfd;\r\n\r\n --tcw-bg: #fcfcfd;\r\n --tcw-bg-surface: #ffffff;\r\n --tcw-bg-elevated: #ffffff;\r\n --tcw-bg-overlay: rgba(255, 255, 255, 0.75);\r\n --tcw-border: #e3e6eb;\r\n --tcw-border-strong: #d2d6dd;\r\n --tcw-text: #0c1016;\r\n --tcw-text-dim: #3f4754;\r\n --tcw-text-muted: #626a77;\r\n\r\n /* Deeper amber: readable as text on the light ground, white text readable on it. */\r\n --tcw-accent: #a0610a;\r\n --tcw-accent-hover: #874f07;\r\n --tcw-accent-ink: #ffffff;\r\n --tcw-accent-soft: rgba(160, 97, 10, 0.10);\r\n --tcw-accent-glow: rgba(160, 97, 10, 0.16);\r\n --tcw-accent-line: rgba(160, 97, 10, 0.45);\r\n --tcw-ring: 0 0 0 2px rgba(160, 97, 10, 0.4);\r\n\r\n /* Darker semantic colours: used as text on white. */\r\n --tcw-red: #c42f3e;\r\n --tcw-red-soft: rgba(196, 47, 62, 0.10);\r\n --tcw-green: #0b7d50;\r\n --tcw-green-soft: rgba(11, 125, 80, 0.10);\r\n\r\n --tcw-hover-bg: rgba(0, 0, 0, 0.04);\r\n --tcw-active-bg: rgba(160, 97, 10, 0.08);\r\n --tcw-divider: rgba(0, 0, 0, 0.06);\r\n\r\n --tcw-shadow-sm: 0 1px 2px rgba(20, 28, 56, 0.05);\r\n --tcw-shadow-md: 0 4px 12px rgba(20, 28, 56, 0.08), 0 1px 3px rgba(20, 28, 56, 0.04);\r\n --tcw-shadow-lg: 0 12px 36px rgba(20, 28, 56, 0.14), 0 4px 12px rgba(20, 28, 56, 0.08);\r\n --tcw-shadow-xl: 0 24px 64px rgba(20, 28, 56, 0.18), 0 12px 24px rgba(20, 28, 56, 0.1);\r\n}\r\n\r\n/* === Toolbar === */\r\n\r\n.tcw-toolbar {\r\n display: flex;\r\n align-items: center;\r\n gap: 0;\r\n padding: 0 10px;\r\n height: 44px;\r\n border-bottom: 1px solid var(--tcw-border);\r\n background:\r\n linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);\r\n flex-shrink: 0;\r\n position: relative;\r\n z-index: 20;\r\n box-shadow: var(--tcw-shadow-sm);\r\n}\r\n\r\n.tcw-toolbar-symbol {\r\n font-size: 14px;\r\n font-weight: 650;\r\n color: var(--tcw-text);\r\n padding: 6px 12px;\r\n white-space: nowrap;\r\n letter-spacing: -0.015em;\r\n cursor: pointer;\r\n border: none;\r\n background: transparent;\r\n font-family: inherit;\r\n border-radius: var(--tcw-radius);\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\r\n}\r\n\r\n.tcw-toolbar-symbol:hover {\r\n background: var(--tcw-hover-bg);\r\n}\r\n\r\n.tcw-toolbar-sep {\r\n width: 1px;\r\n height: 22px;\r\n background: var(--tcw-border);\r\n flex-shrink: 0;\r\n margin: 0 4px;\r\n}\r\n\r\n.tcw-toolbar-group {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n padding: 0 4px;\r\n}\r\n\r\n.tcw-toolbar-spacer {\r\n flex: 1;\r\n}\r\n\r\n.tcw-btn {\r\n padding: 6px 10px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n font-family: inherit;\r\n border: none;\r\n border-radius: var(--tcw-radius);\r\n background: transparent;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n transition:\r\n background var(--tcw-dur-fast) var(--tcw-ease),\r\n color var(--tcw-dur-fast) var(--tcw-ease),\r\n transform var(--tcw-dur-fast) var(--tcw-ease);\r\n white-space: nowrap;\r\n line-height: 1;\r\n letter-spacing: -0.005em;\r\n}\r\n\r\n.tcw-btn:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-btn:active {\r\n transform: translateY(0.5px);\r\n}\r\n\r\n.tcw-btn.tcw-active {\r\n background: var(--tcw-accent-soft);\r\n color: var(--tcw-accent);\r\n font-weight: 600;\r\n box-shadow: inset 0 0 0 1px var(--tcw-accent-line);\r\n}\r\n\r\n.tcw-btn:focus-visible,\r\n.tcw-btn-icon:focus-visible,\r\n.tcw-sidebar-btn:focus-visible,\r\n.tcw-dropdown-trigger:focus-visible {\r\n outline: none;\r\n box-shadow: var(--tcw-ring);\r\n}\r\n\r\n.tcw-btn-icon {\r\n width: 32px;\r\n height: 32px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-family: inherit;\r\n border: none;\r\n border-radius: var(--tcw-radius);\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n transition:\r\n background var(--tcw-dur-fast) var(--tcw-ease),\r\n color var(--tcw-dur-fast) var(--tcw-ease);\r\n line-height: 1;\r\n position: relative;\r\n}\r\n\r\n.tcw-btn-icon:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-btn-icon svg {\r\n display: block;\r\n}\r\n\r\n.tcw-badge-count {\r\n font-size: 10px;\r\n font-weight: 600;\r\n color: var(--tcw-accent);\r\n background: var(--tcw-accent-soft);\r\n padding: 1px 5px;\r\n border-radius: 9px;\r\n font-family: var(--tcw-font-mono);\r\n}\r\n\r\n.tcw-indicator-chips {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 0 4px;\r\n flex-wrap: nowrap;\r\n overflow: hidden;\r\n}\r\n\r\n.tcw-indicator-chip {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 3px 6px 3px 9px;\r\n font-size: 11px;\r\n font-weight: 500;\r\n background: var(--tcw-accent-soft);\r\n color: var(--tcw-accent);\r\n border-radius: 9999px;\r\n white-space: nowrap;\r\n line-height: 1.4;\r\n letter-spacing: -0.005em;\r\n border: 1px solid transparent;\r\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease);\r\n}\r\n\r\n.tcw-indicator-chip:hover {\r\n border-color: var(--tcw-accent-line);\r\n}\r\n\r\n.tcw-chip-remove {\r\n cursor: pointer;\r\n opacity: 0.55;\r\n padding: 0 2px;\r\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\r\n border: none;\r\n background: transparent;\r\n color: inherit;\r\n display: inline-flex;\r\n align-items: center;\r\n}\r\n\r\n.tcw-chip-remove:hover {\r\n opacity: 1;\r\n}\r\n\r\n/* === Dropdown === */\r\n\r\n.tcw-dropdown-trigger {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 6px 10px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n font-family: inherit;\r\n border: none;\r\n border-radius: var(--tcw-radius);\r\n background: transparent;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\r\n white-space: nowrap;\r\n line-height: 1;\r\n}\r\n\r\n.tcw-dropdown-trigger:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-dropdown {\r\n position: absolute;\r\n top: 100%;\r\n margin-top: 6px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: var(--tcw-shadow-lg);\r\n z-index: 50;\r\n padding: 6px;\r\n max-height: 420px;\r\n overflow-y: auto;\r\n backdrop-filter: blur(12px);\r\n -webkit-backdrop-filter: blur(12px);\r\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\r\n}\r\n\r\n@keyframes tcw-pop-in {\r\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\r\n to { opacity: 1; transform: translateY(0) scale(1); }\r\n}\r\n\r\n.tcw-dropdown-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 7px 10px;\r\n font-size: 12.5px;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\r\n width: 100%;\r\n border: none;\r\n background: transparent;\r\n font-family: inherit;\r\n text-align: left;\r\n border-radius: var(--tcw-radius-sm);\r\n gap: 12px;\r\n}\r\n\r\n.tcw-dropdown-item:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-dropdown-item.tcw-active {\r\n color: var(--tcw-accent);\r\n background: var(--tcw-accent-soft);\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-dropdown-label {\r\n text-transform: uppercase;\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n letter-spacing: 0.08em;\r\n padding: 8px 10px 4px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-dropdown-divider {\r\n border-top: 1px solid var(--tcw-divider);\r\n margin: 6px 4px;\r\n}\r\n\r\n.tcw-tag {\r\n font-size: 10px;\r\n font-family: var(--tcw-font-mono);\r\n color: var(--tcw-text-muted);\r\n padding: 2px 6px;\r\n border-radius: 4px;\r\n background: var(--tcw-hover-bg);\r\n letter-spacing: 0.02em;\r\n}\r\n\r\n/* === Body === */\r\n\r\n.tcw-body {\r\n display: flex;\r\n flex: 1;\r\n min-height: 0;\r\n background: var(--tcw-bg);\r\n}\r\n\r\n.tcw-chart-container {\r\n flex: 1;\r\n min-width: 0;\r\n min-height: 0;\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n}\r\n\r\n/* === Loading overlay (candle skeleton) === */\r\n\r\n.tcw-loading-overlay {\r\n /* Uses a modifier class rather than the `hidden` attribute — the global\r\n `[hidden] { display: none !important }` rule above would cut the\r\n opacity transition off before it can play. */\r\n position: absolute;\r\n inset: 0;\r\n z-index: 5;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: var(--tcw-bg);\r\n opacity: 1;\r\n transition: opacity var(--tcw-dur-slow) var(--tcw-ease-out);\r\n pointer-events: none;\r\n}\r\n\r\n.tcw-loading-overlay--hidden {\r\n opacity: 0;\r\n}\r\n\r\n.tcw-loading-card {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 14px;\r\n padding: 22px 26px 20px;\r\n border: 1px solid transparent;\r\n border-radius: var(--tcw-radius-lg);\r\n}\r\n\r\n/* A slow switch: the previous chart stays readable underneath, dimmed, so the\r\n click visibly registered without blanking the screen. */\r\n.tcw-loading-overlay--veil {\r\n background: color-mix(in srgb, var(--tcw-bg) 55%, transparent);\r\n}\r\n\r\n.tcw-loading-overlay--veil .tcw-loading-card {\r\n background: var(--tcw-bg-elevated);\r\n border-color: var(--tcw-border);\r\n box-shadow: var(--tcw-shadow-lg);\r\n}\r\n\r\n.tcw-loading-candles {\r\n position: relative;\r\n display: flex;\r\n gap: 7px;\r\n height: 64px;\r\n}\r\n\r\n/* One candle: the element is the wick's column, ::before the wick, ::after the body. */\r\n.tcw-loading-candle {\r\n position: relative;\r\n width: 8px;\r\n height: 100%;\r\n color: var(--tcw-red);\r\n opacity: 0.28;\r\n animation: tcw-candle-light 1.6s var(--tcw-ease) infinite;\r\n}\r\n\r\n.tcw-loading-candle--up { color: var(--tcw-green); }\r\n\r\n.tcw-loading-candle::before,\r\n.tcw-loading-candle::after {\r\n content: '';\r\n position: absolute;\r\n left: 50%;\r\n background: currentColor;\r\n transform: translateX(-50%);\r\n}\r\n\r\n.tcw-loading-candle::before {\r\n top: var(--tcw-wick-top);\r\n width: 1.5px;\r\n height: var(--tcw-wick-h);\r\n}\r\n\r\n.tcw-loading-candle::after {\r\n top: var(--tcw-body-top);\r\n width: 8px;\r\n height: var(--tcw-body-h);\r\n border-radius: 1.5px;\r\n}\r\n\r\n/* Each candle brightens and lifts slightly in turn, left to right. */\r\n@keyframes tcw-candle-light {\r\n 0%, 55%, 100% { opacity: 0.28; transform: translateY(0); }\r\n 20% { opacity: 1; transform: translateY(-2px); }\r\n}\r\n\r\n.tcw-loading-track {\r\n position: relative;\r\n width: 100%;\r\n min-width: 88px;\r\n height: 2px;\r\n border-radius: 1px;\r\n background: var(--tcw-border);\r\n overflow: hidden;\r\n}\r\n\r\n.tcw-loading-track > span {\r\n position: absolute;\r\n inset: 0;\r\n width: 40%;\r\n border-radius: 1px;\r\n background: linear-gradient(90deg, transparent, var(--tcw-accent), transparent);\r\n animation: tcw-loading-sweep 1.6s var(--tcw-ease) infinite;\r\n}\r\n\r\n@keyframes tcw-loading-sweep {\r\n from { transform: translateX(-100%); }\r\n to { transform: translateX(250%); }\r\n}\r\n\r\n/* The status text is announced, not shown — the candles say \"loading\". */\r\n.tcw-loading-label {\r\n position: absolute;\r\n width: 1px;\r\n height: 1px;\r\n overflow: hidden;\r\n clip-path: inset(50%);\r\n white-space: nowrap;\r\n}\r\n\r\n.tcw-loading-overlay--error .tcw-loading-candles,\r\n.tcw-loading-overlay--error .tcw-loading-track {\r\n display: none;\r\n}\r\n\r\n/* A failure is shown: why the chart is empty and that a retry is running. */\r\n.tcw-loading-overlay--error .tcw-loading-label {\r\n position: static;\r\n width: auto;\r\n height: auto;\r\n overflow: visible;\r\n clip-path: none;\r\n white-space: normal;\r\n max-width: 320px;\r\n text-align: center;\r\n color: var(--tcw-red);\r\n font-size: 13px;\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n .tcw-loading-candle,\r\n .tcw-loading-track > span {\r\n animation: none;\r\n }\r\n .tcw-loading-candle { opacity: 0.6; }\r\n .tcw-loading-track > span { transform: translateX(75%); }\r\n /* Static candles don't say \"loading\" on their own: show the text. */\r\n .tcw-loading-label {\r\n position: static;\r\n width: auto;\r\n height: auto;\r\n overflow: visible;\r\n clip-path: none;\r\n font-size: 12px;\r\n color: var(--tcw-text-muted);\r\n }\r\n}\r\n\r\n/* === Sidebar === */\r\n\r\n.tcw-sidebar {\r\n width: 40px;\r\n flex-shrink: 0;\r\n background: linear-gradient(180deg, var(--tcw-bg-elevated) 0%, var(--tcw-bg-surface) 100%);\r\n border-right: 1px solid var(--tcw-border);\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 6px 0;\r\n overflow: visible;\r\n box-shadow: var(--tcw-shadow-sm);\r\n}\r\n\r\n.tcw-tool-group-wrap {\r\n position: relative;\r\n}\r\n\r\n.tcw-sidebar-btn {\r\n width: 32px;\r\n height: 32px;\r\n margin: 1px 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition:\r\n background var(--tcw-dur-fast) var(--tcw-ease),\r\n color var(--tcw-dur-fast) var(--tcw-ease);\r\n position: relative;\r\n flex-shrink: 0;\r\n line-height: 1;\r\n border-radius: var(--tcw-radius);\r\n}\r\n\r\n.tcw-sidebar-btn:hover {\r\n color: var(--tcw-text);\r\n background: var(--tcw-hover-bg);\r\n}\r\n\r\n.tcw-sidebar-btn.tcw-active {\r\n color: var(--tcw-accent);\r\n background: var(--tcw-accent-soft);\r\n box-shadow: inset 2px 0 0 var(--tcw-accent);\r\n}\r\n\r\n.tcw-sidebar-btn.tcw-danger:hover {\r\n color: var(--tcw-red);\r\n background: var(--tcw-red-soft);\r\n}\r\n\r\n.tcw-multi-dot {\r\n position: absolute;\r\n bottom: 3px;\r\n right: 3px;\r\n width: 4px;\r\n height: 4px;\r\n border-radius: 50%;\r\n background: var(--tcw-text-muted);\r\n opacity: 0.7;\r\n}\r\n\r\n.tcw-sidebar-divider {\r\n width: 22px;\r\n height: 1px;\r\n background: var(--tcw-divider);\r\n margin: 6px 0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-sidebar-spacer {\r\n flex: 1;\r\n}\r\n\r\n/* === Flyout === */\r\n\r\n.tcw-flyout {\r\n position: absolute;\r\n left: 100%;\r\n top: 0;\r\n margin-left: 6px;\r\n min-width: 180px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: var(--tcw-shadow-lg);\r\n z-index: 30;\r\n padding: 6px;\r\n backdrop-filter: blur(12px);\r\n -webkit-backdrop-filter: blur(12px);\r\n animation: tcw-slide-right var(--tcw-dur-normal) var(--tcw-ease-out);\r\n}\r\n\r\n@keyframes tcw-slide-right {\r\n from { opacity: 0; transform: translateX(-4px); }\r\n to { opacity: 1; transform: translateX(0); }\r\n}\r\n\r\n.tcw-flyout-header {\r\n text-transform: uppercase;\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n letter-spacing: 0.08em;\r\n padding: 6px 10px 4px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-flyout-item {\r\n padding: 7px 10px;\r\n font-size: 12.5px;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n width: 100%;\r\n display: block;\r\n border: none;\r\n background: transparent;\r\n text-align: left;\r\n font-family: inherit;\r\n border-radius: var(--tcw-radius-sm);\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\r\n}\r\n\r\n.tcw-flyout-item:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-flyout-item.tcw-active {\r\n color: var(--tcw-accent);\r\n background: var(--tcw-accent-soft);\r\n font-weight: 600;\r\n}\r\n\r\n/* Pinned (favorited) flyout item — a star marker on the right. */\r\n.tcw-flyout-item.tcw-flyout-faved::after {\r\n content: '★';\r\n float: right;\r\n color: var(--tcw-accent);\r\n font-size: 11px;\r\n line-height: 1.4;\r\n}\r\n\r\n/* Favorites strip — pinned drawing tools above the tool groups. */\r\n.tcw-sidebar-favorites {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n}\r\n.tcw-sidebar-favorites .tcw-sidebar-btn {\r\n position: relative;\r\n}\r\n.tcw-sidebar-favorites .tcw-sidebar-btn::before {\r\n content: '';\r\n position: absolute;\r\n top: 3px;\r\n right: 3px;\r\n width: 4px;\r\n height: 4px;\r\n border-radius: 50%;\r\n background: var(--tcw-accent);\r\n opacity: 0.7;\r\n}\r\n\r\n/* === Modal === */\r\n\r\n.tcw-modal-backdrop {\r\n position: fixed;\r\n inset: 0;\r\n background: rgba(8, 10, 18, 0.55);\r\n backdrop-filter: blur(6px) saturate(140%);\r\n -webkit-backdrop-filter: blur(6px) saturate(140%);\r\n z-index: 100;\r\n animation: tcw-fade-in var(--tcw-dur-normal) var(--tcw-ease-out);\r\n}\r\n\r\n@keyframes tcw-fade-in {\r\n from { opacity: 0; }\r\n to { opacity: 1; }\r\n}\r\n\r\n.tcw-modal {\r\n position: fixed;\r\n z-index: 101;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-xl);\r\n width: 520px;\r\n max-width: 92vw;\r\n max-height: 82vh;\r\n display: flex;\r\n flex-direction: column;\r\n box-shadow: var(--tcw-shadow-xl);\r\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\r\n}\r\n\r\n@keyframes tcw-modal-in {\r\n from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }\r\n to { opacity: 1; transform: translate(-50%, -50%) scale(1); }\r\n}\r\n\r\n.tcw-modal-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 18px 22px;\r\n border-bottom: 1px solid var(--tcw-divider);\r\n}\r\n\r\n.tcw-modal-header h3 {\r\n font-size: 15px;\r\n font-weight: 650;\r\n margin: 0;\r\n color: var(--tcw-text);\r\n letter-spacing: -0.015em;\r\n}\r\n\r\n.tcw-modal-close {\r\n width: 28px;\r\n height: 28px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n border-radius: var(--tcw-radius);\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\r\n}\r\n\r\n.tcw-modal-close:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-modal-tabs {\r\n display: flex;\r\n gap: 4px;\r\n padding: 0 18px;\r\n border-bottom: 1px solid var(--tcw-divider);\r\n}\r\n\r\n.tcw-modal-tab {\r\n padding: 11px 14px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n color: var(--tcw-text-muted);\r\n border: none;\r\n background: transparent;\r\n cursor: pointer;\r\n border-bottom: 2px solid transparent;\r\n margin-bottom: -1px;\r\n transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\r\n font-family: inherit;\r\n text-transform: capitalize;\r\n letter-spacing: -0.005em;\r\n}\r\n\r\n.tcw-modal-tab:hover {\r\n color: var(--tcw-text-dim);\r\n}\r\n\r\n.tcw-modal-tab.tcw-active {\r\n color: var(--tcw-accent);\r\n border-bottom-color: var(--tcw-accent);\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-modal-body {\r\n padding: 20px 22px;\r\n overflow-y: auto;\r\n flex: 1;\r\n}\r\n\r\n.tcw-settings-section {\r\n margin-bottom: 22px;\r\n}\r\n\r\n.tcw-settings-section:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.tcw-settings-section-title {\r\n font-size: 10.5px;\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.09em;\r\n color: var(--tcw-text-muted);\r\n margin-bottom: 12px;\r\n}\r\n\r\n.tcw-settings-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 10px 0;\r\n}\r\n\r\n.tcw-settings-row + .tcw-settings-row {\r\n border-top: 1px solid var(--tcw-divider);\r\n}\r\n\r\n.tcw-settings-label {\r\n font-size: 13px;\r\n color: var(--tcw-text-dim);\r\n letter-spacing: -0.005em;\r\n}\r\n\r\n.tcw-color-picker-wrap {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.tcw-color-picker-wrap input[type='color'] {\r\n width: 28px;\r\n height: 28px;\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: var(--tcw-radius-sm);\r\n background: transparent;\r\n cursor: pointer;\r\n padding: 2px;\r\n}\r\n\r\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch-wrapper {\r\n padding: 0;\r\n}\r\n\r\n.tcw-color-picker-wrap input[type='color']::-webkit-color-swatch {\r\n border: none;\r\n border-radius: 2px;\r\n}\r\n\r\n.tcw-color-hex {\r\n font-size: 11px;\r\n font-family: var(--tcw-font-mono);\r\n color: var(--tcw-text-muted);\r\n min-width: 64px;\r\n letter-spacing: 0.01em;\r\n}\r\n\r\n.tcw-toggle {\r\n width: 36px;\r\n height: 20px;\r\n background: rgba(255, 255, 255, 0.12);\r\n border-radius: 10px;\r\n position: relative;\r\n cursor: pointer;\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\r\n border: none;\r\n padding: 0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-toggle::after {\r\n content: '';\r\n position: absolute;\r\n top: 2px;\r\n left: 2px;\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n background: var(--tcw-text-muted);\r\n transition:\r\n left var(--tcw-dur-normal) var(--tcw-ease-out),\r\n background var(--tcw-dur-fast) var(--tcw-ease);\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);\r\n}\r\n\r\n.tcw-toggle.tcw-on {\r\n background: var(--tcw-accent);\r\n box-shadow: 0 0 0 2px var(--tcw-accent-glow);\r\n}\r\n\r\n.tcw-toggle.tcw-on::after {\r\n left: 18px;\r\n background: #fff;\r\n}\r\n\r\n.tcw-root[data-tcw-theme='light'] .tcw-toggle {\r\n background: rgba(0, 0, 0, 0.12);\r\n}\r\n\r\n.tcw-root[data-tcw-theme='light'] .tcw-toggle::after {\r\n background: #999;\r\n}\r\n\r\n.tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on {\r\n background: var(--tcw-accent);\r\n}\r\n\r\n.tcw-root[data-tcw-theme='light'] .tcw-toggle.tcw-on::after {\r\n background: #fff;\r\n}\r\n\r\n.tcw-settings-select {\r\n padding: 6px 10px;\r\n font-size: 12px;\r\n font-family: inherit;\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius);\r\n color: var(--tcw-text);\r\n cursor: pointer;\r\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease);\r\n}\r\n\r\n.tcw-settings-select:hover {\r\n border-color: var(--tcw-border-strong);\r\n}\r\n\r\n.tcw-settings-select:focus-visible {\r\n outline: none;\r\n border-color: var(--tcw-accent);\r\n box-shadow: var(--tcw-ring);\r\n}\r\n\r\n.tcw-modal-footer {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 14px 22px;\r\n border-top: 1px solid var(--tcw-divider);\r\n background: var(--tcw-bg-surface);\r\n border-radius: 0 0 var(--tcw-radius-xl) var(--tcw-radius-xl);\r\n}\r\n\r\n.tcw-reset-link {\r\n font-size: 12px;\r\n color: var(--tcw-text-muted);\r\n cursor: pointer;\r\n border: none;\r\n background: transparent;\r\n font-family: inherit;\r\n text-decoration: underline;\r\n text-underline-offset: 2px;\r\n text-decoration-color: var(--tcw-border-strong);\r\n transition: color var(--tcw-dur-fast) var(--tcw-ease), text-decoration-color var(--tcw-dur-fast) var(--tcw-ease);\r\n}\r\n\r\n.tcw-reset-link:hover {\r\n color: var(--tcw-text-dim);\r\n text-decoration-color: currentColor;\r\n}\r\n\r\n.tcw-done-btn {\r\n padding: 8px 18px;\r\n font-size: 12.5px;\r\n font-weight: 600;\r\n background: var(--tcw-accent);\r\n color: var(--tcw-accent-ink);\r\n border: none;\r\n border-radius: var(--tcw-radius);\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition:\r\n background var(--tcw-dur-fast) var(--tcw-ease),\r\n transform var(--tcw-dur-fast) var(--tcw-ease),\r\n box-shadow var(--tcw-dur-fast) var(--tcw-ease);\r\n letter-spacing: -0.005em;\r\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.15);\r\n}\r\n\r\n.tcw-done-btn:hover {\r\n background: var(--tcw-accent-hover);\r\n box-shadow: var(--tcw-shadow-md), 0 0 0 3px var(--tcw-accent-glow);\r\n}\r\n\r\n.tcw-done-btn:active {\r\n transform: translateY(0.5px);\r\n}\r\n\r\n/* === Status Bar === */\r\n\r\n.tcw-statusbar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 7px 16px;\r\n border-top: 1px solid var(--tcw-border);\r\n background: var(--tcw-bg-surface);\r\n font-size: 11px;\r\n color: var(--tcw-text-muted);\r\n flex-shrink: 0;\r\n font-feature-settings: 'tnum';\r\n}\r\n\r\n.tcw-status-indicator {\r\n display: flex;\r\n align-items: center;\r\n gap: 7px;\r\n font-weight: 500;\r\n}\r\n\r\n.tcw-status-dot {\r\n width: 7px;\r\n height: 7px;\r\n border-radius: 50%;\r\n background: var(--tcw-text-muted);\r\n transition: background var(--tcw-dur-normal) var(--tcw-ease), box-shadow var(--tcw-dur-normal) var(--tcw-ease);\r\n position: relative;\r\n}\r\n\r\n.tcw-status-dot.tcw-connected {\r\n background: var(--tcw-green);\r\n box-shadow: 0 0 0 3px rgba(31, 168, 116, 0.18);\r\n}\r\n\r\n.tcw-status-dot.tcw-connected::after {\r\n content: '';\r\n position: absolute;\r\n inset: -3px;\r\n border-radius: 50%;\r\n border: 2px solid var(--tcw-green);\r\n opacity: 0;\r\n animation: tcw-pulse 2.2s ease-out infinite;\r\n}\r\n\r\n@keyframes tcw-pulse {\r\n 0% { opacity: 0.6; transform: scale(0.6); }\r\n 100% { opacity: 0; transform: scale(2.2); }\r\n}\r\n\r\n.tcw-status-dot.tcw-error {\r\n background: var(--tcw-red);\r\n box-shadow: 0 0 0 3px rgba(232, 80, 91, 0.2);\r\n}\r\n\r\n/* === Command Palette === */\r\n\r\n.tcw-cmd-palette {\r\n position: fixed;\r\n z-index: 102;\r\n top: 18%;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-xl);\r\n width: 560px;\r\n max-width: 92vw;\r\n max-height: 62vh;\r\n display: flex;\r\n flex-direction: column;\r\n box-shadow: var(--tcw-shadow-xl);\r\n overflow: hidden;\r\n backdrop-filter: blur(20px);\r\n -webkit-backdrop-filter: blur(20px);\r\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\r\n}\r\n\r\n.tcw-cmd-header {\r\n display: flex;\r\n align-items: center;\r\n padding: 14px 18px;\r\n border-bottom: 1px solid var(--tcw-divider);\r\n gap: 12px;\r\n}\r\n\r\n.tcw-cmd-icon {\r\n font-size: 18px;\r\n color: var(--tcw-text-muted);\r\n flex-shrink: 0;\r\n display: inline-flex;\r\n align-items: center;\r\n}\r\n\r\n.tcw-cmd-input {\r\n flex: 1;\r\n background: transparent;\r\n border: none;\r\n outline: none;\r\n font-size: 14.5px;\r\n font-family: inherit;\r\n color: var(--tcw-text);\r\n caret-color: var(--tcw-accent);\r\n letter-spacing: -0.005em;\r\n}\r\n\r\n.tcw-cmd-input::placeholder {\r\n color: var(--tcw-text-muted);\r\n}\r\n\r\n.tcw-cmd-hint {\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n font-family: var(--tcw-font-mono);\r\n border: 1px solid var(--tcw-border);\r\n background: var(--tcw-bg-surface);\r\n padding: 3px 7px;\r\n border-radius: 4px;\r\n flex-shrink: 0;\r\n box-shadow: inset 0 -1px 0 var(--tcw-border);\r\n}\r\n\r\n.tcw-cmd-list {\r\n overflow-y: auto;\r\n flex: 1;\r\n padding: 6px;\r\n max-height: 380px;\r\n}\r\n\r\n.tcw-cmd-category {\r\n text-transform: uppercase;\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n letter-spacing: 0.09em;\r\n padding: 10px 10px 4px;\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-cmd-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 9px 12px;\r\n font-size: 13px;\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n width: 100%;\r\n border: none;\r\n background: transparent;\r\n font-family: inherit;\r\n text-align: left;\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\r\n gap: 10px;\r\n border-radius: var(--tcw-radius);\r\n letter-spacing: -0.005em;\r\n}\r\n\r\n.tcw-cmd-item:hover,\r\n.tcw-cmd-item.tcw-selected {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-cmd-item.tcw-selected {\r\n box-shadow: inset 2px 0 0 var(--tcw-accent);\r\n}\r\n\r\n.tcw-cmd-item.tcw-active .tcw-cmd-item-label {\r\n color: var(--tcw-accent);\r\n font-weight: 600;\r\n}\r\n\r\n.tcw-cmd-item-label {\r\n flex: 1;\r\n}\r\n\r\n.tcw-cmd-check {\r\n color: var(--tcw-accent);\r\n font-size: 14px;\r\n font-weight: 700;\r\n}\r\n\r\n.tcw-cmd-kbd {\r\n font-size: 10px;\r\n font-family: var(--tcw-font-mono);\r\n color: var(--tcw-text-muted);\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n padding: 2px 6px;\r\n border-radius: 4px;\r\n box-shadow: inset 0 -1px 0 var(--tcw-border);\r\n}\r\n\r\n.tcw-cmd-empty {\r\n padding: 32px 16px;\r\n text-align: center;\r\n color: var(--tcw-text-muted);\r\n font-size: 13px;\r\n}\r\n\r\n.tcw-cmd-footer {\r\n display: flex;\r\n align-items: center;\r\n gap: 18px;\r\n padding: 10px 18px;\r\n border-top: 1px solid var(--tcw-divider);\r\n font-size: 11px;\r\n color: var(--tcw-text-muted);\r\n background: var(--tcw-bg-surface);\r\n}\r\n\r\n/* === Watchlist === */\r\n\r\n.tcw-watchlist {\r\n width: 220px;\r\n flex-shrink: 0;\r\n background: var(--tcw-bg-surface);\r\n border-left: 1px solid var(--tcw-border);\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n box-shadow: var(--tcw-shadow-sm);\r\n}\r\n\r\n.tcw-watchlist-header {\r\n padding: 10px 14px;\r\n font-size: 11px;\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.08em;\r\n color: var(--tcw-text-muted);\r\n border-bottom: 1px solid var(--tcw-divider);\r\n}\r\n\r\n.tcw-watchlist-list {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 4px 0;\r\n}\r\n\r\n.tcw-watchlist-row {\r\n display: grid;\r\n grid-template-columns: 1fr auto auto;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\r\n border-left: 2px solid transparent;\r\n outline: none;\r\n}\r\n\r\n.tcw-watchlist-row:hover {\r\n background: var(--tcw-hover-bg);\r\n}\r\n\r\n.tcw-watchlist-row:focus-visible {\r\n background: var(--tcw-hover-bg);\r\n border-left-color: var(--tcw-accent);\r\n}\r\n\r\n.tcw-watchlist-row.tcw-watchlist-active {\r\n background: var(--tcw-accent-soft);\r\n border-left-color: var(--tcw-accent);\r\n}\r\n\r\n.tcw-watchlist-symbol {\r\n font-size: 12.5px;\r\n font-weight: 600;\r\n color: var(--tcw-text);\r\n letter-spacing: -0.005em;\r\n white-space: nowrap;\r\n}\r\n\r\n.tcw-watchlist-spark {\r\n width: 56px;\r\n height: 22px;\r\n align-self: center;\r\n}\r\n\r\n.tcw-watchlist-stats {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: flex-end;\r\n gap: 1px;\r\n font-variant-numeric: tabular-nums;\r\n font-family: var(--tcw-font-mono);\r\n}\r\n\r\n.tcw-watchlist-price {\r\n font-size: 12px;\r\n color: var(--tcw-text);\r\n font-weight: 500;\r\n}\r\n\r\n.tcw-watchlist-change {\r\n font-size: 10.5px;\r\n color: var(--tcw-text-muted);\r\n font-weight: 500;\r\n}\r\n\r\n.tcw-watchlist-change.tcw-up {\r\n color: var(--tcw-green);\r\n}\r\n\r\n.tcw-watchlist-change.tcw-down {\r\n color: var(--tcw-red);\r\n}\r\n\r\n@media (max-width: 768px) {\r\n .tcw-watchlist {\r\n display: none;\r\n }\r\n}\r\n\r\n/* === Toast === */\r\n\r\n.tcw-toast {\r\n position: absolute;\r\n bottom: 60px;\r\n left: 50%;\r\n transform: translate(-50%, 12px);\r\n z-index: 40;\r\n padding: 9px 14px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: 9999px;\r\n box-shadow: var(--tcw-shadow-lg);\r\n font-size: 12.5px;\r\n font-weight: 500;\r\n color: var(--tcw-text);\r\n opacity: 0;\r\n transition: opacity var(--tcw-dur-normal) var(--tcw-ease-out), transform var(--tcw-dur-normal) var(--tcw-ease-out);\r\n pointer-events: none;\r\n max-width: calc(100% - 32px);\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n letter-spacing: -0.005em;\r\n}\r\n\r\n.tcw-toast.tcw-toast-in {\r\n opacity: 1;\r\n transform: translate(-50%, 0);\r\n}\r\n\r\n.tcw-toast-error {\r\n border-color: var(--tcw-red);\r\n color: var(--tcw-red);\r\n}\r\n\r\n/* === Replay scrubber === */\r\n\r\n.tcw-replay-bar {\r\n position: absolute;\r\n left: 50%;\r\n bottom: 16px;\r\n transform: translateX(-50%);\r\n z-index: 25;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 6px 10px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: 9999px;\r\n box-shadow: var(--tcw-shadow-lg);\r\n backdrop-filter: blur(12px);\r\n -webkit-backdrop-filter: blur(12px);\r\n font-size: 12px;\r\n color: var(--tcw-text);\r\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\r\n}\r\n\r\n.tcw-replay-btn {\r\n width: 28px;\r\n height: 28px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-dim);\r\n border-radius: 9999px;\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\r\n}\r\n\r\n.tcw-replay-btn:hover {\r\n background: var(--tcw-hover-bg);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-replay-btn.tcw-replay-play {\r\n background: var(--tcw-accent);\r\n color: var(--tcw-accent-ink);\r\n width: 32px;\r\n height: 32px;\r\n box-shadow: 0 0 0 3px var(--tcw-accent-glow);\r\n}\r\n\r\n.tcw-replay-btn.tcw-replay-play:hover {\r\n background: var(--tcw-accent-hover);\r\n}\r\n\r\n.tcw-replay-scrubber {\r\n appearance: none;\r\n -webkit-appearance: none;\r\n width: 220px;\r\n height: 4px;\r\n background: var(--tcw-border-strong);\r\n border-radius: 2px;\r\n outline: none;\r\n cursor: pointer;\r\n}\r\n\r\n.tcw-replay-scrubber::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 14px;\r\n height: 14px;\r\n border-radius: 50%;\r\n background: var(--tcw-accent);\r\n border: 2px solid var(--tcw-bg-elevated);\r\n box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);\r\n cursor: pointer;\r\n}\r\n\r\n.tcw-replay-scrubber::-moz-range-thumb {\r\n width: 14px;\r\n height: 14px;\r\n border-radius: 50%;\r\n background: var(--tcw-accent);\r\n border: 2px solid var(--tcw-bg-elevated);\r\n box-shadow: 0 0 0 1px var(--tcw-accent), 0 2px 6px rgba(0, 0, 0, 0.3);\r\n cursor: pointer;\r\n}\r\n\r\n.tcw-replay-progress {\r\n font-size: 11px;\r\n font-family: var(--tcw-font-mono);\r\n color: var(--tcw-text-muted);\r\n min-width: 64px;\r\n text-align: center;\r\n font-feature-settings: 'tnum';\r\n}\r\n\r\n.tcw-replay-speed {\r\n padding: 4px 8px;\r\n font-size: 11px;\r\n font-family: var(--tcw-font-mono);\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius);\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n}\r\n\r\n.tcw-replay-speed:hover {\r\n border-color: var(--tcw-border-strong);\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .tcw-replay-scrubber {\r\n width: 140px;\r\n }\r\n .tcw-replay-progress {\r\n display: none;\r\n }\r\n}\r\n\r\n/* === Hotkey sheet === */\r\n\r\n.tcw-hotkey-grid {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 24px 32px;\r\n}\r\n\r\n.tcw-hotkey-section .tcw-settings-section-title {\r\n margin-bottom: 8px;\r\n}\r\n\r\n.tcw-hotkey-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 6px 0;\r\n border-bottom: 1px solid var(--tcw-divider);\r\n}\r\n\r\n.tcw-hotkey-row:last-child {\r\n border-bottom: none;\r\n}\r\n\r\n.tcw-hotkey-keys {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.tcw-hotkey-sep {\r\n font-size: 10px;\r\n color: var(--tcw-text-muted);\r\n}\r\n\r\n.tcw-hotkey-label {\r\n font-size: 12.5px;\r\n color: var(--tcw-text-dim);\r\n text-align: right;\r\n letter-spacing: -0.005em;\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .tcw-hotkey-grid {\r\n grid-template-columns: 1fr;\r\n gap: 18px;\r\n }\r\n}\r\n\r\n/* === Scrollbar (subtle, premium feel) === */\r\n\r\n.tcw-dropdown::-webkit-scrollbar,\r\n.tcw-modal-body::-webkit-scrollbar,\r\n.tcw-cmd-list::-webkit-scrollbar {\r\n width: 8px;\r\n height: 8px;\r\n}\r\n\r\n.tcw-dropdown::-webkit-scrollbar-track,\r\n.tcw-modal-body::-webkit-scrollbar-track,\r\n.tcw-cmd-list::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n\r\n.tcw-dropdown::-webkit-scrollbar-thumb,\r\n.tcw-modal-body::-webkit-scrollbar-thumb,\r\n.tcw-cmd-list::-webkit-scrollbar-thumb {\r\n background: var(--tcw-border-strong);\r\n border-radius: 4px;\r\n border: 2px solid transparent;\r\n background-clip: padding-box;\r\n}\r\n\r\n.tcw-dropdown::-webkit-scrollbar-thumb:hover,\r\n.tcw-modal-body::-webkit-scrollbar-thumb:hover,\r\n.tcw-cmd-list::-webkit-scrollbar-thumb:hover {\r\n background: var(--tcw-text-muted);\r\n background-clip: padding-box;\r\n border: 2px solid transparent;\r\n}\r\n\r\n/* === Responsive === */\r\n\r\n@media (max-width: 768px) {\r\n .tcw-toolbar {\r\n padding: 0 4px;\r\n height: 44px; /* Apple HIG minimum touch target */\r\n }\r\n .tcw-toolbar-sep {\r\n display: none;\r\n }\r\n .tcw-indicator-chips {\r\n display: none;\r\n }\r\n .tcw-btn,\r\n .tcw-dropdown-trigger {\r\n padding: 10px 12px; /* fatter tap target */\r\n font-size: 13px;\r\n }\r\n .tcw-btn-icon {\r\n width: 40px;\r\n height: 40px;\r\n }\r\n .tcw-sidebar {\r\n width: 44px;\r\n }\r\n .tcw-sidebar-btn {\r\n width: 40px;\r\n height: 40px;\r\n }\r\n .tcw-modal,\r\n .tcw-cmd-palette {\r\n width: 94vw;\r\n border-radius: var(--tcw-radius-lg);\r\n }\r\n\r\n /* Hide the right-side watchlist on tablets too — already declared but\r\n * grouped here for clarity. */\r\n .tcw-watchlist {\r\n display: none;\r\n }\r\n\r\n /* Replay scrubber compact mode */\r\n .tcw-replay-scrubber {\r\n width: 120px;\r\n }\r\n .tcw-replay-progress {\r\n display: none;\r\n }\r\n}\r\n\r\n/* === Mobile bottom-sheet pattern ===\r\n * On phones, swap floating-centered modals for full-width sheets that slide\r\n * up from the bottom. Bigger hit targets, no awkward off-screen clipping,\r\n * matches how every modern iOS/Android app handles overflow UI.\r\n */\r\n@media (max-width: 640px) {\r\n .tcw-modal,\r\n .tcw-cmd-palette {\r\n top: auto;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n transform: none;\r\n width: 100vw;\r\n max-width: 100vw;\r\n max-height: 92vh;\r\n border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;\r\n border-bottom: none;\r\n /* Grab handle */\r\n padding-top: 8px;\r\n }\r\n\r\n /* Visual \"grab handle\" affordance — a short pill at the top of every sheet */\r\n .tcw-modal::before,\r\n .tcw-cmd-palette::before {\r\n content: '';\r\n display: block;\r\n width: 36px;\r\n height: 4px;\r\n border-radius: 2px;\r\n background: var(--tcw-border-strong);\r\n margin: 0 auto 8px;\r\n opacity: 0.7;\r\n }\r\n\r\n /* Reuse the existing modal-in animation but slide from below instead of\r\n * popping from center, so the entrance reads as a sheet, not a dialog. */\r\n @keyframes tcw-modal-in {\r\n from { opacity: 0; transform: translateY(20px); }\r\n to { opacity: 1; transform: translateY(0); }\r\n }\r\n\r\n .tcw-modal,\r\n .tcw-cmd-palette {\r\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\r\n }\r\n\r\n /* Safe-area-aware footer padding for iPhone notch / home indicator */\r\n .tcw-modal-footer,\r\n .tcw-cmd-footer {\r\n padding-bottom: max(14px, env(safe-area-inset-bottom));\r\n }\r\n\r\n /* Larger tap targets inside sheets */\r\n .tcw-modal-tab {\r\n padding: 14px 16px;\r\n }\r\n .tcw-cmd-item {\r\n padding: 12px 14px;\r\n font-size: 14px;\r\n }\r\n .tcw-dropdown-item {\r\n padding: 12px 12px;\r\n font-size: 14px;\r\n }\r\n\r\n /* Hotkey sheet — single column on phones */\r\n .tcw-hotkey-grid {\r\n grid-template-columns: 1fr;\r\n }\r\n}\r\n\r\n/* === Price alerts panel === */\r\n\r\n.tcw-alerts-panel {\r\n position: absolute;\r\n top: 50px;\r\n right: 12px;\r\n z-index: 40;\r\n width: 300px;\r\n max-width: calc(100vw - 24px);\r\n display: flex;\r\n flex-direction: column;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: var(--tcw-shadow-lg);\r\n overflow: hidden;\r\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\r\n}\r\n\r\n@keyframes tcw-alerts-in {\r\n from { opacity: 0; transform: translateY(-6px) scale(0.98); }\r\n to { opacity: 1; transform: none; }\r\n}\r\n\r\n.tcw-alerts-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 10px 12px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n color: var(--tcw-text);\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n\r\n.tcw-alerts-close {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-alerts-close:hover {\r\n background: var(--tcw-bg-surface);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-alerts-form {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 8px;\r\n padding: 12px;\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n\r\n.tcw-alerts-form input,\r\n.tcw-alerts-form select {\r\n width: 100%;\r\n min-width: 0;\r\n box-sizing: border-box;\r\n height: 32px;\r\n padding: 0 8px;\r\n font-size: 12px;\r\n color: var(--tcw-text);\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-sm);\r\n outline: none;\r\n}\r\n.tcw-alerts-form input:focus,\r\n.tcw-alerts-form select:focus {\r\n border-color: var(--tcw-accent);\r\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\r\n}\r\n.tcw-alerts-message,\r\n.tcw-alerts-source {\r\n grid-column: 1 / -1;\r\n}\r\n\r\n.tcw-alerts-add {\r\n grid-column: 1 / -1;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 6px;\r\n height: 34px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: var(--tcw-accent-ink);\r\n background: var(--tcw-accent);\r\n border: none;\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-alerts-add:hover {\r\n background: var(--tcw-accent-hover);\r\n}\r\n\r\n.tcw-alerts-list {\r\n max-height: 260px;\r\n overflow-y: auto;\r\n padding: 6px;\r\n}\r\n\r\n.tcw-alerts-empty {\r\n padding: 18px 12px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: var(--tcw-text-muted);\r\n line-height: 1.5;\r\n}\r\n\r\n.tcw-alerts-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 8px 8px;\r\n border-radius: var(--tcw-radius-sm);\r\n}\r\n.tcw-alerts-row:hover {\r\n background: var(--tcw-bg-surface);\r\n}\r\n.tcw-alerts-triggered {\r\n background: var(--tcw-accent-soft);\r\n}\r\n\r\n.tcw-alerts-info {\r\n min-width: 0;\r\n}\r\n.tcw-alerts-row-main {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: var(--tcw-text);\r\n font-variant-numeric: tabular-nums;\r\n}\r\n.tcw-alerts-row-note {\r\n margin-top: 2px;\r\n font-size: 11px;\r\n color: var(--tcw-text-muted);\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n.tcw-alerts-badge {\r\n font-size: 9px;\r\n font-weight: 700;\r\n text-transform: uppercase;\r\n letter-spacing: 0.04em;\r\n padding: 2px 5px;\r\n border-radius: 999px;\r\n color: var(--tcw-accent);\r\n background: var(--tcw-accent-soft);\r\n}\r\n\r\n.tcw-alerts-del {\r\n flex-shrink: 0;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-alerts-del:hover {\r\n background: var(--tcw-red-soft);\r\n color: var(--tcw-red);\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .tcw-alerts-panel {\r\n top: auto;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n width: 100vw;\r\n max-width: 100vw;\r\n border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;\r\n }\r\n .tcw-alerts-list {\r\n max-height: 40vh;\r\n padding-bottom: max(8px, env(safe-area-inset-bottom));\r\n }\r\n}\r\n\r\n/* === Data Window === */\r\n\r\n.tcw-datawin {\r\n position: absolute;\r\n top: 50px;\r\n right: 12px;\r\n z-index: 38;\r\n width: 200px;\r\n display: flex;\r\n flex-direction: column;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: var(--tcw-shadow-lg);\r\n overflow: hidden;\r\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\r\n}\r\n.tcw-datawin-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 9px 12px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: var(--tcw-text);\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n.tcw-datawin-close {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 24px;\r\n height: 24px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-datawin-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\r\n.tcw-datawin-body { padding: 6px 4px; max-height: 360px; overflow-y: auto; }\r\n.tcw-datawin-empty { padding: 14px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }\r\n.tcw-datawin-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 10px;\r\n padding: 3px 8px;\r\n font-size: 12px;\r\n}\r\n.tcw-datawin-label { color: var(--tcw-text-muted); }\r\n.tcw-datawin-value { color: var(--tcw-text); font-variant-numeric: tabular-nums; font-weight: 600; }\r\n.tcw-datawin-value.tcw-up { color: var(--tcw-green); }\r\n.tcw-datawin-value.tcw-down { color: var(--tcw-red); }\r\n.tcw-datawin-sub {\r\n margin: 6px 8px 2px;\r\n font-size: 10px;\r\n font-weight: 700;\r\n text-transform: uppercase;\r\n letter-spacing: 0.04em;\r\n color: var(--tcw-text-muted);\r\n border-top: 1px solid var(--tcw-border);\r\n padding-top: 6px;\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .tcw-datawin { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }\r\n}\r\n\r\n/* === Depth-of-market ladder === */\r\n\r\n.tcw-ladder {\r\n position: absolute;\r\n top: 50px;\r\n right: 12px;\r\n z-index: 41;\r\n width: 240px;\r\n display: flex;\r\n flex-direction: column;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: var(--tcw-shadow-lg);\r\n overflow: hidden;\r\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\r\n}\r\n.tcw-ladder-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 10px 12px;\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: var(--tcw-text);\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n.tcw-ladder-close {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-ladder-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\r\n.tcw-ladder-cols {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr 1fr;\r\n padding: 4px 0;\r\n font-size: 10px;\r\n font-weight: 700;\r\n text-transform: uppercase;\r\n letter-spacing: 0.04em;\r\n color: var(--tcw-text-muted);\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n.tcw-ladder-cols span { text-align: center; }\r\n.tcw-ladder-body { max-height: 360px; overflow-y: auto; }\r\n.tcw-ladder-empty { padding: 18px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }\r\n\r\n.tcw-ladder-row {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr 1fr;\r\n height: 22px;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n.tcw-ladder-cell {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n border: none;\r\n background: transparent;\r\n font-size: 11px;\r\n cursor: pointer;\r\n font-variant-numeric: tabular-nums;\r\n overflow: hidden;\r\n}\r\n.tcw-ladder-cell:disabled { cursor: default; }\r\n/* Depth bar grows from the centre column outward. */\r\n.tcw-ladder-cell::before {\r\n content: '';\r\n position: absolute;\r\n top: 1px; bottom: 1px;\r\n width: var(--w, 0%);\r\n}\r\n.tcw-ladder-bid { justify-content: flex-end; padding-right: 8px; color: var(--tcw-green); }\r\n.tcw-ladder-bid::before { right: 0; background: var(--tcw-green-soft); }\r\n.tcw-ladder-bid span, .tcw-ladder-bid { position: relative; }\r\n.tcw-ladder-ask { justify-content: flex-start; padding-left: 8px; color: var(--tcw-red); }\r\n.tcw-ladder-ask::before { left: 0; background: var(--tcw-red-soft); }\r\n.tcw-ladder-cell:not(:disabled):hover::before { opacity: 0.7; filter: brightness(1.4); }\r\n.tcw-ladder-cell > * { position: relative; }\r\n.tcw-ladder-price {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--tcw-text-dim);\r\n border-left: 1px solid var(--tcw-border);\r\n border-right: 1px solid var(--tcw-border);\r\n}\r\n.tcw-ladder-price.tcw-ask { color: var(--tcw-red); }\r\n.tcw-ladder-price.tcw-bid { color: var(--tcw-green); }\r\n\r\n@media (max-width: 640px) {\r\n .tcw-ladder { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }\r\n .tcw-ladder-body { max-height: 45vh; padding-bottom: max(0px, env(safe-area-inset-bottom)); }\r\n}\r\n\r\n/* === Bracket order placement === */\r\n\r\n.tcw-btn-long:hover { color: var(--tcw-green) !important; }\r\n.tcw-btn-short:hover { color: var(--tcw-red) !important; }\r\n\r\n.tcw-bracket-bar {\r\n position: absolute;\r\n top: 52px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n z-index: 45;\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n padding: 7px 8px 7px 14px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: 999px;\r\n box-shadow: var(--tcw-shadow-lg);\r\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\r\n}\r\n.tcw-bracket-label {\r\n font-size: 12px;\r\n font-weight: 700;\r\n}\r\n.tcw-bracket-label[data-side='buy'] { color: var(--tcw-green); }\r\n.tcw-bracket-label[data-side='sell'] { color: var(--tcw-red); }\r\n.tcw-bracket-hint {\r\n font-size: 11px;\r\n color: var(--tcw-text-muted);\r\n}\r\n.tcw-bracket-cancel, .tcw-bracket-confirm {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 5px;\r\n height: 30px;\r\n padding: 0 12px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n border: none;\r\n border-radius: 999px;\r\n cursor: pointer;\r\n}\r\n.tcw-bracket-cancel {\r\n color: var(--tcw-text-dim);\r\n background: var(--tcw-bg-surface);\r\n}\r\n.tcw-bracket-cancel:hover { color: var(--tcw-text); }\r\n.tcw-bracket-confirm {\r\n color: var(--tcw-accent-ink);\r\n background: var(--tcw-accent);\r\n}\r\n.tcw-bracket-confirm:hover { background: var(--tcw-accent-hover); }\r\n\r\n@media (max-width: 640px) {\r\n .tcw-bracket-bar { width: calc(100vw - 24px); justify-content: space-between; }\r\n .tcw-bracket-hint { display: none; }\r\n}\r\n\r\n/* === Drawing style + templates popover === */\r\n\r\n.tcw-style-panel {\r\n position: absolute;\r\n bottom: 12px;\r\n left: 52px;\r\n z-index: 40;\r\n width: 220px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n padding: 12px;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: var(--tcw-shadow-lg);\r\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\r\n}\r\n.tcw-style-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: var(--tcw-text);\r\n}\r\n.tcw-style-close {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 24px;\r\n height: 24px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-style-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\r\n\r\n.tcw-style-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\r\n.tcw-style-swatch {\r\n width: 18px;\r\n height: 18px;\r\n border-radius: 50%;\r\n border: 1px solid var(--tcw-border-strong);\r\n cursor: pointer;\r\n padding: 0;\r\n}\r\n.tcw-style-swatch.tcw-on { outline: 2px solid var(--tcw-accent); outline-offset: 1px; }\r\n.tcw-style-picker {\r\n width: 22px;\r\n height: 22px;\r\n padding: 0;\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-sm);\r\n background: transparent;\r\n cursor: pointer;\r\n}\r\n.tcw-style-width, .tcw-style-dash {\r\n flex: 1;\r\n min-width: 0;\r\n height: 26px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-sm);\r\n color: var(--tcw-text-dim);\r\n cursor: pointer;\r\n font-size: 11px;\r\n}\r\n.tcw-style-width span { width: 16px; background: currentColor; border-radius: 2px; }\r\n.tcw-style-width.tcw-on, .tcw-style-dash.tcw-on {\r\n border-color: var(--tcw-accent);\r\n color: var(--tcw-accent);\r\n}\r\n\r\n.tcw-style-subhead {\r\n font-size: 10px;\r\n font-weight: 700;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n color: var(--tcw-text-muted);\r\n margin-top: 2px;\r\n}\r\n.tcw-style-save { display: flex; gap: 6px; }\r\n.tcw-style-name {\r\n flex: 1;\r\n min-width: 0;\r\n height: 28px;\r\n padding: 0 8px;\r\n font-size: 12px;\r\n color: var(--tcw-text);\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-sm);\r\n outline: none;\r\n}\r\n.tcw-style-name:focus { border-color: var(--tcw-accent); }\r\n.tcw-style-savebtn {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 0 10px;\r\n height: 28px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: var(--tcw-accent-ink);\r\n background: var(--tcw-accent);\r\n border: none;\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-style-savebtn:hover { background: var(--tcw-accent-hover); }\r\n\r\n.tcw-style-templates { display: flex; flex-direction: column; gap: 2px; max-height: 140px; overflow-y: auto; }\r\n.tcw-style-empty { font-size: 11px; color: var(--tcw-text-muted); padding: 4px 0; }\r\n.tcw-style-template { display: flex; align-items: center; gap: 4px; }\r\n.tcw-style-apply {\r\n flex: 1;\r\n min-width: 0;\r\n display: flex;\r\n align-items: center;\r\n gap: 7px;\r\n padding: 5px 7px;\r\n font-size: 12px;\r\n color: var(--tcw-text);\r\n background: transparent;\r\n border: none;\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n text-align: left;\r\n}\r\n.tcw-style-apply:hover { background: var(--tcw-bg-surface); }\r\n.tcw-style-tdot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; }\r\n.tcw-style-tdel {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-style-tdel:hover { background: var(--tcw-red-soft); color: var(--tcw-red); }\r\n\r\n/* === Settings range slider === */\r\n\r\n.tcw-settings-range {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n.tcw-settings-range input[type='range'] {\r\n width: 110px;\r\n accent-color: var(--tcw-accent);\r\n cursor: pointer;\r\n}\r\n.tcw-settings-range-val {\r\n min-width: 38px;\r\n text-align: right;\r\n font-size: 12px;\r\n font-variant-numeric: tabular-nums;\r\n color: var(--tcw-text-dim);\r\n}\r\n\r\n/* === Indicator settings dialog === */\r\n\r\n.tcw-modal-narrow {\r\n max-width: 360px;\r\n}\r\n.tcw-indi-input {\r\n width: 110px;\r\n height: 30px;\r\n padding: 0 8px;\r\n font-size: 12px;\r\n color: var(--tcw-text);\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-sm);\r\n outline: none;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n.tcw-indi-input:focus {\r\n border-color: var(--tcw-accent);\r\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\r\n}\r\n.tcw-indi-color {\r\n width: 36px;\r\n height: 28px;\r\n padding: 2px;\r\n background: var(--tcw-bg-surface);\r\n border: 1px solid var(--tcw-border);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n\r\n/* === Object tree panel === */\r\n\r\n.tcw-tree-panel {\r\n position: absolute;\r\n top: 50px;\r\n right: 12px;\r\n z-index: 39;\r\n width: 280px;\r\n max-width: calc(100vw - 24px);\r\n display: flex;\r\n flex-direction: column;\r\n background: var(--tcw-bg-elevated);\r\n border: 1px solid var(--tcw-border-strong);\r\n border-radius: var(--tcw-radius-lg);\r\n box-shadow: var(--tcw-shadow-lg);\r\n overflow: hidden;\r\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\r\n}\r\n\r\n.tcw-tree-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 10px 12px;\r\n font-weight: 600;\r\n font-size: 13px;\r\n color: var(--tcw-text);\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n.tcw-tree-close {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-tree-close:hover {\r\n background: var(--tcw-bg-surface);\r\n color: var(--tcw-text);\r\n}\r\n\r\n.tcw-tree-section {\r\n padding: 6px;\r\n border-bottom: 1px solid var(--tcw-border);\r\n}\r\n.tcw-tree-section:last-child {\r\n border-bottom: none;\r\n}\r\n.tcw-tree-section-head {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 6px 8px 4px;\r\n font-size: 10px;\r\n font-weight: 700;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n color: var(--tcw-text-muted);\r\n}\r\n.tcw-tree-add {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 22px;\r\n height: 22px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-tree-add:hover {\r\n background: var(--tcw-accent-soft);\r\n color: var(--tcw-accent);\r\n}\r\n.tcw-tree-dot {\r\n flex-shrink: 0;\r\n width: 8px;\r\n height: 8px;\r\n border-radius: 50%;\r\n}\r\n.tcw-tree-list {\r\n max-height: 200px;\r\n overflow-y: auto;\r\n}\r\n\r\n.tcw-tree-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 6px 8px;\r\n border-radius: var(--tcw-radius-sm);\r\n}\r\n.tcw-tree-row:hover {\r\n background: var(--tcw-bg-surface);\r\n}\r\n.tcw-tree-hidden .tcw-tree-name {\r\n opacity: 0.5;\r\n}\r\n.tcw-tree-name {\r\n min-width: 0;\r\n font-size: 12px;\r\n color: var(--tcw-text);\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n.tcw-tree-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 2px;\r\n flex-shrink: 0;\r\n}\r\n.tcw-tree-btn {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n border: none;\r\n background: transparent;\r\n color: var(--tcw-text-muted);\r\n border-radius: var(--tcw-radius-sm);\r\n cursor: pointer;\r\n}\r\n.tcw-tree-btn:hover {\r\n background: var(--tcw-bg-elevated);\r\n color: var(--tcw-text);\r\n}\r\n.tcw-tree-btn.tcw-tree-on {\r\n color: var(--tcw-accent);\r\n}\r\n.tcw-tree-btn.tcw-tree-del:hover {\r\n background: var(--tcw-red-soft);\r\n color: var(--tcw-red);\r\n}\r\n.tcw-tree-empty {\r\n padding: 8px;\r\n font-size: 12px;\r\n color: var(--tcw-text-muted);\r\n}\r\n\r\n@media (max-width: 640px) {\r\n .tcw-tree-panel {\r\n top: auto;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n width: 100vw;\r\n max-width: 100vw;\r\n border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;\r\n }\r\n .tcw-tree-list {\r\n max-height: 30vh;\r\n }\r\n .tcw-tree-section:last-child {\r\n padding-bottom: max(6px, env(safe-area-inset-bottom));\r\n }\r\n}\r\n\r\n/* === Reduced motion === */\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n .tcw-root *,\r\n .tcw-root *::before,\r\n .tcw-root *::after {\r\n animation-duration: 0.01ms !important;\r\n animation-iteration-count: 1 !important;\r\n transition-duration: 0.01ms !important;\r\n }\r\n}\r\n", m = 0, h = "tcw-styles";
604
719
  function g() {
605
720
  if (m++, m > 1 || document.getElementById(h)) return;
606
721
  let e = document.createElement("style");
@@ -618,6 +733,7 @@ var v = {
618
733
  trendingUp: "<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"/><polyline points=\"16 7 22 7 22 13\"/>",
619
734
  minus: "<path d=\"M5 12h14\"/>",
620
735
  penLine: "<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>",
736
+ zigzag: "<polyline points=\"2 18 7 8 12 14 17 4 22 12\"/>",
621
737
  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\"/>",
622
738
  square: "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>",
623
739
  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\"/>",
@@ -691,14 +807,15 @@ var b = class {
691
807
  }, ne = class {
692
808
  config;
693
809
  callbacks;
810
+ t;
694
811
  el;
695
812
  chartTypeDropdown = null;
696
813
  indicatorDropdown = null;
697
814
  tfButtons = [];
698
815
  chipsContainer = null;
699
816
  themeBtn = null;
700
- constructor(e, t, n) {
701
- this.config = t, this.callbacks = n, this.el = document.createElement("div"), this.el.className = "tcw-toolbar", this.build(), e.appendChild(this.el);
817
+ constructor(e, t, n, r) {
818
+ this.config = t, this.callbacks = n, this.t = r, this.el = document.createElement("div"), this.el.className = "tcw-toolbar", this.build(), e.appendChild(this.el);
702
819
  }
703
820
  build() {
704
821
  let { config: e, callbacks: t, el: n } = this, r = document.createElement("button");
@@ -718,35 +835,39 @@ var b = class {
718
835
  s.style.position = "relative", s.style.display = "inline-flex";
719
836
  let c = document.createElement("button");
720
837
  if (c.className = "tcw-dropdown-trigger", c.dataset.role = "indicators", s.appendChild(c), n.appendChild(s), this.indicatorDropdown = new b(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) {
721
- let e = this.iconBtn("play", "Bar replay", t.onToggleReplay);
838
+ let e = this.iconBtn("play", this.t("toolbar.replay"), t.onToggleReplay);
722
839
  e.dataset.role = "replay", n.appendChild(e);
723
840
  }
724
841
  if (t.onBracket) {
725
- let e = t.onBracket, r = this.iconBtn("trendingUp", "Long bracket", () => e("buy"));
842
+ let e = t.onBracket, r = this.iconBtn("trendingUp", this.t("toolbar.longBracket"), () => e("buy"));
726
843
  r.dataset.role = "long", r.classList.add("tcw-btn-long"), n.appendChild(r);
727
- let i = this.iconBtn("trendingDown", "Short bracket", () => e("sell"));
844
+ let i = this.iconBtn("trendingDown", this.t("toolbar.shortBracket"), () => e("sell"));
728
845
  i.dataset.role = "short", i.classList.add("tcw-btn-short"), n.appendChild(i);
729
846
  }
730
847
  if (t.onToggleLadder) {
731
- let e = this.iconBtn("ladder", "Depth ladder", t.onToggleLadder);
848
+ let e = this.iconBtn("ladder", this.t("toolbar.depthLadder"), t.onToggleLadder);
732
849
  e.dataset.role = "ladder", n.appendChild(e);
733
850
  }
734
851
  if (t.onToggleObjects) {
735
- let e = this.iconBtn("layers", "Objects", t.onToggleObjects);
852
+ let e = this.iconBtn("layers", this.t("toolbar.objects"), t.onToggleObjects);
736
853
  e.dataset.role = "objects", n.appendChild(e);
737
854
  }
738
855
  if (t.onToggleAlerts) {
739
- let e = this.iconBtn("bell", "Price alerts", t.onToggleAlerts);
856
+ let e = this.iconBtn("bell", this.t("toolbar.priceAlerts"), t.onToggleAlerts);
740
857
  e.dataset.role = "alerts", n.appendChild(e);
741
858
  }
742
- let l = this.iconBtn("camera", "Screenshot", t.onScreenshot);
859
+ let l = this.iconBtn("camera", this.t("toolbar.screenshot"), t.onScreenshot);
743
860
  n.appendChild(l);
744
- let u = this.iconBtn("settings", "Chart Settings", t.onSettings);
745
- n.appendChild(u), this.themeBtn = this.iconBtn("moon", "Toggle theme", t.onToggleTheme), this.themeBtn.dataset.role = "theme", n.appendChild(this.themeBtn);
861
+ let u = this.iconBtn("settings", this.t("toolbar.settings"), t.onSettings);
862
+ n.appendChild(u), this.themeBtn = this.iconBtn("moon", this.t("toolbar.toggleTheme"), t.onToggleTheme), this.themeBtn.dataset.role = "theme", n.appendChild(this.themeBtn);
863
+ }
864
+ chartTypeLabel(e) {
865
+ let t = `chartType.${e.value}`, n = this.t(t);
866
+ return n === t ? e.label : n;
746
867
  }
747
868
  buildChartTypeMenu() {
748
869
  if (!this.chartTypeDropdown) return;
749
- let e = this.config.chartTypes.map((e) => `<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join("");
870
+ let e = this.config.chartTypes.map((e) => `<button class="tcw-dropdown-item" data-ct="${e.value}">${this.chartTypeLabel(e)}</button>`).join("");
750
871
  this.chartTypeDropdown.setContent(e), this.chartTypeDropdown.panel.querySelectorAll(".tcw-dropdown-item").forEach((e) => {
751
872
  e.addEventListener("click", (e) => {
752
873
  let t = e.currentTarget.dataset.ct;
@@ -756,11 +877,11 @@ var b = class {
756
877
  }
757
878
  buildIndicatorMenu() {
758
879
  if (!this.indicatorDropdown) return;
759
- 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>";
760
- 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>`;
761
- i += "<div class=\"tcw-dropdown-divider\"></div>", i += "<div class=\"tcw-dropdown-label\">All</div>";
762
- 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>`;
763
- this.indicatorDropdown.setContent(i), this.indicatorDropdown.panel.querySelectorAll(".tcw-dropdown-item[data-ind]").forEach((e) => {
880
+ let { indicators: e, popularIndicatorIds: t } = this.config, n = e.filter((e) => t.includes(e.id)), r = e.filter((e) => !t.includes(e.id)), i = (e) => this.t(`indicatorType.${e}`), a = `<div class="tcw-dropdown-label">${this.t("toolbar.indicators.popular")}</div>`;
881
+ for (let e of n) a += `<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${i(e.type)}</span></button>`;
882
+ a += "<div class=\"tcw-dropdown-divider\"></div>", a += `<div class="tcw-dropdown-label">${this.t("toolbar.indicators.all")}</div>`;
883
+ for (let e of r) a += `<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${i(e.type)}</span></button>`;
884
+ this.indicatorDropdown.setContent(a), this.indicatorDropdown.panel.querySelectorAll(".tcw-dropdown-item[data-ind]").forEach((e) => {
764
885
  e.addEventListener("click", (e) => {
765
886
  let t = e.currentTarget.dataset.ind;
766
887
  this.callbacks.onAddIndicator(t);
@@ -773,12 +894,12 @@ var b = class {
773
894
  for (let t of this.tfButtons) t.classList.toggle("tcw-active", t.dataset.tf === e.timeframe);
774
895
  let n = this.el.querySelector("[data-role=\"charttype\"]");
775
896
  if (n) {
776
- let t = this.config.chartTypes.find((t) => t.value === e.chartType)?.label ?? "Candles";
777
- n.innerHTML = `${y("barChart", 14)} ${t} ${y("chevronDown", 12)}`;
897
+ let t = this.config.chartTypes.find((t) => t.value === e.chartType), r = t ? this.chartTypeLabel(t) : e.chartType;
898
+ n.innerHTML = `${y("barChart", 14)} ${r} ${y("chevronDown", 12)}`;
778
899
  }
779
900
  let r = this.el.querySelector("[data-role=\"indicators\"]");
780
901
  if (r) {
781
- let t = e.activeIndicators.size, n = `${y("trendingUp", 14)} Indicators`;
902
+ let t = e.activeIndicators.size, n = `${y("trendingUp", 14)} ${this.t("toolbar.indicators")}`;
782
903
  t > 0 && (n += ` <span class="tcw-badge-count">${t}</span>`), r.innerHTML = n;
783
904
  }
784
905
  if (this.chipsContainer) {
@@ -826,33 +947,52 @@ var b = class {
826
947
  "hash",
827
948
  "square",
828
949
  "gitBranch",
950
+ "zigzag",
829
951
  "ruler",
830
- "type"
952
+ "type",
953
+ "ladder"
831
954
  ], ie = {
832
955
  trendLine: "trendingUp",
833
956
  ray: "trendingUp",
834
957
  extendedLine: "trendingUp",
958
+ infoLine: "trendingUp",
959
+ trendAngle: "trendingUp",
835
960
  horizontalLine: "minus",
961
+ horizontalRay: "minus",
836
962
  verticalLine: "penLine",
963
+ crossLine: "plus",
837
964
  rectangle: "square",
965
+ circle: "square",
838
966
  ellipse: "square",
839
967
  triangle: "square",
840
968
  arrow: "trendingUp",
841
969
  parallelChannel: "gitBranch",
842
970
  regressionChannel: "gitBranch",
843
971
  pitchfork: "gitBranch",
972
+ schiffPitchfork: "gitBranch",
973
+ modifiedSchiffPitchfork: "gitBranch",
844
974
  fibRetracement: "hash",
845
975
  fibExtension: "hash",
846
976
  fibTimeZones: "hash",
977
+ fibChannel: "hash",
978
+ fibSpeedResistanceFan: "hash",
847
979
  gannBox: "hash",
848
980
  gannFan: "gitBranch",
849
- elliottWave: "trendingUp",
981
+ cyclicLines: "barChart",
982
+ elliottWave: "zigzag",
983
+ xabcdPattern: "zigzag",
984
+ abcdPattern: "zigzag",
985
+ headAndShoulders: "zigzag",
850
986
  priceRange: "ruler",
851
987
  dateRange: "ruler",
988
+ dateAndPriceRange: "ruler",
852
989
  measure: "ruler",
990
+ text: "type",
853
991
  textAnnotation: "type",
992
+ priceLabel: "type",
854
993
  anchoredVWAP: "trendingUp",
855
- volumeProfileRange: "barChart"
994
+ volumeProfileRange: "barChart",
995
+ riskReward: "square"
856
996
  };
857
997
  function ae(e) {
858
998
  return ie[e] ?? "penLine";
@@ -864,7 +1004,7 @@ function oe(e, t) {
864
1004
  }
865
1005
  return t;
866
1006
  }
867
- var x = class {
1007
+ var se = class {
868
1008
  config;
869
1009
  callbacks;
870
1010
  el;
@@ -959,20 +1099,21 @@ var x = class {
959
1099
  destroy() {
960
1100
  this.hideFlyout(), this.el.remove();
961
1101
  }
962
- }, S = [
1102
+ }, x = [
963
1103
  "style",
964
1104
  "display",
965
1105
  "scale"
966
- ], C = class {
1106
+ ], S = class {
967
1107
  callbacks;
1108
+ t;
968
1109
  backdrop = null;
969
1110
  modal = null;
970
1111
  currentTab = "style";
971
1112
  currentSettings = null;
972
1113
  bodyEl = null;
973
1114
  tabButtons = [];
974
- constructor(e) {
975
- this.callbacks = e;
1115
+ constructor(e, t) {
1116
+ this.callbacks = e, this.t = t;
976
1117
  }
977
1118
  open(e) {
978
1119
  this.currentSettings = { ...e }, this.currentTab = "style", this.buildModal();
@@ -987,16 +1128,16 @@ var x = class {
987
1128
  let e = document.createElement("div");
988
1129
  e.className = "tcw-modal-header";
989
1130
  let t = document.createElement("h3");
990
- t.textContent = "Chart Settings", e.appendChild(t);
1131
+ t.textContent = this.t("settings.title"), e.appendChild(t);
991
1132
  let n = document.createElement("button");
992
1133
  n.className = "tcw-modal-close", n.innerHTML = y("x", 16), n.addEventListener("click", () => {
993
1134
  this.callbacks.onClose(), this.close();
994
1135
  }), e.appendChild(n), this.modal.appendChild(e);
995
1136
  let r = document.createElement("div");
996
1137
  r.className = "tcw-modal-tabs", this.tabButtons = [];
997
- for (let e of S) {
1138
+ for (let e of x) {
998
1139
  let t = document.createElement("button");
999
- t.className = "tcw-modal-tab", t.textContent = e, t.dataset.tab = e, e === this.currentTab && t.classList.add("tcw-active"), t.addEventListener("click", () => {
1140
+ t.className = "tcw-modal-tab", t.textContent = this.t(`settings.tab.${e}`), t.dataset.tab = e, e === this.currentTab && t.classList.add("tcw-active"), t.addEventListener("click", () => {
1000
1141
  this.currentTab = e, this.tabButtons.forEach((t) => t.classList.toggle("tcw-active", t.dataset.tab === e)), this.renderTabContent();
1001
1142
  }), r.appendChild(t), this.tabButtons.push(t);
1002
1143
  }
@@ -1004,9 +1145,9 @@ var x = class {
1004
1145
  let i = document.createElement("div");
1005
1146
  i.className = "tcw-modal-footer";
1006
1147
  let a = document.createElement("button");
1007
- a.className = "tcw-reset-link", a.textContent = "Reset to defaults", a.addEventListener("click", () => this.callbacks.onReset()), i.appendChild(a);
1148
+ a.className = "tcw-reset-link", a.textContent = this.t("settings.resetToDefaults"), a.addEventListener("click", () => this.callbacks.onReset()), i.appendChild(a);
1008
1149
  let o = document.createElement("button");
1009
- o.className = "tcw-done-btn", o.textContent = "Done", o.addEventListener("click", () => {
1150
+ o.className = "tcw-done-btn", o.textContent = this.t("settings.done"), o.addEventListener("click", () => {
1010
1151
  this.callbacks.onClose(), this.close();
1011
1152
  }), i.appendChild(o), this.modal.appendChild(i), document.body.appendChild(this.modal);
1012
1153
  let s = (e) => {
@@ -1029,9 +1170,9 @@ var x = class {
1029
1170
  }
1030
1171
  renderStyleTab() {
1031
1172
  if (!this.bodyEl || !this.currentSettings) return;
1032
- let e = this.currentSettings, t = this.section("Candle Colors");
1173
+ let e = this.currentSettings, t = this.section(this.t("settings.section.candleColors"));
1033
1174
  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);
1034
- let n = this.section("Background");
1175
+ let n = this.section(this.t("settings.section.background"));
1035
1176
  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);
1036
1177
  }
1037
1178
  renderDisplayTab() {
@@ -1205,7 +1346,7 @@ var x = class {
1205
1346
  destroy() {
1206
1347
  this.close();
1207
1348
  }
1208
- }, w = class {
1349
+ }, C = class {
1209
1350
  el;
1210
1351
  dotEl;
1211
1352
  messageEl;
@@ -1221,7 +1362,7 @@ var x = class {
1221
1362
  destroy() {
1222
1363
  this.el.remove();
1223
1364
  }
1224
- }, T = class {
1365
+ }, w = class {
1225
1366
  backdrop = null;
1226
1367
  modal = null;
1227
1368
  input = null;
@@ -1346,7 +1487,7 @@ var x = class {
1346
1487
  destroy() {
1347
1488
  this.close();
1348
1489
  }
1349
- }, E = class {
1490
+ }, T = class {
1350
1491
  backdrop = null;
1351
1492
  modal = null;
1352
1493
  input = null;
@@ -1370,7 +1511,7 @@ var x = class {
1370
1511
  let r = document.createElement("div");
1371
1512
  r.className = "tcw-cmd-header";
1372
1513
  let i = document.createElement("span");
1373
- i.className = "tcw-cmd-icon", i.innerHTML = A(), 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);
1514
+ i.className = "tcw-cmd-icon", i.innerHTML = k(), 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);
1374
1515
  let a = document.createElement("span");
1375
1516
  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);
1376
1517
  let o = document.createElement("div");
@@ -1389,7 +1530,7 @@ var x = class {
1389
1530
  let e = (this.input?.value ?? "").toUpperCase().trim();
1390
1531
  e ? this.filtered = this.symbols.map((t) => ({
1391
1532
  symbol: t,
1392
- score: D(t.toUpperCase(), e)
1533
+ score: E(t.toUpperCase(), e)
1393
1534
  })).filter((e) => e.score > 0).sort((e, t) => t.score - e.score) : this.filtered = this.symbols.map((e) => ({
1394
1535
  symbol: e,
1395
1536
  score: 0
@@ -1407,7 +1548,7 @@ var x = class {
1407
1548
  let { symbol: n } = this.filtered[t], r = document.createElement("button");
1408
1549
  r.className = "tcw-cmd-item", t === this.selectedIndex && r.classList.add("tcw-selected"), n === this.current && r.classList.add("tcw-active");
1409
1550
  let i = document.createElement("span");
1410
- if (i.className = "tcw-cmd-item-label", i.innerHTML = O(n, e), r.appendChild(i), n === this.current) {
1551
+ if (i.className = "tcw-cmd-item-label", i.innerHTML = D(n, e), r.appendChild(i), n === this.current) {
1411
1552
  let e = document.createElement("span");
1412
1553
  e.className = "tcw-cmd-check", e.textContent = "✓", r.appendChild(e);
1413
1554
  }
@@ -1444,7 +1585,7 @@ var x = class {
1444
1585
  }
1445
1586
  }
1446
1587
  };
1447
- function D(e, t) {
1588
+ function E(e, t) {
1448
1589
  if (e === t) return 1e3;
1449
1590
  if (e.startsWith(t)) return 500 + (50 - Math.min(50, e.length - t.length));
1450
1591
  if (e.includes(t)) return 200 + (50 - Math.min(50, e.length - t.length));
@@ -1452,13 +1593,13 @@ function D(e, t) {
1452
1593
  for (let a = 0; a < e.length && n < t.length; a++) e[a] === t[n] && (r >= 0 && (i += a - r - 1), r = a, n++);
1453
1594
  return n < t.length ? 0 : 100 - Math.min(99, i);
1454
1595
  }
1455
- function O(e, t) {
1456
- if (!t) return k(e);
1596
+ function D(e, t) {
1597
+ if (!t) return O(e);
1457
1598
  let n = e.toUpperCase(), r = "", i = 0;
1458
- 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">${k(e[a])}</mark>`, i++) : r += k(e[a]);
1599
+ 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">${O(e[a])}</mark>`, i++) : r += O(e[a]);
1459
1600
  return r;
1460
1601
  }
1461
- function k(e) {
1602
+ function O(e) {
1462
1603
  return e.replace(/[&<>"']/g, (e) => ({
1463
1604
  "&": "&amp;",
1464
1605
  "<": "&lt;",
@@ -1467,12 +1608,18 @@ function k(e) {
1467
1608
  "'": "&#39;"
1468
1609
  })[e]);
1469
1610
  }
1470
- function A() {
1611
+ function k() {
1471
1612
  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>";
1472
1613
  }
1473
1614
  //#endregion
1474
1615
  //#region src/widget/WidgetHotkeySheet.ts
1475
- var j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent) ? "⌘" : "Ctrl", M = [
1616
+ var A = {
1617
+ "Search & navigation": "hotkeys.group.searchNavigation",
1618
+ "Chart manipulation": "hotkeys.group.chartManipulation",
1619
+ "Touch (mobile / tablet)": "hotkeys.group.touch",
1620
+ Keyboard: "hotkeys.group.keyboard",
1621
+ Drawing: "hotkeys.group.drawing"
1622
+ }, j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent) ? "⌘" : "Ctrl", M = [
1476
1623
  {
1477
1624
  title: "Search & navigation",
1478
1625
  entries: [
@@ -1493,6 +1640,18 @@ var j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platfor
1493
1640
  {
1494
1641
  title: "Chart manipulation",
1495
1642
  entries: [
1643
+ {
1644
+ keys: ["Drag"],
1645
+ label: "Pan — past the last bar into empty future space"
1646
+ },
1647
+ {
1648
+ keys: [j, "Drag"],
1649
+ label: "Select drawings in a box"
1650
+ },
1651
+ {
1652
+ keys: [j, "Click"],
1653
+ label: "Add / remove a drawing from the selection"
1654
+ },
1496
1655
  {
1497
1656
  keys: ["Shift", "Drag"],
1498
1657
  label: "Measure tool (bars × price Δ)"
@@ -1590,9 +1749,10 @@ var j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platfor
1590
1749
  backdrop = null;
1591
1750
  modal = null;
1592
1751
  callbacks;
1752
+ t;
1593
1753
  boundKeydown;
1594
- constructor(e) {
1595
- this.callbacks = e, this.boundKeydown = (e) => {
1754
+ constructor(e, t) {
1755
+ this.callbacks = e, this.t = t, this.boundKeydown = (e) => {
1596
1756
  e.key === "Escape" && (e.preventDefault(), this.close());
1597
1757
  };
1598
1758
  }
@@ -1600,9 +1760,9 @@ var j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platfor
1600
1760
  if (this.backdrop) return;
1601
1761
  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";
1602
1762
  let e = document.createElement("div");
1603
- e.className = "tcw-modal-header", e.innerHTML = "<h3>Keyboard shortcuts</h3>";
1763
+ e.className = "tcw-modal-header", e.innerHTML = `<h3>${this.t("hotkeys.title")}</h3>`;
1604
1764
  let t = document.createElement("button");
1605
- t.className = "tcw-modal-close", t.setAttribute("aria-label", "Close"), t.innerHTML = "×", t.addEventListener("click", () => this.close()), e.appendChild(t), this.modal.appendChild(e);
1765
+ t.className = "tcw-modal-close", t.setAttribute("aria-label", this.t("hotkeys.close")), t.innerHTML = "×", t.addEventListener("click", () => this.close()), e.appendChild(t), this.modal.appendChild(e);
1606
1766
  let n = document.createElement("div");
1607
1767
  n.className = "tcw-modal-body";
1608
1768
  let r = document.createElement("div");
@@ -1611,7 +1771,9 @@ var j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platfor
1611
1771
  let t = document.createElement("section");
1612
1772
  t.className = "tcw-hotkey-section";
1613
1773
  let n = document.createElement("div");
1614
- n.className = "tcw-settings-section-title", n.textContent = e.title, t.appendChild(n);
1774
+ n.className = "tcw-settings-section-title";
1775
+ let i = A[e.title];
1776
+ n.textContent = i ? this.t(i) : e.title, t.appendChild(n);
1615
1777
  for (let n of e.entries) {
1616
1778
  let e = document.createElement("div");
1617
1779
  e.className = "tcw-hotkey-row";
@@ -1635,7 +1797,7 @@ var j = typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.platfor
1635
1797
  let i = document.createElement("div");
1636
1798
  i.className = "tcw-modal-footer", i.innerHTML = "<span style=\"font-size:11px;color:var(--tcw-text-muted)\">Press ? anytime to show this sheet</span>";
1637
1799
  let a = document.createElement("button");
1638
- 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);
1800
+ a.className = "tcw-done-btn", a.textContent = this.t("hotkeys.gotIt"), 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);
1639
1801
  }
1640
1802
  close() {
1641
1803
  document.removeEventListener("keydown", this.boundKeydown), this.backdrop?.remove(), this.modal?.remove(), this.backdrop = null, this.modal = null, this.callbacks.onClose();
@@ -1736,13 +1898,18 @@ var V = class {
1736
1898
  entries = /* @__PURE__ */ new Map();
1737
1899
  active = null;
1738
1900
  callbacks;
1739
- constructor(e, t, n) {
1901
+ locale;
1902
+ constructor(e, t, n, r = "Watchlist") {
1740
1903
  this.callbacks = n, this.el = document.createElement("div"), this.el.className = "tcw-watchlist";
1741
- let r = document.createElement("div");
1742
- 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);
1904
+ let i = document.createElement("div");
1905
+ i.className = "tcw-watchlist-header", i.textContent = r, this.el.appendChild(i), this.listEl = document.createElement("div"), this.listEl.className = "tcw-watchlist-list", this.el.appendChild(this.listEl);
1743
1906
  for (let e of t) this.entries.set(e, { symbol: e }), this.appendRow(e);
1744
1907
  e.appendChild(this.el);
1745
1908
  }
1909
+ setLocale(e) {
1910
+ this.locale = e;
1911
+ for (let e of this.entries.keys()) this.renderRow(e);
1912
+ }
1746
1913
  setSymbols(e) {
1747
1914
  let t = new Set(e);
1748
1915
  for (let e of this.rowMap.keys()) t.has(e) || this.removeRow(e);
@@ -1792,9 +1959,12 @@ var V = class {
1792
1959
  renderRow(e) {
1793
1960
  let t = this.rowMap.get(e), n = this.entries.get(e);
1794
1961
  if (!(!t || !n)) {
1795
- if (n.lastPrice !== void 0 && (t.priceEl.textContent = U(n.lastPrice)), n.lastPrice !== void 0 && n.refPrice !== void 0 && n.refPrice !== 0) {
1796
- let e = n.lastPrice - n.refPrice, r = e / n.refPrice * 100, i = e >= 0 ? "+" : "";
1797
- t.changeEl.textContent = `${i}${r.toFixed(2)}%`, t.changeEl.className = `tcw-watchlist-change ${e >= 0 ? "tcw-up" : "tcw-down"}`;
1962
+ if (n.lastPrice !== void 0 && (t.priceEl.textContent = U(n.lastPrice, this.locale)), n.lastPrice !== void 0 && n.refPrice !== void 0 && n.refPrice !== 0) {
1963
+ let e = n.lastPrice - n.refPrice, r = e / n.refPrice * 100, i = e >= 0 ? "+" : "-", a = Math.abs(r).toLocaleString(this.locale, {
1964
+ minimumFractionDigits: 2,
1965
+ maximumFractionDigits: 2
1966
+ });
1967
+ t.changeEl.textContent = `${i}${a}%`, t.changeEl.className = `tcw-watchlist-change ${e >= 0 ? "tcw-up" : "tcw-down"}`;
1798
1968
  } else t.changeEl.textContent = "";
1799
1969
  n.sparkline && n.sparkline.length >= 2 && W(t.sparkCanvas, n.sparkline, n.refPrice ?? n.sparkline[0]);
1800
1970
  }
@@ -1810,10 +1980,16 @@ function H(e) {
1810
1980
  ]) if (e.length > t.length && e.endsWith(t)) return e.slice(0, -t.length) + "/" + t;
1811
1981
  return e;
1812
1982
  }
1813
- function U(e) {
1983
+ function U(e, t) {
1814
1984
  if (e === 0) return "0";
1815
- let t = Math.abs(e);
1816
- return t >= 1e3 ? e.toFixed(2) : t >= 1 ? e.toFixed(4) : e.toPrecision(4);
1985
+ let n = Math.abs(e);
1986
+ return n >= 1e3 ? e.toLocaleString(t, {
1987
+ minimumFractionDigits: 2,
1988
+ maximumFractionDigits: 2
1989
+ }) : n >= 1 ? e.toLocaleString(t, {
1990
+ minimumFractionDigits: 4,
1991
+ maximumFractionDigits: 4
1992
+ }) : Number(e.toPrecision(4)).toLocaleString(t, { maximumFractionDigits: 10 });
1817
1993
  }
1818
1994
  function W(e, t, n) {
1819
1995
  let r = e.getContext("2d");
@@ -1822,7 +1998,7 @@ function W(e, t, n) {
1822
1998
  e.width !== e.clientWidth * i && (e.width = (e.clientWidth || 64) * i, e.height = (e.clientHeight || 22) * i);
1823
1999
  let a = e.width, o = e.height, s = Infinity, c = -Infinity;
1824
2000
  for (let e of t) e < s && (s = e), e > c && (c = e);
1825
- let l = Math.max(c - s, 1e-9), u = t[t.length - 1] >= n ? "#26a17b" : "#f23645";
2001
+ let l = Math.max(c - s, 1e-9), u = t[t.length - 1] >= n ? "#1fa874" : "#e8505b";
1826
2002
  r.clearRect(0, 0, a, o), r.lineWidth = 1.4 * i, r.strokeStyle = u, r.beginPath();
1827
2003
  let d = a / (t.length - 1);
1828
2004
  for (let e = 0; e < t.length; e++) {
@@ -1855,14 +2031,14 @@ var G = [
1855
2031
  label: "Less than"
1856
2032
  }
1857
2033
  ], K = new Map(G.map((e) => [e.value, e.label]));
1858
- function q(e) {
2034
+ function ce(e) {
1859
2035
  return Math.round(e * 1e6) / 1e6;
1860
2036
  }
1861
- function se(e) {
2037
+ function le(e) {
1862
2038
  let t = Math.abs(e);
1863
2039
  return t >= 1e3 || t >= 1 ? e.toFixed(2) : e.toPrecision(4);
1864
2040
  }
1865
- var ce = class {
2041
+ var ue = class {
1866
2042
  el;
1867
2043
  listEl;
1868
2044
  priceInput;
@@ -1923,7 +2099,7 @@ var ce = class {
1923
2099
  }
1924
2100
  prefillPrice() {
1925
2101
  let e = this.callbacks.getChannelValue(this.sourceSelect.value || "price");
1926
- this.priceInput.value = e === null ? "" : String(q(e));
2102
+ this.priceInput.value = e === null ? "" : String(ce(e));
1927
2103
  }
1928
2104
  close() {
1929
2105
  this.open = !1, this.el.hidden = !0;
@@ -1952,7 +2128,7 @@ var ce = class {
1952
2128
  n.className = "tcw-alerts-info";
1953
2129
  let r = document.createElement("div");
1954
2130
  r.className = "tcw-alerts-row-main";
1955
- let i = K.get(e.condition) ?? e.condition, a = e.channel && e.channel !== "price", o = a ? se(e.price) : this.callbacks.formatPrice(e.price);
2131
+ let i = K.get(e.condition) ?? e.condition, a = e.channel && e.channel !== "price", o = a ? le(e.price) : this.callbacks.formatPrice(e.price);
1956
2132
  if (r.textContent = `${a && e.label ? `${e.label} ` : ""}${i} ${o}`, n.appendChild(r), e.message) {
1957
2133
  let t = document.createElement("div");
1958
2134
  t.className = "tcw-alerts-row-note", t.textContent = e.message, n.appendChild(t);
@@ -1965,7 +2141,7 @@ var ce = class {
1965
2141
  s.type = "button", s.className = "tcw-alerts-del", s.setAttribute("aria-label", "Delete alert"), s.innerHTML = y("trash", 14), s.addEventListener("click", () => this.callbacks.onRemove(e.id)), t.appendChild(n), t.appendChild(s), this.listEl.appendChild(t);
1966
2142
  }
1967
2143
  }
1968
- }, le = class {
2144
+ }, de = class {
1969
2145
  el;
1970
2146
  indicatorsEl;
1971
2147
  drawingsEl;
@@ -2062,11 +2238,26 @@ var ce = class {
2062
2238
  let i = document.createElement("button");
2063
2239
  return i.type = "button", i.className = `tcw-tree-btn ${n}`.trim(), i.setAttribute("aria-label", t), i.title = t, i.innerHTML = y(e, 14), i.addEventListener("click", r), i;
2064
2240
  }
2065
- }, ue = {
2241
+ }, fe = {
2066
2242
  trendLine: "Trend Line",
2067
2243
  ray: "Ray",
2068
2244
  extendedLine: "Extended Line",
2069
2245
  horizontalLine: "Horizontal Line",
2246
+ horizontalRay: "Horizontal Ray",
2247
+ crossLine: "Cross Line",
2248
+ infoLine: "Info Line",
2249
+ trendAngle: "Trend Angle",
2250
+ circle: "Circle",
2251
+ fibChannel: "Fib Channel",
2252
+ fibSpeedResistanceFan: "Fib Speed Resistance Fan",
2253
+ schiffPitchfork: "Schiff Pitchfork",
2254
+ modifiedSchiffPitchfork: "Modified Schiff Pitchfork",
2255
+ xabcdPattern: "XABCD Pattern",
2256
+ abcdPattern: "ABCD Pattern",
2257
+ headAndShoulders: "Head and Shoulders",
2258
+ dateAndPriceRange: "Date and Price Range",
2259
+ cyclicLines: "Cyclic Lines",
2260
+ priceLabel: "Price Label",
2070
2261
  verticalLine: "Vertical Line",
2071
2262
  rectangle: "Rectangle",
2072
2263
  ellipse: "Ellipse",
@@ -2084,20 +2275,22 @@ var ce = class {
2084
2275
  priceRange: "Price Range",
2085
2276
  dateRange: "Date Range",
2086
2277
  measure: "Measure",
2278
+ text: "Text",
2087
2279
  textAnnotation: "Text",
2088
2280
  anchoredVWAP: "Anchored VWAP",
2089
- volumeProfileRange: "Volume Profile"
2281
+ volumeProfileRange: "Volume Profile",
2282
+ riskReward: "Long/Short Position"
2090
2283
  };
2091
- function de(e) {
2092
- return ue[e] ?? e;
2284
+ function pe(e) {
2285
+ return fe[e] ?? e;
2093
2286
  }
2094
2287
  //#endregion
2095
2288
  //#region src/widget/WidgetIndicatorSettings.ts
2096
- var fe = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
2097
- function pe(e) {
2289
+ var me = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
2290
+ function he(e) {
2098
2291
  return e.replace(/_/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^./, (e) => e.toUpperCase());
2099
2292
  }
2100
- var me = class {
2293
+ var ge = class {
2101
2294
  backdrop;
2102
2295
  modal;
2103
2296
  bodyEl;
@@ -2162,9 +2355,9 @@ var me = class {
2162
2355
  let t = document.createElement("div");
2163
2356
  t.className = "tcw-settings-row";
2164
2357
  let n = document.createElement("span");
2165
- n.className = "tcw-settings-label", n.textContent = pe(e), t.appendChild(n);
2358
+ n.className = "tcw-settings-label", n.textContent = he(e), t.appendChild(n);
2166
2359
  let r = this.currentValue(e), i = typeof (this.target?.defaults[e] ?? r);
2167
- return i === "boolean" ? t.appendChild(this.toggleControl(e, !!r)) : i === "number" ? t.appendChild(this.numberControl(e, Number(r))) : typeof r == "string" && fe.test(r) ? t.appendChild(this.colorControl(e, r)) : t.appendChild(this.textControl(e, String(r ?? ""))), t;
2360
+ return i === "boolean" ? t.appendChild(this.toggleControl(e, !!r)) : i === "number" ? t.appendChild(this.numberControl(e, Number(r))) : typeof r == "string" && me.test(r) ? t.appendChild(this.colorControl(e, r)) : t.appendChild(this.textControl(e, String(r ?? ""))), t;
2168
2361
  }
2169
2362
  toggleControl(e, t) {
2170
2363
  let n = document.createElement("button");
@@ -2182,27 +2375,27 @@ var me = class {
2182
2375
  }
2183
2376
  colorControl(e, t) {
2184
2377
  let n = document.createElement("input");
2185
- return n.type = "color", n.className = "tcw-indi-color", n.value = t.length === 4 ? he(t) : t, n.addEventListener("input", () => this.setValue(e, n.value)), n;
2378
+ return n.type = "color", n.className = "tcw-indi-color", n.value = t.length === 4 ? _e(t) : t, n.addEventListener("input", () => this.setValue(e, n.value)), n;
2186
2379
  }
2187
2380
  textControl(e, t) {
2188
2381
  let n = document.createElement("input");
2189
2382
  return n.type = "text", n.className = "tcw-indi-input", n.value = t, n.addEventListener("change", () => this.setValue(e, n.value)), n;
2190
2383
  }
2191
2384
  };
2192
- function he(e) {
2385
+ function _e(e) {
2193
2386
  let t = e[1], n = e[2], r = e[3];
2194
2387
  return `#${t}${t}${n}${n}${r}${r}`;
2195
2388
  }
2196
2389
  //#endregion
2197
2390
  //#region src/widget/DrawingTemplateStore.ts
2198
- function ge() {
2391
+ function ve() {
2199
2392
  try {
2200
2393
  return typeof localStorage < "u" ? localStorage : null;
2201
2394
  } catch {
2202
2395
  return null;
2203
2396
  }
2204
2397
  }
2205
- var _e = [
2398
+ var ye = [
2206
2399
  "color",
2207
2400
  "lineWidth",
2208
2401
  "lineStyle",
@@ -2210,15 +2403,15 @@ var _e = [
2210
2403
  "fillOpacity",
2211
2404
  "fontSize"
2212
2405
  ];
2213
- function J(e) {
2406
+ function q(e) {
2214
2407
  if (!e || typeof e != "object") return {};
2215
2408
  let t = {}, n = e;
2216
- for (let e of _e) n[e] !== void 0 && (t[e] = n[e]);
2409
+ for (let e of ye) n[e] !== void 0 && (t[e] = n[e]);
2217
2410
  return t;
2218
2411
  }
2219
- var ve = class {
2412
+ var be = class {
2220
2413
  templates = [];
2221
- constructor(e = "tcw:draw-templates", t = ge()) {
2414
+ constructor(e = "tcw:draw-templates", t = ve()) {
2222
2415
  this.storageKey = e, this.storage = t, this.load();
2223
2416
  }
2224
2417
  list() {
@@ -2237,7 +2430,7 @@ var ve = class {
2237
2430
  save(e, t) {
2238
2431
  let n = e.trim();
2239
2432
  if (!n) return;
2240
- let r = J(t);
2433
+ let r = q(t);
2241
2434
  this.templates = this.templates.filter((e) => e.name !== n), this.templates.push({
2242
2435
  name: n,
2243
2436
  style: r
@@ -2258,7 +2451,7 @@ var ve = class {
2258
2451
  if (!Array.isArray(t)) return;
2259
2452
  this.templates = t.filter((e) => e && typeof e.name == "string").map((e) => ({
2260
2453
  name: e.name,
2261
- style: J(e.style)
2454
+ style: q(e.style)
2262
2455
  }));
2263
2456
  } catch {}
2264
2457
  }
@@ -2267,25 +2460,25 @@ var ve = class {
2267
2460
  this.storage.setItem(this.storageKey, JSON.stringify(this.templates));
2268
2461
  } catch {}
2269
2462
  }
2270
- }, ye = [
2271
- "#2962ff",
2272
- "#089981",
2273
- "#f23645",
2274
- "#ff9800",
2275
- "#ab47bc",
2276
- "#26c6da",
2463
+ }, xe = [
2464
+ "#4c8dff",
2465
+ "#1fa874",
2466
+ "#e8505b",
2467
+ "#f2a93b",
2468
+ "#a57cff",
2469
+ "#1398a8",
2277
2470
  "#ffffff",
2278
- "#787b86"
2279
- ], be = [
2471
+ "#7d8696"
2472
+ ], Se = [
2280
2473
  1,
2281
2474
  2,
2282
2475
  3,
2283
2476
  4
2284
- ], xe = [
2477
+ ], Ce = [
2285
2478
  "solid",
2286
2479
  "dashed",
2287
2480
  "dotted"
2288
- ], Se = class {
2481
+ ], we = class {
2289
2482
  el;
2290
2483
  templatesEl;
2291
2484
  nameInput;
@@ -2325,7 +2518,7 @@ var ve = class {
2325
2518
  colorRow() {
2326
2519
  let e = document.createElement("div");
2327
2520
  e.className = "tcw-style-row tcw-style-colors";
2328
- for (let t of ye) {
2521
+ for (let t of xe) {
2329
2522
  let n = document.createElement("button");
2330
2523
  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);
2331
2524
  }
@@ -2335,7 +2528,7 @@ var ve = class {
2335
2528
  widthRow() {
2336
2529
  let e = document.createElement("div");
2337
2530
  e.className = "tcw-style-row tcw-style-widths";
2338
- for (let t of be) {
2531
+ for (let t of Se) {
2339
2532
  let n = document.createElement("button");
2340
2533
  n.type = "button", n.className = "tcw-style-width", n.dataset.width = String(t);
2341
2534
  let r = document.createElement("span");
@@ -2346,7 +2539,7 @@ var ve = class {
2346
2539
  lineStyleRow() {
2347
2540
  let e = document.createElement("div");
2348
2541
  e.className = "tcw-style-row tcw-style-dashes";
2349
- for (let t of xe) {
2542
+ for (let t of Ce) {
2350
2543
  let n = document.createElement("button");
2351
2544
  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);
2352
2545
  }
@@ -2397,16 +2590,16 @@ var ve = class {
2397
2590
  };
2398
2591
  //#endregion
2399
2592
  //#region src/widget/DrawingFavoritesStore.ts
2400
- function Ce() {
2593
+ function Te() {
2401
2594
  try {
2402
2595
  return typeof localStorage < "u" ? localStorage : null;
2403
2596
  } catch {
2404
2597
  return null;
2405
2598
  }
2406
2599
  }
2407
- var we = class {
2600
+ var Ee = class {
2408
2601
  favorites = [];
2409
- constructor(e = "tcw:draw-favorites", t = Ce()) {
2602
+ constructor(e = "tcw:draw-favorites", t = Te()) {
2410
2603
  this.storageKey = e, this.storage = t, this.load();
2411
2604
  }
2412
2605
  list() {
@@ -2440,7 +2633,7 @@ var we = class {
2440
2633
  this.storage.setItem(this.storageKey, JSON.stringify(this.favorites));
2441
2634
  } catch {}
2442
2635
  }
2443
- }, Te = class {
2636
+ }, De = class {
2444
2637
  el;
2445
2638
  labelEl;
2446
2639
  callbacks;
@@ -2466,7 +2659,7 @@ var we = class {
2466
2659
  destroy() {
2467
2660
  this.el.remove();
2468
2661
  }
2469
- }, Ee = class {
2662
+ }, Oe = class {
2470
2663
  options;
2471
2664
  audioCtx = null;
2472
2665
  audioEl = null;
@@ -2529,7 +2722,7 @@ var we = class {
2529
2722
  };
2530
2723
  //#endregion
2531
2724
  //#region src/widget/ladderRows.ts
2532
- function De(e, t = 12) {
2725
+ function ke(e, t = 12) {
2533
2726
  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 = /* @__PURE__ */ new Map(), c = (e) => {
2534
2727
  let t = s.get(e);
2535
2728
  return t || (t = {
@@ -2550,7 +2743,7 @@ function De(e, t = 12) {
2550
2743
  }
2551
2744
  //#endregion
2552
2745
  //#region src/widget/WidgetDepthLadder.ts
2553
- var Oe = class {
2746
+ var Ae = class {
2554
2747
  el;
2555
2748
  bodyEl;
2556
2749
  callbacks;
@@ -2584,7 +2777,7 @@ var Oe = class {
2584
2777
  this.renderEmpty();
2585
2778
  return;
2586
2779
  }
2587
- this.render(De(e, this.levels));
2780
+ this.render(ke(e, this.levels));
2588
2781
  }
2589
2782
  destroy() {
2590
2783
  this.el.remove();
@@ -2604,20 +2797,20 @@ var Oe = class {
2604
2797
  let e = n.askVolume > 0, r = document.createElement("div");
2605
2798
  r.className = "tcw-ladder-row";
2606
2799
  let i = document.createElement("button");
2607
- 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;
2800
+ i.type = "button", i.className = "tcw-ladder-cell tcw-ladder-bid", n.bidVolume > 0 ? (i.textContent = J(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;
2608
2801
  let a = document.createElement("div");
2609
2802
  a.className = `tcw-ladder-price ${e ? "tcw-ask" : "tcw-bid"}`, a.textContent = this.callbacks.formatPrice(n.price);
2610
2803
  let o = document.createElement("button");
2611
- 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);
2804
+ o.type = "button", o.className = "tcw-ladder-cell tcw-ladder-ask", n.askVolume > 0 ? (o.textContent = J(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);
2612
2805
  }
2613
2806
  }
2614
2807
  };
2615
- function Y(e) {
2808
+ function J(e) {
2616
2809
  return e >= 1e3 ? (e / 1e3).toFixed(1) + "k" : e >= 1 ? e.toFixed(2).replace(/\.00$/, "") : e.toPrecision(2);
2617
2810
  }
2618
2811
  //#endregion
2619
2812
  //#region src/widget/WidgetDataWindow.ts
2620
- var ke = class {
2813
+ var je = class {
2621
2814
  el;
2622
2815
  bodyEl;
2623
2816
  callbacks;
@@ -2656,11 +2849,11 @@ var ke = class {
2656
2849
  let t = this.callbacks.formatPrice, n = e.ohlc;
2657
2850
  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)));
2658
2851
  let r = e.change > 0 ? "up" : e.change < 0 ? "down" : "", i = e.change > 0 ? "+" : "";
2659
- this.bodyEl.appendChild(this.row("Change", `${i}${t(e.change)} (${i}${e.changePct.toFixed(2)}%)`, r)), this.bodyEl.appendChild(this.row("Volume", X(n.volume)));
2852
+ this.bodyEl.appendChild(this.row("Change", `${i}${t(e.change)} (${i}${e.changePct.toFixed(2)}%)`, r)), this.bodyEl.appendChild(this.row("Volume", Ne(n.volume)));
2660
2853
  for (let t of e.indicators) {
2661
2854
  let e = document.createElement("div");
2662
2855
  e.className = "tcw-datawin-sub", e.textContent = t.name, this.bodyEl.appendChild(e);
2663
- for (let e of t.values) this.bodyEl.appendChild(this.row(e.key, Ae(e.value)));
2856
+ for (let e of t.values) this.bodyEl.appendChild(this.row(e.key, Me(e.value)));
2664
2857
  }
2665
2858
  }
2666
2859
  row(e, t, n = "") {
@@ -2672,43 +2865,43 @@ var ke = class {
2672
2865
  return a.className = `tcw-datawin-value${n ? ` tcw-${n}` : ""}`, a.textContent = t, r.appendChild(i), r.appendChild(a), r;
2673
2866
  }
2674
2867
  };
2675
- function Ae(e) {
2868
+ function Me(e) {
2676
2869
  if (!Number.isFinite(e)) return "—";
2677
2870
  let t = Math.abs(e);
2678
2871
  return t >= 1e3 ? e.toFixed(2) : t >= 1 ? e.toFixed(4) : e.toPrecision(4);
2679
2872
  }
2680
- function X(e) {
2873
+ function Ne(e) {
2681
2874
  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);
2682
2875
  }
2683
2876
  //#endregion
2684
2877
  //#region src/widget/widgetShareState.ts
2685
- var Z = globalThis.Buffer;
2686
- function je(e) {
2687
- if (Z) return Z.from(e, "utf8").toString("base64");
2878
+ var Y = globalThis.Buffer;
2879
+ function Pe(e) {
2880
+ if (Y) return Y.from(e, "utf8").toString("base64");
2688
2881
  let t = new TextEncoder().encode(e), n = "";
2689
2882
  for (let e of t) n += String.fromCharCode(e);
2690
2883
  return btoa(n);
2691
2884
  }
2692
- function Me(e) {
2693
- if (Z) return Z.from(e, "base64").toString("utf8");
2885
+ function Fe(e) {
2886
+ if (Y) return Y.from(e, "base64").toString("utf8");
2694
2887
  let t = atob(e), n = new Uint8Array(t.length);
2695
2888
  for (let e = 0; e < t.length; e++) n[e] = t.charCodeAt(e);
2696
2889
  return new TextDecoder().decode(n);
2697
2890
  }
2698
- function Ne(e) {
2891
+ function Ie(e) {
2699
2892
  return e.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
2700
2893
  }
2701
- function Pe(e) {
2894
+ function Le(e) {
2702
2895
  let t = e.replace(/-/g, "+").replace(/_/g, "/");
2703
2896
  return t + (t.length % 4 == 0 ? "" : "=".repeat(4 - t.length % 4));
2704
2897
  }
2705
- function Fe(e) {
2706
- return Ne(je(JSON.stringify(e)));
2898
+ function Re(e) {
2899
+ return Ie(Pe(JSON.stringify(e)));
2707
2900
  }
2708
- function Ie(e) {
2901
+ function ze(e) {
2709
2902
  if (!e) return null;
2710
2903
  try {
2711
- let t = Me(Pe(e)), n = JSON.parse(t);
2904
+ let t = Fe(Le(e)), n = JSON.parse(t);
2712
2905
  return !n || n.v !== 1 || typeof n.symbol != "string" ? null : {
2713
2906
  v: 1,
2714
2907
  symbol: n.symbol,
@@ -2722,29 +2915,253 @@ function Ie(e) {
2722
2915
  return null;
2723
2916
  }
2724
2917
  }
2725
- var Q = "tcw";
2726
- function Le(e) {
2918
+ var X = "tcw";
2919
+ function Be(e) {
2727
2920
  let t = e.startsWith("#") ? e.slice(1) : e;
2728
2921
  for (let e of t.split("&")) {
2729
2922
  let t = e.indexOf("=");
2730
- if (t > 0 && e.slice(0, t) === Q) return decodeURIComponent(e.slice(t + 1));
2923
+ if (t > 0 && e.slice(0, t) === X) return decodeURIComponent(e.slice(t + 1));
2731
2924
  }
2732
2925
  return null;
2733
2926
  }
2734
- function Re(e, t) {
2927
+ function Ve(e, t) {
2735
2928
  let [n] = e.split("#");
2736
- return `${n}#${Q}=${t}`;
2929
+ return `${n}#${X}=${t}`;
2737
2930
  }
2738
2931
  //#endregion
2739
- //#region src/widget/ChartWidget.ts
2932
+ //#region src/widget/i18n.ts
2933
+ var Z = {
2934
+ "toolbar.indicators": "Indicators",
2935
+ "toolbar.indicators.popular": "Popular",
2936
+ "toolbar.indicators.all": "All",
2937
+ "indicatorType.overlay": "overlay",
2938
+ "indicatorType.panel": "panel",
2939
+ "toolbar.replay": "Bar replay",
2940
+ "toolbar.longBracket": "Long bracket",
2941
+ "toolbar.shortBracket": "Short bracket",
2942
+ "toolbar.depthLadder": "Depth ladder",
2943
+ "toolbar.objects": "Objects",
2944
+ "toolbar.priceAlerts": "Price alerts",
2945
+ "toolbar.screenshot": "Screenshot",
2946
+ "toolbar.settings": "Chart Settings",
2947
+ "toolbar.toggleTheme": "Toggle theme",
2948
+ "chartType.candlestick": "Candlestick",
2949
+ "chartType.line": "Line",
2950
+ "chartType.area": "Area",
2951
+ "chartType.bar": "Bar",
2952
+ "chartType.heikinAshi": "Heikin-Ashi",
2953
+ "chartType.hollowCandle": "Hollow Candle",
2954
+ "chartType.baseline": "Baseline",
2955
+ "chartType.volumeCandles": "Volume Candles",
2956
+ "chartType.equivolume": "Equivolume",
2957
+ "chartType.hlcArea": "HLC Area",
2958
+ "chartType.stepLine": "Step Line",
2959
+ "chartType.lineWithMarkers": "Line + Markers",
2960
+ "watchlist.title": "Watchlist",
2961
+ "status.connecting": "Connecting...",
2962
+ "status.live": "Live",
2963
+ "status.connectionFailed": "Connection failed",
2964
+ "status.loading": "Loading chart...",
2965
+ "settings.title": "Chart Settings",
2966
+ "settings.tab.style": "style",
2967
+ "settings.tab.display": "display",
2968
+ "settings.tab.scale": "scale",
2969
+ "settings.resetToDefaults": "Reset to defaults",
2970
+ "settings.done": "Done",
2971
+ "settings.section.candleColors": "Candle Colors",
2972
+ "settings.section.background": "Background",
2973
+ "hotkeys.title": "Keyboard shortcuts",
2974
+ "hotkeys.close": "Close",
2975
+ "hotkeys.gotIt": "Got it",
2976
+ "hotkeys.group.searchNavigation": "Search & navigation",
2977
+ "hotkeys.group.chartManipulation": "Chart manipulation",
2978
+ "hotkeys.group.touch": "Touch (mobile / tablet)",
2979
+ "hotkeys.group.keyboard": "Keyboard",
2980
+ "hotkeys.group.drawing": "Drawing"
2981
+ }, He = {
2982
+ en: Z,
2983
+ vi: {
2984
+ "toolbar.indicators": "Chỉ báo",
2985
+ "toolbar.indicators.popular": "Phổ biến",
2986
+ "toolbar.indicators.all": "Tất cả",
2987
+ "indicatorType.overlay": "phủ lên",
2988
+ "indicatorType.panel": "bảng riêng",
2989
+ "toolbar.replay": "Phát lại",
2990
+ "toolbar.longBracket": "Lệnh Long",
2991
+ "toolbar.shortBracket": "Lệnh Short",
2992
+ "toolbar.depthLadder": "Sổ lệnh",
2993
+ "toolbar.objects": "Đối tượng",
2994
+ "toolbar.priceAlerts": "Cảnh báo giá",
2995
+ "toolbar.screenshot": "Chụp màn hình",
2996
+ "toolbar.settings": "Cài đặt biểu đồ",
2997
+ "toolbar.toggleTheme": "Đổi giao diện",
2998
+ "chartType.candlestick": "Nến",
2999
+ "chartType.line": "Đường",
3000
+ "chartType.area": "Vùng",
3001
+ "chartType.bar": "Thanh",
3002
+ "chartType.heikinAshi": "Heikin-Ashi",
3003
+ "chartType.hollowCandle": "Nến rỗng",
3004
+ "chartType.baseline": "Đường cơ sở",
3005
+ "chartType.volumeCandles": "Nến khối lượng",
3006
+ "chartType.equivolume": "Equivolume",
3007
+ "chartType.hlcArea": "Vùng HLC",
3008
+ "chartType.stepLine": "Đường bậc thang",
3009
+ "chartType.lineWithMarkers": "Đường + điểm đánh dấu",
3010
+ "watchlist.title": "Danh mục theo dõi",
3011
+ "status.connecting": "Đang kết nối...",
3012
+ "status.live": "Trực tiếp",
3013
+ "status.connectionFailed": "Kết nối thất bại",
3014
+ "status.loading": "Đang tải biểu đồ...",
3015
+ "settings.title": "Cài đặt biểu đồ",
3016
+ "settings.tab.style": "Giao diện",
3017
+ "settings.tab.display": "Hiển thị",
3018
+ "settings.tab.scale": "Thang giá",
3019
+ "settings.resetToDefaults": "Khôi phục mặc định",
3020
+ "settings.done": "Xong",
3021
+ "settings.section.candleColors": "Màu nến",
3022
+ "settings.section.background": "Nền",
3023
+ "hotkeys.title": "Phím tắt",
3024
+ "hotkeys.close": "Đóng",
3025
+ "hotkeys.gotIt": "Đã hiểu",
3026
+ "hotkeys.group.searchNavigation": "Tìm kiếm & điều hướng",
3027
+ "hotkeys.group.chartManipulation": "Thao tác biểu đồ",
3028
+ "hotkeys.group.touch": "Cảm ứng (di động / máy tính bảng)",
3029
+ "hotkeys.group.keyboard": "Bàn phím",
3030
+ "hotkeys.group.drawing": "Vẽ"
3031
+ }
3032
+ };
3033
+ function Q(e, t) {
3034
+ let n = { ...Z }, r = e ? He[e] : void 0;
3035
+ return r && Object.assign(n, r), t && Object.assign(n, t), n;
3036
+ }
3037
+ function Ue(e) {
3038
+ return (t) => e[t] ?? Z[t] ?? t;
3039
+ }
3040
+ var We = [
3041
+ [
3042
+ 34,
3043
+ 16,
3044
+ 28,
3045
+ 26,
3046
+ !1
3047
+ ],
3048
+ [
3049
+ 30,
3050
+ 14,
3051
+ 24,
3052
+ 26,
3053
+ !0
3054
+ ],
3055
+ [
3056
+ 26,
3057
+ 18,
3058
+ 20,
3059
+ 30,
3060
+ !0
3061
+ ],
3062
+ [
3063
+ 30,
3064
+ 10,
3065
+ 24,
3066
+ 22,
3067
+ !1
3068
+ ],
3069
+ [
3070
+ 20,
3071
+ 16,
3072
+ 14,
3073
+ 28,
3074
+ !0
3075
+ ],
3076
+ [
3077
+ 14,
3078
+ 18,
3079
+ 8,
3080
+ 30,
3081
+ !0
3082
+ ],
3083
+ [
3084
+ 18,
3085
+ 10,
3086
+ 12,
3087
+ 20,
3088
+ !1
3089
+ ],
3090
+ [
3091
+ 8,
3092
+ 18,
3093
+ 2,
3094
+ 30,
3095
+ !0
3096
+ ]
3097
+ ], Ge = class {
3098
+ el;
3099
+ label;
3100
+ showTimer = null;
3101
+ phase = "loading";
3102
+ constructor(e, t) {
3103
+ this.loadingText = t, this.el = document.createElement("div"), this.el.className = "tcw-loading-overlay", this.el.setAttribute("role", "status"), this.el.setAttribute("aria-live", "polite");
3104
+ let n = document.createElement("div");
3105
+ n.className = "tcw-loading-card";
3106
+ let r = document.createElement("div");
3107
+ r.className = "tcw-loading-candles", r.setAttribute("aria-hidden", "true"), We.forEach(([e, t, n, i, a], o) => {
3108
+ let s = document.createElement("span");
3109
+ s.className = a ? "tcw-loading-candle tcw-loading-candle--up" : "tcw-loading-candle", s.style.setProperty("--tcw-body-top", `${e}px`), s.style.setProperty("--tcw-body-h", `${t}px`), s.style.setProperty("--tcw-wick-top", `${n}px`), s.style.setProperty("--tcw-wick-h", `${i}px`), s.style.animationDelay = `${o * 110}ms`, r.appendChild(s);
3110
+ }), n.appendChild(r);
3111
+ let i = document.createElement("div");
3112
+ i.className = "tcw-loading-track", i.setAttribute("aria-hidden", "true"), i.appendChild(document.createElement("span")), n.appendChild(i), this.label = document.createElement("div"), this.label.className = "tcw-loading-label", this.label.textContent = t, n.appendChild(this.label), this.el.appendChild(n), e.appendChild(this.el);
3113
+ }
3114
+ begin(e, t = !1) {
3115
+ if (this.phase = "loading", this.clearTimer(), this.label.textContent = this.loadingText, this.el.classList.remove("tcw-loading-overlay--error"), this.el.classList.toggle("tcw-loading-overlay--veil", e), !e || t || this.isShown()) {
3116
+ this.el.classList.remove("tcw-loading-overlay--hidden");
3117
+ return;
3118
+ }
3119
+ this.showTimer = setTimeout(() => {
3120
+ this.showTimer = null, this.el.classList.remove("tcw-loading-overlay--hidden");
3121
+ }, 200);
3122
+ }
3123
+ end() {
3124
+ this.phase = "idle", this.clearTimer(), this.el.classList.add("tcw-loading-overlay--hidden");
3125
+ }
3126
+ fail(e) {
3127
+ this.phase !== "idle" && (this.phase = "failed", this.clearTimer(), this.label.textContent = e, this.el.classList.add("tcw-loading-overlay--error"), this.el.classList.remove("tcw-loading-overlay--hidden"));
3128
+ }
3129
+ isActive() {
3130
+ return this.phase !== "idle";
3131
+ }
3132
+ hasFailed() {
3133
+ return this.phase === "failed";
3134
+ }
3135
+ isShown() {
3136
+ return !this.el.classList.contains("tcw-loading-overlay--hidden");
3137
+ }
3138
+ destroy() {
3139
+ this.clearTimer(), this.el.remove();
3140
+ }
3141
+ clearTimer() {
3142
+ this.showTimer !== null && (clearTimeout(this.showTimer), this.showTimer = null);
3143
+ }
3144
+ }, Ke = 48, qe = 5e4, Je = 100;
3145
+ function Ye() {
3146
+ return new Promise((e) => {
3147
+ if (typeof requestAnimationFrame != "function" || document.hidden) {
3148
+ setTimeout(e, 0);
3149
+ return;
3150
+ }
3151
+ let t = setTimeout(e, Je);
3152
+ requestAnimationFrame(() => setTimeout(() => {
3153
+ clearTimeout(t), e();
3154
+ }, 0));
3155
+ });
3156
+ }
2740
3157
  var $ = [
2741
- "#f7931a",
2742
- "#627eea",
2743
- "#26a17b",
2744
- "#e84142",
2745
- "#8247e5",
2746
- "#f3ba2f"
2747
- ], ze = class {
3158
+ "#4c8dff",
3159
+ "#a57cff",
3160
+ "#1398a8",
3161
+ "#e25592",
3162
+ "#8a93a3",
3163
+ "#62c895"
3164
+ ], Xe = class {
2748
3165
  chart;
2749
3166
  state;
2750
3167
  toolbar = null;
@@ -2765,10 +3182,11 @@ var $ = [
2765
3182
  depthLadder = null;
2766
3183
  dataWindow = null;
2767
3184
  lastHoverIndex = null;
2768
- favoritesStore = new we();
3185
+ favoritesStore = new Ee();
2769
3186
  watchlist = null;
2770
3187
  watchlistSparkBuffer = /* @__PURE__ */ new Map();
2771
3188
  sessionRefPrice = null;
3189
+ hostWatchlistRefPrice = /* @__PURE__ */ new Map();
2772
3190
  watchlistInterval = null;
2773
3191
  replayOriginalData = null;
2774
3192
  replayPollInterval = null;
@@ -2778,17 +3196,25 @@ var $ = [
2778
3196
  activeLayoutKey = null;
2779
3197
  root;
2780
3198
  chartContainer;
3199
+ loading;
3200
+ connectSeq = 0;
3201
+ localSeq = 0;
3202
+ lastLocalSwitchMs = 0;
2781
3203
  destroyed = !1;
2782
3204
  options;
2783
3205
  symbols;
2784
3206
  settingsState;
3207
+ t;
2785
3208
  adapter = null;
2786
3209
  boundGlobalKeydown = null;
2787
3210
  baseSeries = null;
2788
3211
  baseTimeframeMs = 0;
2789
3212
  compares = [];
2790
3213
  constructor(n, r = {}) {
2791
- if (this.options = r, this.symbols = r.symbols ?? ee, this.settingsState = { ...p }, r.persistLayouts) {
3214
+ if (this.options = r, this.symbols = r.symbols ?? ee, this.settingsState = {
3215
+ ...p,
3216
+ ...r.chartOptions?.numberLocale ? { numberLocale: r.chartOptions.numberLocale } : {}
3217
+ }, this.t = Ue(Q(r.locale, r.messages)), r.persistLayouts) {
2792
3218
  let e = r.persistLayouts === !0 ? {} : r.persistLayouts;
2793
3219
  this.layoutKeyPrefix = e.keyPrefix ?? "tcw:layout:", this.layoutDebounceMs = e.debounceMs ?? 1500;
2794
3220
  }
@@ -2801,8 +3227,8 @@ var $ = [
2801
3227
  activeIndicators: /* @__PURE__ */ new Map(),
2802
3228
  activeTool: null,
2803
3229
  magnetEnabled: !0,
2804
- connectionState: "connecting",
2805
- connectionMessage: "Connecting..."
3230
+ connectionState: r.adapter ? "connecting" : "disconnected",
3231
+ connectionMessage: r.adapter ? this.t("status.connecting") : ""
2806
3232
  }, g(), this.root = document.createElement("div"), this.root.className = "tcw-root", this.root.dataset.tcwTheme = i ? "dark" : "light", n.appendChild(this.root), r.toolbar !== !1 && (this.toolbar = new ne(this.root, {
2807
3233
  symbols: this.symbols,
2808
3234
  timeframes: r.timeframes ? c.filter((e) => r.timeframes.includes(e.value)) : c,
@@ -2823,9 +3249,9 @@ var $ = [
2823
3249
  onToggleObjects: r.objectTree === !1 ? void 0 : () => this.toggleObjects(),
2824
3250
  onBracket: r.trading === !1 ? void 0 : (e) => this.startBracket(e),
2825
3251
  onToggleLadder: r.trading !== !1 && r.depthLadder ? () => this.depthLadder?.toggle() : void 0
2826
- }));
3252
+ }, this.t));
2827
3253
  let o = document.createElement("div");
2828
- if (o.className = "tcw-body", r.drawingTools !== !1 && (r.drawingFavorites && this.favoritesStore.seedDefaults(r.drawingFavorites), this.sidebar = new x(o, {
3254
+ if (o.className = "tcw-body", r.drawingTools !== !1 && (r.drawingFavorites && this.favoritesStore.seedDefaults(r.drawingFavorites), this.sidebar = new se(o, {
2829
3255
  drawingToolGroups: u,
2830
3256
  favorites: this.favoritesStore.list()
2831
3257
  }, {
@@ -2842,60 +3268,62 @@ var $ = [
2842
3268
  }, this.updateUI();
2843
3269
  },
2844
3270
  onToggleStyle: () => this.drawingStyle?.toggle()
2845
- })), this.chartContainer = document.createElement("div"), this.chartContainer.className = "tcw-chart-container", o.appendChild(this.chartContainer), r.watchlist && (this.watchlist = new V(o, this.symbols, { onSelect: (e) => {
3271
+ })), this.chartContainer = document.createElement("div"), this.chartContainer.className = "tcw-chart-container", o.appendChild(this.chartContainer), this.loading = new Ge(this.chartContainer, this.t("status.loading")), r.watchlist && (this.watchlist = new V(o, this.symbols, { onSelect: (e) => {
2846
3272
  this.setSymbol(e);
2847
- } }), this.watchlist.setActive(this.state.symbol)), this.root.appendChild(o), this.chart = new e(this.chartContainer, {
3273
+ } }, this.t("watchlist.title")), this.watchlist.setActive(this.state.symbol), this.watchlist.setLocale(this.settingsState.numberLocale || void 0)), this.root.appendChild(o), this.chart = new e(this.chartContainer, {
2848
3274
  chartType: this.state.chartType,
2849
3275
  theme: a,
2850
3276
  autoScale: !0,
2851
3277
  crosshair: { mode: "magnet" },
3278
+ ...r.chartOptions,
2852
3279
  features: {
2853
3280
  drawings: !0,
2854
3281
  drawingMagnet: !0,
2855
3282
  drawingUndoRedo: !0,
2856
3283
  indicators: !0,
2857
3284
  trading: r.trading !== !1,
2858
- tradingContextMenu: r.trading !== !1,
3285
+ tradingContextMenu: !1,
2859
3286
  volume: !0,
2860
3287
  legend: !0,
2861
3288
  crosshair: !0,
3289
+ crosshairTooltip: !1,
2862
3290
  keyboard: !0,
2863
3291
  screenshot: !0,
2864
3292
  alerts: !0,
2865
3293
  barCountdown: !0,
2866
3294
  logScale: !0,
2867
- watermark: !0
2868
- },
2869
- ...r.chartOptions
2870
- }), r.dragDropImport !== !1 && (this.dragDrop = new t(this.chartContainer, {
3295
+ watermark: !0,
3296
+ ...r.chartOptions?.features
3297
+ }
3298
+ }), this.chart.on("dataUpdate", (e) => this.handleDataUpdate(e.payload)), r.dragDropImport !== !1 && (this.dragDrop = new t(this.chartContainer, {
2871
3299
  onData: (e, t, n) => {
2872
3300
  this.setData(e), this.toast(`Loaded ${t.data.length} bars from ${n.name}` + (t.skipped > 0 ? ` (${t.skipped} skipped)` : ""));
2873
3301
  },
2874
3302
  onError: (e, t) => {
2875
3303
  this.toast(`${t.name}: ${e.message}`, "error");
2876
3304
  }
2877
- }), this.dragDrop.attach()), r.statusBar !== !1 && (this.statusBar = new w(this.root)), r.settings !== !1 && (this.settings = new C({
3305
+ }), this.dragDrop.attach()), r.statusBar !== !1 && (this.statusBar = new C(this.root)), r.settings !== !1 && (this.settings = new S({
2878
3306
  onChange: (e) => this.applySettings(e),
2879
3307
  onReset: () => this.resetSettings(),
2880
3308
  onClose: () => {}
2881
- })), this.symbolSearch = new E({
3309
+ }, this.t)), this.symbolSearch = new T({
2882
3310
  onPick: (e) => {
2883
3311
  this.setSymbol(e);
2884
3312
  },
2885
3313
  onClose: () => {}
2886
- }), this.hotkeySheet = new N({ onClose: () => {} }), this.chart.on("barClick", (e) => {
3314
+ }), this.hotkeySheet = new N({ onClose: () => {} }, this.t), this.chart.on("barClick", (e) => {
2887
3315
  if (!this.replayBar?.isMounted()) return;
2888
3316
  let t = e.payload.barIndex;
2889
3317
  typeof t == "number" && (this.chart.getReplayState() === "playing" && this.chart.replayPause(), this.chart.replaySeek(t), this.replayBar.setState("paused"));
2890
- }), this.dataWindow = new ke(this.root, { formatPrice: (e) => this.formatAlertPrice(e) }), this.chart.on("crosshairMove", (e) => {
3318
+ }), this.dataWindow = new je(this.root, { formatPrice: (e) => this.formatAlertPrice(e) }), this.chart.on("crosshairMove", (e) => {
2891
3319
  let t = e.payload;
2892
3320
  this.lastHoverIndex = typeof t.barIndex == "number" ? t.barIndex : null, this.dataWindow?.isOpen() && this.dataWindow.render(this.buildDataWindowModel());
2893
- }), r.drawingTools !== !1 && (this.drawingStyle = new Se(this.root, {
3321
+ }), r.drawingTools !== !1 && (this.drawingStyle = new we(this.root, {
2894
3322
  onStyleChange: (e) => {
2895
3323
  this.chart.setDrawingStyle(e), this.chart.setSelectedDrawingStyle(e);
2896
3324
  },
2897
3325
  getStyle: () => this.chart.getDrawingStyle()
2898
- }, new ve())), r.trading !== !1 && (this.bracketBar = new Te(this.root, {
3326
+ }, new be())), r.trading !== !1 && (this.bracketBar = new De(this.root, {
2899
3327
  onConfirm: () => this.chart.confirmBracket(),
2900
3328
  onCancel: () => {
2901
3329
  this.chart.cancelBracket(), this.bracketBar?.hide();
@@ -2903,7 +3331,7 @@ var $ = [
2903
3331
  }), this.chart.on("bracketPlace", (e) => {
2904
3332
  let t = e.payload;
2905
3333
  this.bracketBar?.hide(), this.toast(`${t.side === "buy" ? "Long" : "Short"} bracket placed · ${t.riskReward.toFixed(2)}R`);
2906
- }), r.depthLadder && (this.depthLadder = new Oe(this.root, {
3334
+ }), r.depthLadder && (this.depthLadder = new Ae(this.root, {
2907
3335
  onTrade: (e, t) => {
2908
3336
  this.chart.placeOrderIntent({
2909
3337
  side: e,
@@ -2915,7 +3343,7 @@ var $ = [
2915
3343
  })), this.chart.on("dataUpdate", (e) => {
2916
3344
  let t = e.payload;
2917
3345
  t && t.bracket === "cancelled" && this.bracketBar?.hide();
2918
- })), r.alerts !== !1 && (this.alertsPanel = new ce(this.root, {
3346
+ })), r.alerts !== !1 && (this.alertsPanel = new ue(this.root, {
2919
3347
  onAdd: (e, t, n, r, i) => {
2920
3348
  this.chart.addAlert(e, t, n, r, i);
2921
3349
  },
@@ -2923,14 +3351,14 @@ var $ = [
2923
3351
  onClear: () => this.chart.clearAlerts(),
2924
3352
  getChannelValue: (e) => this.getAlertChannelValue(e),
2925
3353
  formatPrice: (e) => this.formatAlertPrice(e)
2926
- }), this.chart.on("alertAdd", () => this.refreshAlerts()), this.chart.on("alertRemove", () => this.refreshAlerts()), this.chart.on("alertUpdate", () => this.refreshAlerts()), r.alertNotifications && (this.alertNotifier = new Ee(r.alertNotifications)), this.chart.on("alertTriggered", (e) => {
3354
+ }), this.chart.on("alertAdd", () => this.refreshAlerts()), this.chart.on("alertRemove", () => this.refreshAlerts()), this.chart.on("alertUpdate", () => this.refreshAlerts()), r.alertNotifications && (this.alertNotifier = new Oe(r.alertNotifications)), this.chart.on("alertTriggered", (e) => {
2927
3355
  let t = e.payload, n = `Price ${this.formatAlertPrice(t.price)}${t.message ? ` — ${t.message}` : ""}`;
2928
3356
  this.toast(`🔔 Alert: ${n}`, "info"), this.alertNotifier?.notify(n), this.refreshAlerts();
2929
3357
  })), r.objectTree !== !1) {
2930
- this.indicatorSettings = new me(this.root, {
3358
+ this.indicatorSettings = new ge(this.root, {
2931
3359
  onApply: (e, t) => this.chart.updateIndicator(e, t),
2932
3360
  onClose: () => {}
2933
- }), this.objectTree = new le(this.root, {
3361
+ }), this.objectTree = new de(this.root, {
2934
3362
  onRemoveIndicator: (e) => this.handleRemoveIndicator(e),
2935
3363
  onConfigureIndicator: (e) => this.openIndicatorSettings(e),
2936
3364
  onToggleIndicatorVisible: (e, t) => {
@@ -2953,7 +3381,7 @@ var $ = [
2953
3381
  };
2954
3382
  this.chart.on("drawingCreate", e), this.chart.on("drawingRemove", e), this.chart.on("indicatorAdd", e), this.chart.on("indicatorRemove", e);
2955
3383
  }
2956
- if (this.commandPalette = new T({
3384
+ if (this.commandPalette = new w({
2957
3385
  onIndicator: (e) => this.handleAddIndicator(e),
2958
3386
  onChartType: (e) => this.handleChartType(e),
2959
3387
  onDrawingTool: (e) => this.handleDrawingTool(e),
@@ -2969,7 +3397,7 @@ var $ = [
2969
3397
  e.preventDefault(), this.hotkeySheet?.open();
2970
3398
  }
2971
3399
  }, document.addEventListener("keydown", this.boundGlobalKeydown), r.adapter && (this.adapter = r.adapter, this.connectStream()), this.watchlist && (this.watchlistInterval = setInterval(() => this.tickWatchlist(), 1e3)), this.updateUI(), r.onReady?.(this.chart), r.shareUrl && typeof location < "u") {
2972
- let e = Le(location.hash);
3400
+ let e = Be(location.hash);
2973
3401
  e && this.importState(e);
2974
3402
  }
2975
3403
  }
@@ -2983,19 +3411,19 @@ var $ = [
2983
3411
  }, this.sessionRefPrice = null, this.options.onSymbolChange?.(e), this.updateUI(), this.watchlist?.setActive(e), this.adapter && await this.connectStream();
2984
3412
  }
2985
3413
  setWatchlistEntry(e, t) {
2986
- this.watchlist?.setEntry(e, t);
3414
+ t.refPrice !== void 0 && this.hostWatchlistRefPrice.set(e, t.refPrice), this.watchlist?.setEntry(e, t);
2987
3415
  }
2988
3416
  tickWatchlist() {
2989
3417
  if (!this.watchlist) return;
2990
3418
  let e = this.chart.getData();
2991
3419
  if (e.length === 0) return;
2992
- let t = e[e.length - 1];
2993
- this.sessionRefPrice === null && (this.sessionRefPrice = e[0].open);
2994
- let n = this.watchlistSparkBuffer.get(this.state.symbol) ?? [];
2995
- n.push(t.close), n.length > 40 && n.shift(), this.watchlistSparkBuffer.set(this.state.symbol, n), this.watchlist.setEntry(this.state.symbol, {
3420
+ let t = e[e.length - 1], n = this.hostWatchlistRefPrice.get(this.state.symbol);
3421
+ n === void 0 && this.sessionRefPrice === null && (this.sessionRefPrice = e[0].open);
3422
+ let r = this.watchlistSparkBuffer.get(this.state.symbol) ?? [];
3423
+ r.push(t.close), r.length > 40 && r.shift(), this.watchlistSparkBuffer.set(this.state.symbol, r), this.watchlist.setEntry(this.state.symbol, {
2996
3424
  lastPrice: t.close,
2997
- refPrice: this.sessionRefPrice,
2998
- sparkline: n.slice()
3425
+ refPrice: n ?? this.sessionRefPrice ?? e[0].open,
3426
+ sparkline: r.slice()
2999
3427
  });
3000
3428
  }
3001
3429
  async setTimeframe(e) {
@@ -3006,7 +3434,13 @@ var $ = [
3006
3434
  await this.connectStream();
3007
3435
  return;
3008
3436
  }
3009
- this.options.resampleTimeframes !== !1 && this.applyTimeframeData();
3437
+ if (this.options.resampleTimeframes !== !1) {
3438
+ if (!this.baseSeries) {
3439
+ let e = this.chart.getData();
3440
+ e.length > 0 && (this.baseSeries = e, this.baseTimeframeMs = s(e));
3441
+ }
3442
+ await this.switchLocalTimeframe();
3443
+ }
3010
3444
  }
3011
3445
  setTheme(e) {
3012
3446
  let t = this.resolveIsDark(e), n = this.resolveTheme(e);
@@ -3019,37 +3453,65 @@ var $ = [
3019
3453
  return this.chart;
3020
3454
  }
3021
3455
  destroy() {
3022
- 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(), _());
3456
+ 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.loading.destroy(), this.chart.destroy(), this.root.remove(), _());
3023
3457
  }
3024
3458
  handleSymbolClick() {
3025
3459
  this.symbolSearch?.open(this.symbols, this.state.symbol);
3026
3460
  }
3027
3461
  handleTimeframe(e) {
3028
- if (this.state = {
3029
- ...this.state,
3030
- timeframe: e
3031
- }, this.options.onTimeframeChange?.(e), this.updateUI(), this.adapter) {
3032
- this.connectStream();
3033
- return;
3034
- }
3035
- if (this.options.resampleTimeframes !== !1) {
3036
- if (!this.baseSeries) {
3037
- let e = this.chart.getData();
3038
- e.length > 0 && (this.baseSeries = e, this.baseTimeframeMs = s(e));
3039
- }
3040
- this.applyTimeframeData();
3041
- }
3462
+ this.setTimeframe(e);
3042
3463
  }
3043
3464
  setData(e) {
3044
- this.baseSeries = e, this.baseTimeframeMs = s(e), this.applyTimeframeData();
3465
+ this.localSeq++, this.baseSeries = e, this.baseTimeframeMs = s(e), this.applyTimeframeData(), this.adapter || this.loading.end();
3466
+ }
3467
+ async switchLocalTimeframe() {
3468
+ if (!this.baseSeries) return;
3469
+ let e = ++this.localSeq, t = this.lastLocalSwitchMs >= Ke || this.baseSeries.length >= qe;
3470
+ try {
3471
+ if (t && (this.loading.begin(this.chart.getData().length > 0, !0), await Ye(), e !== this.localSeq || this.destroyed)) return;
3472
+ this.applyTimeframeData();
3473
+ } finally {
3474
+ e === this.localSeq && this.loading.end();
3475
+ }
3045
3476
  }
3046
3477
  applyTimeframeData() {
3047
3478
  if (!this.baseSeries) return;
3048
- let e = a(this.state.timeframe);
3049
- if (this.baseTimeframeMs > 0 && e > this.baseTimeframeMs) {
3479
+ let e = performance.now(), t = a(this.state.timeframe);
3480
+ if (this.baseTimeframeMs > 0 && t > this.baseTimeframeMs) {
3050
3481
  let e = this.options.weekStartsOn ?? 1;
3051
3482
  this.chart.setData(o(this.baseSeries, this.state.timeframe, { weekStartsOn: e }));
3052
3483
  } else this.chart.setData(this.baseSeries);
3484
+ this.lastLocalSwitchMs = performance.now() - e;
3485
+ }
3486
+ handleDataUpdate(e) {
3487
+ if (!e || typeof e != "object") return;
3488
+ let t = e;
3489
+ if (typeof t.length == "number") {
3490
+ t.length > 0 && this.loading.isActive() && (this.loading.end(), this.state.connectionState === "error" && this.setConnectionState("connected", this.t("status.live")));
3491
+ return;
3492
+ }
3493
+ if (t.error !== void 0) {
3494
+ this.loading.isActive() && (this.loading.fail(this.t("status.connectionFailed")), this.setConnectionState("error", t.error || this.t("status.connectionFailed")));
3495
+ return;
3496
+ }
3497
+ switch (t.connection?.state) {
3498
+ case "connected":
3499
+ this.loading.hasFailed() && this.loading.end(), !this.loading.isActive() && this.state.connectionState !== "connected" && this.setConnectionState("connected", this.t("status.live"));
3500
+ break;
3501
+ case "reconnecting":
3502
+ this.loading.isActive() || this.setConnectionState("connecting", this.t("status.connecting"));
3503
+ break;
3504
+ case "error":
3505
+ this.loading.isActive() || this.setConnectionState("error", this.t("status.connectionFailed"));
3506
+ break;
3507
+ }
3508
+ }
3509
+ setConnectionState(e, t) {
3510
+ this.state = {
3511
+ ...this.state,
3512
+ connectionState: e,
3513
+ connectionMessage: t
3514
+ }, this.updateUI();
3053
3515
  }
3054
3516
  toggleAlerts() {
3055
3517
  this.alertsPanel && (this.alertsPanel.toggle(), this.alertsPanel.isOpen() && this.refreshAlerts());
@@ -3063,7 +3525,7 @@ var $ = [
3063
3525
  id: e.id,
3064
3526
  params: e.params
3065
3527
  }));
3066
- return Fe({
3528
+ return Re({
3067
3529
  v: 1,
3068
3530
  symbol: this.state.symbol,
3069
3531
  timeframe: this.state.timeframe,
@@ -3074,7 +3536,7 @@ var $ = [
3074
3536
  });
3075
3537
  }
3076
3538
  async importState(e) {
3077
- let t = Ie(e);
3539
+ let t = ze(e);
3078
3540
  if (!t) return !1;
3079
3541
  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);
3080
3542
  for (let [, e] of this.state.activeIndicators) this.chart.removeIndicator(e);
@@ -3093,7 +3555,7 @@ var $ = [
3093
3555
  this.toast(e ? "Chart image copied" : "Copy failed — image clipboard unavailable", e ? "info" : "error");
3094
3556
  }
3095
3557
  async copyShareLink() {
3096
- let e = Re(typeof location < "u" ? location.href : "", this.exportState());
3558
+ let e = Ve(typeof location < "u" ? location.href : "", this.exportState());
3097
3559
  try {
3098
3560
  await navigator.clipboard.writeText(e), this.toast("Share link copied");
3099
3561
  } catch {
@@ -3161,7 +3623,7 @@ var $ = [
3161
3623
  visible: e.visible
3162
3624
  })), t = this.chart.getDrawings().map((e) => ({
3163
3625
  id: e.id,
3164
- label: de(e.type),
3626
+ label: pe(e.type),
3165
3627
  visible: e.visible,
3166
3628
  locked: e.locked
3167
3629
  })), n = this.compares.map((e) => ({
@@ -3524,7 +3986,7 @@ var $ = [
3524
3986
  }) : (this.chart.setScaleMode(e.scaleMode), this.settingsState = {
3525
3987
  ...this.settingsState,
3526
3988
  logScale: e.scaleMode === "logarithmic"
3527
- }), e.numberLocale !== void 0 && this.chart.setNumberLocale(e.numberLocale), e.timezone !== void 0 && this.chart.setTimezoneOffset(e.timezone === "local" ? null : Number(e.timezone));
3989
+ }), e.numberLocale !== void 0 && (this.chart.setNumberLocale(e.numberLocale), this.watchlist?.setLocale(e.numberLocale || void 0)), e.timezone !== void 0 && this.chart.setTimezoneOffset(e.timezone === "local" ? null : Number(e.timezone));
3528
3990
  let t = { ...this.chart.getTheme() }, n = !1;
3529
3991
  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);
3530
3992
  }
@@ -3532,35 +3994,40 @@ var $ = [
3532
3994
  this.settingsState = { ...p }, this.applySettings(this.settingsState);
3533
3995
  }
3534
3996
  async connectStream() {
3535
- if (this.adapter) {
3536
- this.state = {
3997
+ if (!this.adapter) return;
3998
+ let e = ++this.connectSeq;
3999
+ this.state = {
4000
+ ...this.state,
4001
+ connectionState: "connecting",
4002
+ connectionMessage: this.t("status.connecting")
4003
+ }, this.updateUI(), this.loading.begin(this.chart.getData().length > 0);
4004
+ try {
4005
+ if (this.chart.disconnectStream(), await this.chart.connect({
4006
+ adapter: this.adapter,
4007
+ symbol: this.state.symbol,
4008
+ timeframe: this.state.timeframe,
4009
+ historyLimit: this.options.historyLimit ?? 500
4010
+ }), e !== this.connectSeq || this.destroyed) return;
4011
+ this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), {
4012
+ fontSize: 48,
4013
+ color: this.state.isDark ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)"
4014
+ }), this.applySymbolLayout(this.state.symbol), this.loading.hasFailed() ? this.state = {
3537
4015
  ...this.state,
3538
- connectionState: "connecting",
3539
- connectionMessage: "Connecting..."
3540
- }, this.updateUI();
3541
- try {
3542
- this.chart.disconnectStream(), await this.chart.connect({
3543
- adapter: this.adapter,
3544
- symbol: this.state.symbol,
3545
- timeframe: this.state.timeframe,
3546
- historyLimit: this.options.historyLimit ?? 500
3547
- }), this.chart.setWatermark(this.state.symbol.replace("USDT", " / USDT"), {
3548
- fontSize: 48,
3549
- color: this.state.isDark ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)"
3550
- }), this.applySymbolLayout(this.state.symbol), this.state = {
3551
- ...this.state,
3552
- connectionState: "connected",
3553
- connectionMessage: "Live"
3554
- }, this.refetchCompares();
3555
- } catch (e) {
3556
- this.state = {
3557
- ...this.state,
3558
- connectionState: "error",
3559
- connectionMessage: e instanceof Error ? e.message : "Connection failed"
3560
- };
3561
- }
3562
- this.updateUI();
4016
+ connectionState: "error"
4017
+ } : (this.loading.end(), this.state = {
4018
+ ...this.state,
4019
+ connectionState: "connected",
4020
+ connectionMessage: this.t("status.live")
4021
+ }), this.refetchCompares();
4022
+ } catch (t) {
4023
+ if (e !== this.connectSeq || this.destroyed) return;
4024
+ this.loading.fail(this.t("status.connectionFailed")), this.state = {
4025
+ ...this.state,
4026
+ connectionState: "error",
4027
+ connectionMessage: t instanceof Error ? t.message : this.t("status.connectionFailed")
4028
+ };
3563
4029
  }
4030
+ this.updateUI();
3564
4031
  }
3565
4032
  updateUI() {
3566
4033
  this.toolbar?.update(this.state), this.sidebar?.update(this.state), this.statusBar?.update({
@@ -3585,6 +4052,6 @@ var $ = [
3585
4052
  }
3586
4053
  };
3587
4054
  //#endregion
3588
- export { ze as ChartWidget };
4055
+ export { Xe as ChartWidget };
3589
4056
 
3590
4057
  //# sourceMappingURL=index.js.map