@tradecanvas/chart 1.70.0 → 1.71.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.
- package/dist/Chart.d.ts +4 -11
- package/dist/Chart.d.ts.map +1 -1
- package/dist/{LayoutSession-Bcy79w0l.js → LayoutSession-BOQCN6yY.js} +584 -529
- package/dist/LayoutSession-BOQCN6yY.js.map +1 -0
- package/dist/LayoutSession-RF8OqOXy.cjs +2 -0
- package/dist/LayoutSession-RF8OqOXy.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +60 -60
- package/dist/model/AlertWatch.d.ts +60 -0
- package/dist/model/AlertWatch.d.ts.map +1 -0
- package/dist/model/ReplayMarks.d.ts +42 -0
- package/dist/model/ReplayMarks.d.ts.map +1 -0
- package/dist/widget/WidgetIndicatorSettings.d.ts +1 -0
- package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -1
- package/dist/widget/index.cjs +4 -4
- package/dist/widget/index.cjs.map +1 -1
- package/dist/widget/index.js +544 -528
- package/dist/widget/index.js.map +1 -1
- package/dist/widget/settingsControls.d.ts +1 -0
- package/dist/widget/settingsControls.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/LayoutSession-Bcy79w0l.js.map +0 -1
- package/dist/LayoutSession-D7S6GZgJ.cjs +0 -2
- package/dist/LayoutSession-D7S6GZgJ.cjs.map +0 -1
package/dist/widget/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { O as e, a as t, c as n, d as r, f as i, i as a, n as o, o as s, r as c, t as l } from "../LayoutSession-
|
|
1
|
+
import { O as e, a as t, c as n, d as r, f as i, i as a, n as o, o as s, r as c, t as l } from "../LayoutSession-BOQCN6yY.js";
|
|
2
2
|
import { a as u, c as d, i as f, n as p, o as m, r as h, s as ee, t as g } from "../i18n-DUmd4Z_r.js";
|
|
3
3
|
import { CHART_STYLE_KEYS as _, CHART_TYPE_ICONS as v, DARK_THEME as y, DEFAULT_SIGNAL_STYLE as b, DEFAULT_TRADE_ZONE_STYLE as x, DEFAULT_TRADING_CONFIG as S, DRAWING_TOOL_ICONS as te, LIGHT_THEME as ne, PHI as re, PRICE_SOURCES as ie, SANS_FONT_FAMILY as ae, UI_ICONS as oe, barTimeUnit as se, formatPrice as ce, formatVolumeLoc as le, iconSvg as ue, indicatorSource as de, isTimeFrame as fe, isValidTimeZone as pe, marketStatus as me, offsetAt as he, parseIndicatorSource as ge, phiStep as _e, readChartStyleOverrides as ve, readChartTypeOptions as ye, readIndicatorPlotStyles as be, readNews as xe, readQuote as Se, resampleBars as Ce, sanitizeDrawingOptions as we, sanitizeDrawingStyle as Te, stepDecimals as Ee, symbolTimeZone as De, tickBarCount as Oe, timeParts as ke, timeframeFollowsDays as Ae, timeframeToMs as C, tzLabel as je, wallToUtc as Me, zoneOffsetMinutes as Ne, zonedDateFormatter as Pe } from "@tradecanvas/commons";
|
|
4
|
-
import { ChartStateManager as Fe, INDICATOR_CATEGORIES as Ie, INTERVAL_LIMITS as Le, INTERVAL_UNITS as Re, MAX_ALERT_BARS as ze, MIN_ALERT_BARS as Be, RANGE_PRESETS as Ve, ResamplingAdapter as He, SYMBOL_INDICATOR_IDS as Ue, adapterFromFeed as We,
|
|
4
|
+
import { ChartStateManager as Fe, INDICATOR_CATEGORIES as Ie, INTERVAL_LIMITS as Le, INTERVAL_UNITS as Re, MAX_ALERT_BARS as ze, MIN_ALERT_BARS as Be, RANGE_PRESETS as Ve, ResamplingAdapter as He, SYMBOL_INDICATOR_IDS as Ue, adapterFromFeed as We, describeInputs as Ge, indicatorCategory as Ke, indicatorValuePrecision as qe, isSeriesPalette as Je, plotColor as Ye, plotShown as Xe, rangePresetStart as Ze, servesTimeframe as Qe, sourceParam as $e, withResampling as et } from "@tradecanvas/core";
|
|
5
5
|
//#region src/io/resampleOHLCV.ts
|
|
6
|
-
function
|
|
6
|
+
function tt(e, t, n = {}) {
|
|
7
7
|
return Ce(e, t, {
|
|
8
8
|
weekStartsOn: n.weekStartsOn ?? 1,
|
|
9
9
|
timeZone: n.timeZone
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
|
-
function
|
|
12
|
+
function nt(e) {
|
|
13
13
|
if (e.length < 2) return 0;
|
|
14
14
|
let t = [];
|
|
15
15
|
for (let n = 1; n < e.length; n++) {
|
|
@@ -20,7 +20,7 @@ function tt(e) {
|
|
|
20
20
|
}
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region src/widget/widgetTimezones.ts
|
|
23
|
-
var
|
|
23
|
+
var rt = [
|
|
24
24
|
{
|
|
25
25
|
zone: "Pacific/Honolulu",
|
|
26
26
|
city: "Honolulu"
|
|
@@ -133,27 +133,27 @@ var nt = [
|
|
|
133
133
|
zone: "Pacific/Auckland",
|
|
134
134
|
city: "Auckland"
|
|
135
135
|
}
|
|
136
|
-
],
|
|
137
|
-
function at(e) {
|
|
138
|
-
if (!rt.test(e)) return null;
|
|
139
|
-
let t = Number(e);
|
|
140
|
-
return Math.abs(t) <= it ? t : null;
|
|
141
|
-
}
|
|
136
|
+
], it = /^-?\d+$/, at = 840;
|
|
142
137
|
function ot(e) {
|
|
143
|
-
|
|
138
|
+
if (!it.test(e)) return null;
|
|
139
|
+
let t = Number(e);
|
|
140
|
+
return Math.abs(t) <= at ? t : null;
|
|
144
141
|
}
|
|
145
142
|
function st(e) {
|
|
143
|
+
return !e || e === "local" ? null : e === "exchange" ? "exchange" : it.test(e) ? ot(e) : pe(e) ? e : null;
|
|
144
|
+
}
|
|
145
|
+
function ct(e) {
|
|
146
146
|
return e === null ? "local" : String(e);
|
|
147
147
|
}
|
|
148
|
-
function
|
|
149
|
-
let i = he(null, t), a =
|
|
148
|
+
function lt(e, t, n, r) {
|
|
149
|
+
let i = he(null, t), a = rt.filter(({ zone: e }) => pe(e)).map(({ zone: e, city: n }) => {
|
|
150
150
|
let r = he(e, t);
|
|
151
151
|
return {
|
|
152
152
|
value: e,
|
|
153
153
|
label: e === "UTC" ? "UTC" : `(${je(r)}) ${n}`,
|
|
154
154
|
offset: r
|
|
155
155
|
};
|
|
156
|
-
}), o =
|
|
156
|
+
}), o = st(e);
|
|
157
157
|
typeof o == "number" && a.push({
|
|
158
158
|
value: e,
|
|
159
159
|
label: je(o),
|
|
@@ -176,18 +176,18 @@ function ct(e, t, n, r) {
|
|
|
176
176
|
}
|
|
177
177
|
//#endregion
|
|
178
178
|
//#region src/widget/placeMenu.ts
|
|
179
|
-
var
|
|
180
|
-
function
|
|
179
|
+
var ut = 6, dt = 8, ft = 120;
|
|
180
|
+
function pt(e, t, n = "left") {
|
|
181
181
|
let r = e.style, i = t.getBoundingClientRect();
|
|
182
182
|
r.position = "fixed", r.margin = "0", r.top = r.bottom = r.left = r.right = "";
|
|
183
|
-
let a = window.innerHeight - i.bottom -
|
|
184
|
-
e.scrollHeight <= a || a >= o ? (r.top = `${i.bottom +
|
|
183
|
+
let a = window.innerHeight - i.bottom - ut - dt, o = i.top - ut - dt;
|
|
184
|
+
e.scrollHeight <= a || a >= o ? (r.top = `${i.bottom + ut}px`, r.bottom = "auto", r.maxHeight = `${Math.max(ft, a)}px`) : (r.top = "auto", r.bottom = `${window.innerHeight - i.top + ut}px`, r.maxHeight = `${Math.max(ft, o)}px`);
|
|
185
185
|
let s = getComputedStyle(t).direction === "rtl", c = n === "right" !== s, l = e.offsetWidth, u = c ? i.right - l : i.left;
|
|
186
|
-
r.left = `${Math.max(
|
|
186
|
+
r.left = `${Math.max(dt, Math.min(u, window.innerWidth - l - dt))}px`;
|
|
187
187
|
}
|
|
188
188
|
//#endregion
|
|
189
189
|
//#region src/widget/selectMenu.ts
|
|
190
|
-
var
|
|
190
|
+
var mt = 700, ht = class {
|
|
191
191
|
select = null;
|
|
192
192
|
panel = null;
|
|
193
193
|
rows = [];
|
|
@@ -233,7 +233,7 @@ var pt = 700, mt = class {
|
|
|
233
233
|
}), t.addEventListener("mousemove", (e) => {
|
|
234
234
|
let t = r(e);
|
|
235
235
|
t >= 0 && t !== this.active && this.enabled(t) && this.setActive(t, !1);
|
|
236
|
-
}), this.layer().appendChild(t), this.panel = t,
|
|
236
|
+
}), this.layer().appendChild(t), this.panel = t, pt(t, e), e.setAttribute("aria-expanded", "true"), e.setAttribute("aria-controls", t.id), this.setActive(this.rows.findIndex((e) => e.option.selected)), document.addEventListener("pointerdown", this.onOutside, !0), window.addEventListener("resize", this.onAway), document.addEventListener("scroll", this.onScroll, {
|
|
237
237
|
capture: !0,
|
|
238
238
|
passive: !0
|
|
239
239
|
}), this.watch.observe(document.documentElement, {
|
|
@@ -254,7 +254,7 @@ var pt = 700, mt = class {
|
|
|
254
254
|
case "End": return this.setActive(this.nextEnabled(this.rows.length, -1)), !0;
|
|
255
255
|
case "PageDown": return this.step(8), !0;
|
|
256
256
|
case "PageUp": return this.step(-8), !0;
|
|
257
|
-
case " ": return this.typed && Date.now() - this.typedAt <=
|
|
257
|
+
case " ": return this.typed && Date.now() - this.typedAt <= mt ? (this.typeahead(" "), !0) : (this.active >= 0 ? this.pick(this.active) : this.close(!0), !0);
|
|
258
258
|
case "Enter": return this.active >= 0 ? this.pick(this.active) : this.close(!0), !0;
|
|
259
259
|
case "Escape": return this.close(!0), !0;
|
|
260
260
|
case "Tab": return this.close(!1), !1;
|
|
@@ -298,7 +298,7 @@ var pt = 700, mt = class {
|
|
|
298
298
|
}
|
|
299
299
|
typeahead(e) {
|
|
300
300
|
let t = Date.now();
|
|
301
|
-
this.typed = t - this.typedAt >
|
|
301
|
+
this.typed = t - this.typedAt > mt ? e.toLowerCase() : this.typed + e.toLowerCase(), this.typedAt = t;
|
|
302
302
|
let n = (e) => this.enabled(e) && (this.rows[e].el.textContent ?? "").trim().toLowerCase().startsWith(this.typed), r = this.typed.length === 1 ? this.active + 1 : Math.max(0, this.active);
|
|
303
303
|
for (let e = 0; e < this.rows.length; e++) {
|
|
304
304
|
let t = (r + e) % this.rows.length;
|
|
@@ -314,7 +314,7 @@ var pt = 700, mt = class {
|
|
|
314
314
|
let r = !n.option.selected;
|
|
315
315
|
n.option.selected = !0, this.close(!0), r && (t.dispatchEvent(new Event("input", { bubbles: !0 })), t.dispatchEvent(new Event("change", { bubbles: !0 })));
|
|
316
316
|
}
|
|
317
|
-
},
|
|
317
|
+
}, gt = 42, _t = 7, vt = new Set([
|
|
318
318
|
"US",
|
|
319
319
|
"CA",
|
|
320
320
|
"MX",
|
|
@@ -333,17 +333,17 @@ var pt = 700, mt = class {
|
|
|
333
333
|
"PE",
|
|
334
334
|
"CO"
|
|
335
335
|
]);
|
|
336
|
-
function
|
|
336
|
+
function yt(e) {
|
|
337
337
|
try {
|
|
338
338
|
let t = new Intl.Locale(e), n = t.getWeekInfo?.() ?? t.weekInfo;
|
|
339
|
-
return n ? n.firstDay === 7 ? 0 : 1 : +!
|
|
339
|
+
return n ? n.firstDay === 7 ? 0 : 1 : +!vt.has(t.maximize().region ?? "");
|
|
340
340
|
} catch {
|
|
341
341
|
return 1;
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
|
-
function
|
|
345
|
-
let r = (new Date(Date.UTC(e, t, 1)).getUTCDay() - n +
|
|
346
|
-
for (let n = 0; n <
|
|
344
|
+
function bt(e, t, n) {
|
|
345
|
+
let r = (new Date(Date.UTC(e, t, 1)).getUTCDay() - n + _t) % _t, i = [];
|
|
346
|
+
for (let n = 0; n < gt; n++) {
|
|
347
347
|
let a = new Date(Date.UTC(e, t, 1 - r + n));
|
|
348
348
|
i.push({
|
|
349
349
|
year: a.getUTCFullYear(),
|
|
@@ -353,8 +353,8 @@ function yt(e, t, n) {
|
|
|
353
353
|
}
|
|
354
354
|
return i;
|
|
355
355
|
}
|
|
356
|
-
var
|
|
357
|
-
function
|
|
356
|
+
var xt = (e) => String(e).padStart(2, "0"), w = (e) => `${String(e.year).padStart(4, "0")}-${xt(e.month + 1)}-${xt(e.day)}`;
|
|
357
|
+
function St(e) {
|
|
358
358
|
let t = /^(\d{4})-(\d{2})-(\d{2})$/.exec(e ?? "");
|
|
359
359
|
return t ? {
|
|
360
360
|
year: Number(t[1]),
|
|
@@ -362,7 +362,7 @@ function xt(e) {
|
|
|
362
362
|
day: Number(t[3])
|
|
363
363
|
} : null;
|
|
364
364
|
}
|
|
365
|
-
function
|
|
365
|
+
function Ct() {
|
|
366
366
|
let e = /* @__PURE__ */ new Date();
|
|
367
367
|
return {
|
|
368
368
|
year: e.getFullYear(),
|
|
@@ -370,7 +370,7 @@ function St() {
|
|
|
370
370
|
day: e.getDate()
|
|
371
371
|
};
|
|
372
372
|
}
|
|
373
|
-
function
|
|
373
|
+
function wt(e, t) {
|
|
374
374
|
let n = new Date(Date.UTC(e.year, e.month, e.day + t));
|
|
375
375
|
return {
|
|
376
376
|
year: n.getUTCFullYear(),
|
|
@@ -378,18 +378,18 @@ function Ct(e, t) {
|
|
|
378
378
|
day: n.getUTCDate()
|
|
379
379
|
};
|
|
380
380
|
}
|
|
381
|
-
var
|
|
381
|
+
var Tt = class {
|
|
382
382
|
element;
|
|
383
383
|
grid;
|
|
384
384
|
titleEl;
|
|
385
385
|
chosen = "";
|
|
386
386
|
limits = {};
|
|
387
|
-
today = w(
|
|
387
|
+
today = w(Ct());
|
|
388
388
|
view = {
|
|
389
389
|
year: 0,
|
|
390
390
|
month: 0
|
|
391
391
|
};
|
|
392
|
-
focusDay =
|
|
392
|
+
focusDay = Ct();
|
|
393
393
|
constructor(e, t, n) {
|
|
394
394
|
this.locale = t, this.onPick = n;
|
|
395
395
|
let r = document.createElement("div");
|
|
@@ -400,13 +400,13 @@ var wt = class {
|
|
|
400
400
|
a.className = "tcw-calendar-title", a.setAttribute("aria-live", "polite"), i.append(this.navButton(e.prevMonth, -1), a, this.navButton(e.nextMonth, 1));
|
|
401
401
|
let o = document.createElement("div");
|
|
402
402
|
o.className = "tcw-calendar-weekdays", o.setAttribute("aria-hidden", "true");
|
|
403
|
-
let s =
|
|
403
|
+
let s = yt(t), c = new Intl.DateTimeFormat(t, {
|
|
404
404
|
weekday: "narrow",
|
|
405
405
|
timeZone: "UTC"
|
|
406
406
|
});
|
|
407
|
-
for (let e = 0; e <
|
|
407
|
+
for (let e = 0; e < _t; e++) {
|
|
408
408
|
let t = document.createElement("span");
|
|
409
|
-
t.className = "tcw-calendar-weekday", t.textContent = c.format(new Date(Date.UTC(2023, 0, 1 + (s + e) %
|
|
409
|
+
t.className = "tcw-calendar-weekday", t.textContent = c.format(new Date(Date.UTC(2023, 0, 1 + (s + e) % _t))), o.appendChild(t);
|
|
410
410
|
}
|
|
411
411
|
let l = document.createElement("div");
|
|
412
412
|
l.className = "tcw-calendar-grid", l.setAttribute("role", "grid"), l.addEventListener("keydown", (e) => this.onKey(e)), l.addEventListener("click", (e) => {
|
|
@@ -419,8 +419,8 @@ var wt = class {
|
|
|
419
419
|
d.type = "button", d.className = "tcw-calendar-today", d.textContent = e.today, d.addEventListener("click", () => this.pick(this.today)), u.appendChild(d), r.append(i, o, l, u), this.element = r, this.grid = l, this.titleEl = a;
|
|
420
420
|
}
|
|
421
421
|
show(e, t = {}) {
|
|
422
|
-
this.chosen = e, this.limits = t, this.today =
|
|
423
|
-
let n = this.clamp(
|
|
422
|
+
this.chosen = e, this.limits = t, this.today = St(t.today) ? t.today : w(Ct());
|
|
423
|
+
let n = this.clamp(St(e) ?? St(this.today));
|
|
424
424
|
this.focusDay = n, this.view = {
|
|
425
425
|
year: n.year,
|
|
426
426
|
month: n.month
|
|
@@ -449,7 +449,7 @@ var wt = class {
|
|
|
449
449
|
}, this.render();
|
|
450
450
|
}
|
|
451
451
|
clamp(e) {
|
|
452
|
-
let t = w(e), n =
|
|
452
|
+
let t = w(e), n = St(this.limits.min), r = St(this.limits.max);
|
|
453
453
|
return n && t < w(n) ? n : r && t > w(r) ? r : e;
|
|
454
454
|
}
|
|
455
455
|
allowed(e) {
|
|
@@ -469,8 +469,8 @@ var wt = class {
|
|
|
469
469
|
});
|
|
470
470
|
this.grid.textContent = "";
|
|
471
471
|
let i = null;
|
|
472
|
-
for (let [a, o] of
|
|
473
|
-
a %
|
|
472
|
+
for (let [a, o] of bt(this.view.year, this.view.month, yt(e)).entries()) {
|
|
473
|
+
a % _t === 0 && (i = document.createElement("div"), i.className = "tcw-calendar-week", i.setAttribute("role", "row"), this.grid.appendChild(i));
|
|
474
474
|
let e = w(o), s = document.createElement("button");
|
|
475
475
|
s.type = "button", s.className = "tcw-calendar-day", s.dataset.date = e, s.setAttribute("role", "gridcell"), s.textContent = String(o.day), s.setAttribute("aria-label", r.format(new Date(Date.UTC(o.year, o.month, o.day)))), s.setAttribute("aria-selected", String(e === this.chosen)), s.tabIndex = e === n ? 0 : -1, o.month !== this.view.month && s.classList.add("tcw-outside"), e === t && s.classList.add("tcw-today"), this.allowed(e) || (s.disabled = !0), i?.appendChild(s);
|
|
476
476
|
}
|
|
@@ -479,12 +479,12 @@ var wt = class {
|
|
|
479
479
|
let t = {
|
|
480
480
|
ArrowLeft: -1,
|
|
481
481
|
ArrowRight: 1,
|
|
482
|
-
ArrowUp: -
|
|
483
|
-
ArrowDown:
|
|
482
|
+
ArrowUp: -_t,
|
|
483
|
+
ArrowDown: _t
|
|
484
484
|
}, n = this.element.isConnected && getComputedStyle(this.element).direction === "rtl";
|
|
485
485
|
if (e.key in t) {
|
|
486
486
|
let r = n && (e.key === "ArrowLeft" || e.key === "ArrowRight") ? -t[e.key] : t[e.key];
|
|
487
|
-
this.moveFocus(
|
|
487
|
+
this.moveFocus(wt(this.focusDay, r));
|
|
488
488
|
} else if (e.key === "PageUp" || e.key === "PageDown") this.turn(e.key === "PageUp" ? -1 : 1), this.focusGrid();
|
|
489
489
|
else if (e.key === "Home" || e.key === "End") {
|
|
490
490
|
let t = new Date(Date.UTC(this.view.year, this.view.month + 1, 0)).getUTCDate();
|
|
@@ -506,7 +506,7 @@ var wt = class {
|
|
|
506
506
|
pick(e) {
|
|
507
507
|
this.allowed(e) && this.onPick(e);
|
|
508
508
|
}
|
|
509
|
-
},
|
|
509
|
+
}, Et = class {
|
|
510
510
|
input = null;
|
|
511
511
|
view = null;
|
|
512
512
|
onOutside = (e) => {
|
|
@@ -531,7 +531,7 @@ var wt = class {
|
|
|
531
531
|
}
|
|
532
532
|
open(e) {
|
|
533
533
|
this.close(!1), this.input = e;
|
|
534
|
-
let t = new
|
|
534
|
+
let t = new Tt(this.labels(), this.locale(), (e) => this.pick(e));
|
|
535
535
|
t.show(e.value, {
|
|
536
536
|
min: e.min || void 0,
|
|
537
537
|
max: e.max || void 0
|
|
@@ -543,7 +543,7 @@ var wt = class {
|
|
|
543
543
|
e.target.closest("button") || e.preventDefault();
|
|
544
544
|
}), n.addEventListener("keydown", (e) => {
|
|
545
545
|
e.stopPropagation(), e.key === "Escape" && (e.preventDefault(), this.close(!0));
|
|
546
|
-
}), this.view = t, this.layer().appendChild(n),
|
|
546
|
+
}), this.view = t, this.layer().appendChild(n), pt(n, e), document.addEventListener("pointerdown", this.onOutside, !0), window.addEventListener("resize", this.onAway), document.addEventListener("scroll", this.onScroll, {
|
|
547
547
|
capture: !0,
|
|
548
548
|
passive: !0
|
|
549
549
|
}), this.watch.observe(document.documentElement, {
|
|
@@ -567,19 +567,19 @@ var wt = class {
|
|
|
567
567
|
let n = t.value !== e;
|
|
568
568
|
t.value = e, this.close(!0), n && (t.dispatchEvent(new Event("input", { bubbles: !0 })), t.dispatchEvent(new Event("change", { bubbles: !0 })));
|
|
569
569
|
}
|
|
570
|
-
},
|
|
571
|
-
function
|
|
570
|
+
}, Dt = () => typeof matchMedia == "function" && matchMedia("(pointer: coarse)").matches, Ot = () => typeof CSS > "u" || typeof CSS.supports != "function" || CSS.supports("selector(::-webkit-calendar-picker-indicator)");
|
|
571
|
+
function kt(e) {
|
|
572
572
|
if (!(e instanceof Element)) return null;
|
|
573
573
|
let t = e.closest("select");
|
|
574
574
|
return !t || t.matches(":disabled") || t.multiple || t.size > 1 ? null : t;
|
|
575
575
|
}
|
|
576
|
-
function
|
|
576
|
+
function At(e) {
|
|
577
577
|
return !(e instanceof HTMLInputElement) || e.type !== "date" || e.dataset.tcwCalendar === "inline" || e.matches(":disabled") || e.readOnly ? null : e;
|
|
578
578
|
}
|
|
579
|
-
function
|
|
580
|
-
let n = new
|
|
579
|
+
function jt(e, t) {
|
|
580
|
+
let n = new ht(t.layer), r = new Et(t.layer, t.labels, t.locale), i = t.native ?? Dt, a = t.calendar ?? Ot, o = /* @__PURE__ */ new WeakSet(), s = (e) => o.has(e) ? !1 : (o.add(e), !0), c = (e) => {
|
|
581
581
|
if (e.button !== 0 || i() || !s(e)) return;
|
|
582
|
-
let t =
|
|
582
|
+
let t = kt(e.target);
|
|
583
583
|
if (t) {
|
|
584
584
|
if (e.preventDefault(), n.isOpenFor(t)) {
|
|
585
585
|
n.close(!0);
|
|
@@ -589,11 +589,11 @@ function At(e, t) {
|
|
|
589
589
|
}
|
|
590
590
|
}, l = (e) => {
|
|
591
591
|
if (i() || !a() || !s(e)) return;
|
|
592
|
-
let t =
|
|
592
|
+
let t = At(e.target);
|
|
593
593
|
t && (e.preventDefault(), r.isOpenFor(t) || r.open(t));
|
|
594
594
|
}, u = (e) => {
|
|
595
595
|
if (i() || !s(e)) return;
|
|
596
|
-
let t =
|
|
596
|
+
let t = kt(e.target);
|
|
597
597
|
if (t) {
|
|
598
598
|
if (n.isOpenFor(t)) {
|
|
599
599
|
n.key(e) && (e.preventDefault(), e.stopPropagation());
|
|
@@ -602,7 +602,7 @@ function At(e, t) {
|
|
|
602
602
|
(e.key === "Enter" || e.key === " " || e.altKey && (e.key === "ArrowDown" || e.key === "ArrowUp") || e.key === "F4") && (e.preventDefault(), e.stopPropagation(), n.open(t));
|
|
603
603
|
return;
|
|
604
604
|
}
|
|
605
|
-
let o =
|
|
605
|
+
let o = At(e.target);
|
|
606
606
|
!o || !a() || (e.key === "Escape" && r.isOpenFor(o) ? (e.preventDefault(), e.stopPropagation(), r.close(!0)) : (e.altKey && e.key === "ArrowDown" || e.key === "F4") && (e.preventDefault(), r.isOpenFor(o) || r.open(o), r.focusGrid()));
|
|
607
607
|
}, d = (e) => {
|
|
608
608
|
if (!s(e)) return;
|
|
@@ -617,7 +617,7 @@ function At(e, t) {
|
|
|
617
617
|
}
|
|
618
618
|
//#endregion
|
|
619
619
|
//#region src/widget/widgetConfig.ts
|
|
620
|
-
var
|
|
620
|
+
var Mt = [
|
|
621
621
|
{
|
|
622
622
|
label: "Candlestick",
|
|
623
623
|
value: "candlestick"
|
|
@@ -690,7 +690,7 @@ var jt = [
|
|
|
690
690
|
label: "Range Bars",
|
|
691
691
|
value: "rangeBars"
|
|
692
692
|
}
|
|
693
|
-
],
|
|
693
|
+
], Nt = [
|
|
694
694
|
{
|
|
695
695
|
label: "Lines",
|
|
696
696
|
section: "lines",
|
|
@@ -1058,12 +1058,12 @@ var jt = [
|
|
|
1058
1058
|
}
|
|
1059
1059
|
]
|
|
1060
1060
|
}
|
|
1061
|
-
],
|
|
1061
|
+
], Pt = [
|
|
1062
1062
|
"BTCUSDT",
|
|
1063
1063
|
"ETHUSDT",
|
|
1064
1064
|
"SOLUSDT",
|
|
1065
1065
|
"BNBUSDT"
|
|
1066
|
-
],
|
|
1066
|
+
], Ft = {
|
|
1067
1067
|
gridVisible: !0,
|
|
1068
1068
|
volumeVisible: !0,
|
|
1069
1069
|
volumeProfileVisible: !1,
|
|
@@ -1103,7 +1103,7 @@ var jt = [
|
|
|
1103
1103
|
label: e,
|
|
1104
1104
|
keys: [t],
|
|
1105
1105
|
auto: n
|
|
1106
|
-
}), D = (e) => ({ hint: e }),
|
|
1106
|
+
}), D = (e) => ({ hint: e }), It = { from: "panes.titleColor" }, Lt = {
|
|
1107
1107
|
title: "settings.section.lastPrice",
|
|
1108
1108
|
rows: [
|
|
1109
1109
|
T("settings.priceLine", "lastPrice.visible"),
|
|
@@ -1112,24 +1112,24 @@ var jt = [
|
|
|
1112
1112
|
T("drawingSettings.lineStyle", "lastPrice.style"),
|
|
1113
1113
|
T("drawingSettings.lineWidth", "lastPrice.width")
|
|
1114
1114
|
]
|
|
1115
|
-
},
|
|
1115
|
+
}, Rt = {
|
|
1116
1116
|
title: "settings.volume",
|
|
1117
1117
|
rows: [T("settings.up", "volume.upColor"), T("settings.down", "volume.downColor")]
|
|
1118
|
-
},
|
|
1118
|
+
}, zt = {
|
|
1119
1119
|
title: "settings.highLowLines",
|
|
1120
|
-
rows: [E("drawingSettings.color", "highLow.color",
|
|
1121
|
-
},
|
|
1122
|
-
It,
|
|
1120
|
+
rows: [E("drawingSettings.color", "highLow.color", It)]
|
|
1121
|
+
}, Bt = [
|
|
1123
1122
|
Lt,
|
|
1124
|
-
Rt
|
|
1125
|
-
|
|
1123
|
+
Rt,
|
|
1124
|
+
zt
|
|
1125
|
+
], Vt = [T("settings.legendText", "legend.textColor"), T("settings.legendLabels", "legend.labelColor")], Ht = [...Vt, T("settings.paneTitles", "panes.titleColor")], Ut = [T("drawingSettings.text", "axis.price.textColor", "axis.time.textColor"), T("settings.scaleLines", "axis.price.lineColor", "axis.time.lineColor")], Wt = [
|
|
1126
1126
|
{
|
|
1127
1127
|
title: "settings.section.background",
|
|
1128
1128
|
rows: [
|
|
1129
1129
|
T("settings.background", "background.color"),
|
|
1130
1130
|
T("settings.paneBackground", "panes.background"),
|
|
1131
1131
|
T("settings.paneSeparator", "panes.separatorColor"),
|
|
1132
|
-
E("settings.watermark", "watermark.color",
|
|
1132
|
+
E("settings.watermark", "watermark.color", It)
|
|
1133
1133
|
]
|
|
1134
1134
|
},
|
|
1135
1135
|
{
|
|
@@ -1166,7 +1166,7 @@ var jt = [
|
|
|
1166
1166
|
title: "objects.drawings",
|
|
1167
1167
|
rows: [E("settings.handles", "drawings.handleColor", D("#ffffff"))]
|
|
1168
1168
|
}
|
|
1169
|
-
],
|
|
1169
|
+
], Gt = [
|
|
1170
1170
|
{
|
|
1171
1171
|
title: "settings.section.orders",
|
|
1172
1172
|
trading: !0,
|
|
@@ -1194,7 +1194,7 @@ var jt = [
|
|
|
1194
1194
|
E("settings.openTrade", "tradeZones.activeColor", D(x.activeColor))
|
|
1195
1195
|
]
|
|
1196
1196
|
}
|
|
1197
|
-
],
|
|
1197
|
+
], Kt = {
|
|
1198
1198
|
upColor: "settings.up",
|
|
1199
1199
|
downColor: "settings.down",
|
|
1200
1200
|
wickUpColor: "settings.upWick",
|
|
@@ -1204,28 +1204,28 @@ var jt = [
|
|
|
1204
1204
|
lineWidth: "drawingSettings.lineWidth",
|
|
1205
1205
|
topColor: "settings.areaTop",
|
|
1206
1206
|
bottomColor: "settings.areaBottom"
|
|
1207
|
-
},
|
|
1207
|
+
}, qt = new Set([
|
|
1208
1208
|
"candlestick",
|
|
1209
1209
|
"heikinAshi",
|
|
1210
1210
|
"volumeCandles",
|
|
1211
1211
|
"equivolume"
|
|
1212
1212
|
]);
|
|
1213
|
-
function
|
|
1213
|
+
function Jt(e) {
|
|
1214
1214
|
let t = `series.${e}.`;
|
|
1215
1215
|
return Object.keys(_).filter((e) => e.startsWith(t)).map((n) => {
|
|
1216
|
-
let r = n.slice(t.length), i =
|
|
1217
|
-
return
|
|
1216
|
+
let r = n.slice(t.length), i = Kt[r] ?? "drawingSettings.color";
|
|
1217
|
+
return qt.has(e) && r === "upColor" && (i = "settings.upBody"), qt.has(e) && r === "downColor" && (i = "settings.downBody"), e === "baseline" && r === "upColor" && (i = "settings.aboveBase"), e === "baseline" && r === "downColor" && (i = "settings.belowBase"), T(i, n);
|
|
1218
1218
|
});
|
|
1219
1219
|
}
|
|
1220
|
-
var
|
|
1220
|
+
var Yt = [...new Set([
|
|
1221
1221
|
...Object.keys(_).filter((e) => e.startsWith("series.")),
|
|
1222
1222
|
...[
|
|
1223
|
-
...
|
|
1224
|
-
...
|
|
1225
|
-
...
|
|
1223
|
+
...Bt,
|
|
1224
|
+
...Wt,
|
|
1225
|
+
...Gt
|
|
1226
1226
|
].flatMap((e) => e.rows.flatMap((e) => e.keys)),
|
|
1227
|
-
...[...
|
|
1228
|
-
])], Yt = "/* === 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/* Control tooltips (WidgetTooltip): quick to appear, slide in from the control. */\n.tcw-tooltip {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 60;\n max-width: 240px;\n padding: var(--tcw-space-3) var(--tcw-space-4);\n border-radius: var(--tcw-tooltip-radius);\n background: var(--tcw-tooltip-bg);\n color: var(--tcw-tooltip-fg);\n box-shadow: var(--tcw-tooltip-shadow);\n width: max-content;\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight);\n line-height: 1.35;\n overflow-wrap: anywhere;\n pointer-events: none;\n opacity: 0;\n visibility: hidden;\n transform: translate(var(--tcw-tip-dx, 0), var(--tcw-tip-dy, 0));\n transition:\n opacity 110ms var(--tcw-ease-out),\n transform 110ms var(--tcw-ease-out),\n visibility 0s linear 110ms;\n}\n\n.tcw-tooltip--visible {\n opacity: 1;\n visibility: visible;\n transform: none;\n transition:\n opacity 110ms var(--tcw-ease-out),\n transform 110ms var(--tcw-ease-out),\n visibility 0s;\n}\n\n/* The modal portal: carries the tokens and fonts, but no box of its own. */\n.tcw-root.tcw-portal {\n display: contents;\n}\n\n/* Fullscreen: the root fills the screen; the chart resizes with it. */\n.tcw-root:fullscreen {\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n}\n\n.tcw-root {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n font-family: var(--tcw-font);\n font-feature-settings: var(--tcw-font-features);\n font-size: var(--tcw-font-size);\n line-height: 1.4;\n color: #e6e3dc;\n background: #131416;\n font-variant-numeric: tabular-nums;\n position: relative;\n /* Clipped, not hidden: a box that hides its overflow still scrolls to what the keyboard lands on\n past its edge, and the whole widget slid aside until the next resize. Hidden where clip is unknown. */\n overflow: hidden;\n overflow: clip;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n\n /* --- Dark theme tokens (default) ---\n * Print at night: warm ink on an off-black, never pure white on black, so\n * text doesn't glare. Grey for everything that is normal; colour only where\n * it means something. */\n --tcw-bg: #131416;\n --tcw-bg-surface: #131416;\n --tcw-bg-elevated: #1b1c1f;\n --tcw-bg-overlay: rgba(19, 20, 22, 0.6);\n --tcw-border: #2a2b2f;\n --tcw-border-strong: #3a3b40;\n /* Tooltips are the ink turned over: light on the dark ground. */\n --tcw-tooltip-bg: #e6e3dc;\n --tcw-tooltip-fg: #131416;\n --tcw-text: #e6e3dc;\n --tcw-text-dim: #a9a6a0;\n --tcw-text-muted: #918f8a;\n\n /* Ink blue: links, focus and what you picked. --tcw-accent-ink is the text colour on an accent fill. */\n --tcw-accent: #7d9bff;\n --tcw-accent-hover: #98b0ff;\n --tcw-accent-ink: #131416;\n --tcw-accent-soft: rgba(125, 155, 255, 0.14);\n --tcw-accent-glow: rgba(125, 155, 255, 0.22);\n --tcw-accent-line: rgba(125, 155, 255, 0.55);\n\n --tcw-red: #e2706b;\n --tcw-red-soft: rgba(226, 112, 107, 0.12);\n --tcw-green: #4fae8a;\n --tcw-green-soft: rgba(79, 174, 138, 0.12);\n\n /* The kinds of symbol in the symbol search (stock, futures, index, crypto, forex): hues as far\n * from the accent's blue and the up and down green and red as from each other (0.11 in OKLab at\n * the least, where 0.02 is a step the eye just sees), so a badge is never taken for the chart's\n * symbol, a match or a move; each readable on a tint of itself, on the selected row too. */\n --tcw-kind-1: #4cbedf;\n --tcw-kind-2: #e8a144;\n --tcw-kind-3: #ca8cff;\n --tcw-kind-4: #f387c1;\n --tcw-kind-5: #a5c45d;\n\n --tcw-hover-bg: rgba(230, 227, 220, 0.06);\n --tcw-active-bg: rgba(230, 227, 220, 0.1);\n --tcw-divider: rgba(230, 227, 220, 0.07);\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 /* Spacing: Fibonacci numbers, so each step is near φ times the one before. */\n --tcw-space-1: 2px;\n --tcw-space-2: 3px;\n --tcw-space-3: 5px;\n --tcw-space-4: 8px;\n --tcw-space-5: 13px;\n --tcw-space-6: 21px;\n --tcw-space-7: 34px;\n\n /* The look (UI system): Print's values. The `ui` option sets them inline. */\n --tcw-radius-xs: 1px;\n --tcw-radius-sm: 2px;\n --tcw-radius: 3px;\n --tcw-radius-lg: 5px;\n --tcw-radius-xl: 8px;\n --tcw-control-radius: var(--tcw-radius);\n --tcw-input-radius: var(--tcw-radius);\n --tcw-menu-radius: var(--tcw-radius-lg);\n --tcw-dialog-radius: var(--tcw-radius-xl);\n --tcw-panel-radius: var(--tcw-radius-lg);\n --tcw-tooltip-radius: var(--tcw-radius-sm);\n --tcw-tag-radius: var(--tcw-radius-sm);\n --tcw-toast-radius: var(--tcw-radius-lg);\n --tcw-toolbar-radius: 0px;\n --tcw-sidebar-radius: 0px;\n --tcw-toolbar-h: 42px;\n --tcw-control-h: 26px;\n --tcw-control-h-sm: 20px;\n --tcw-icon: 16px;\n --tcw-sidebar-w: 42px;\n --tcw-menu-item-h: 33px;\n --tcw-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n --tcw-font-size: 13px;\n --tcw-font-size-sm: 11px;\n --tcw-font-size-xs: 10px;\n --tcw-font-size-lg: 15px;\n --tcw-font-size-xl: 18px;\n --tcw-font-size-display: 21px;\n --tcw-weight: 400;\n --tcw-weight-strong: 600;\n --tcw-label-case: uppercase;\n --tcw-label-tracking: 0.06em;\n --tcw-border-w: 1px;\n --tcw-sep-w: 1px;\n --tcw-menu-shadow: 0 0 0 1px var(--tcw-border), var(--tcw-shadow-md);\n --tcw-dialog-shadow: 0 0 0 1px var(--tcw-border), var(--tcw-shadow-lg);\n --tcw-tooltip-shadow: var(--tcw-shadow-sm);\n --tcw-blur: 0px;\n --tcw-surface-opacity: 100%;\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(125, 155, 255, 0.5);\n\n /* Type */\n --tcw-font-mono: 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n /* The faces as drawn: a tag means something else in each face (in IBM Plex, ss01 is a one-storey a).\n * The `ui` option never sets it, so a rule of yours on .tcw-root turns on your face's own. */\n --tcw-font-features: normal;\n}\n\n/* Print by day: ink on paper. */\n.tcw-root[data-tcw-theme='light'] {\n color: #1b1d21;\n background: #fbfaf6;\n\n --tcw-bg: #fbfaf6;\n --tcw-bg-surface: #fbfaf6;\n --tcw-bg-elevated: #ffffff;\n --tcw-bg-overlay: rgba(251, 250, 246, 0.8);\n --tcw-border: #dcd8cf;\n --tcw-border-strong: #c7c2b7;\n --tcw-tooltip-bg: #1b1d21;\n --tcw-tooltip-fg: #fbfaf6;\n --tcw-text: #1b1d21;\n --tcw-text-dim: #4a4e57;\n --tcw-text-muted: #6a6e75;\n\n /* A deeper ink blue: readable as text on paper, white text readable on it. */\n --tcw-accent: #2348c4;\n --tcw-accent-hover: #1b3a9f;\n --tcw-accent-ink: #ffffff;\n --tcw-accent-soft: rgba(35, 72, 196, 0.1);\n --tcw-accent-glow: rgba(35, 72, 196, 0.16);\n --tcw-accent-line: rgba(35, 72, 196, 0.45);\n --tcw-ring: 0 0 0 2px rgba(35, 72, 196, 0.4);\n\n /* Darker semantic colours: used as text on paper. */\n --tcw-red: #b8423f;\n --tcw-red-soft: rgba(184, 66, 63, 0.1);\n --tcw-green: #1f7a5c;\n --tcw-green-soft: rgba(31, 122, 92, 0.1);\n\n /* The same hues, deep enough to read on paper. */\n --tcw-kind-1: #06596e;\n --tcw-kind-2: #855402;\n --tcw-kind-3: #8238b2;\n --tcw-kind-4: #a12673;\n --tcw-kind-5: #415500;\n\n --tcw-hover-bg: rgba(27, 29, 33, 0.05);\n --tcw-active-bg: rgba(27, 29, 33, 0.08);\n --tcw-divider: #e7e3da;\n\n /* Warm shadows, as paper casts. */\n --tcw-shadow-sm: 0 1px 2px rgba(40, 34, 22, 0.06);\n --tcw-shadow-md: 0 4px 12px rgba(40, 34, 22, 0.08), 0 1px 3px rgba(40, 34, 22, 0.05);\n --tcw-shadow-lg: 0 12px 36px rgba(40, 34, 22, 0.13), 0 4px 12px rgba(40, 34, 22, 0.07);\n --tcw-shadow-xl: 0 24px 64px rgba(40, 34, 22, 0.17), 0 12px 24px rgba(40, 34, 22, 0.09);\n}\n\n/* === Toolbar === */\n\n.tcw-toolbar {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 var(--tcw-space-4);\n height: var(--tcw-toolbar-h);\n border-bottom: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n flex-shrink: 0;\n position: relative;\n z-index: 20;\n}\n\n.tcw-toolbar-symbol {\n font-size: var(--tcw-font-size-lg);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n display: inline-flex;\n align-items: center;\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\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-control-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/* With the symbol search switched off, the button only names the symbol. */\n.tcw-toolbar-symbol[aria-disabled=\"true\"] {\n cursor: default;\n}\n\n.tcw-toolbar-symbol[aria-disabled=\"true\"]:hover {\n background: transparent;\n}\n\n/* With everything folded and still no room (a long symbol on a phone), the symbol gives way so\n \"more\" stays on the bar, a step at a time (`data-tcw-squeeze`). First its venue\n (\"HYPERLIQUID:xyz:\") is cut short before anything else shrinks, down to its first letter and an\n ellipsis, a gap keeping it off the ticker. That is 2em: a line's first letter is cut, never\n swapped for the ellipsis, so less shows a letter and a sliver (\"H.\"). The venue's column counts\n only those 2em in the button's smallest width, so the ticker stays whole and the buttons beside it\n give the rest. With room, the symbol shows as it always has. */\n.tcw-toolbar[data-tcw-squeeze='venue'] > .tcw-toolbar-symbol--venue {\n display: inline-grid;\n grid-template-columns: minmax(2em, max-content) auto;\n column-gap: var(--tcw-space-1);\n align-items: center;\n /* Shrinking is shared by width times this: the symbol takes it all until it is at its smallest. */\n flex-shrink: 1000;\n}\n\n.tcw-toolbar[data-tcw-squeeze='venue'] .tcw-toolbar-venue {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Then, with no room even for the ellipsis (a 320 phone in the Capsule look), the venue goes, the\n ticker whole; and last of all, the ticker is cut short. */\n.tcw-toolbar[data-tcw-squeeze='ticker'] .tcw-toolbar-venue,\n.tcw-toolbar[data-tcw-squeeze='cut'] .tcw-toolbar-venue {\n display: none;\n}\n\n.tcw-toolbar[data-tcw-squeeze='cut'] > .tcw-toolbar-symbol {\n min-width: 0;\n}\n\n.tcw-toolbar[data-tcw-squeeze='cut'] .tcw-toolbar-ticker {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-toolbar-sep {\n width: var(--tcw-sep-w);\n /* A button's height over phi: the rule stands as tall as the icons beside it. */\n height: calc(var(--tcw-control-h) / 1.618);\n background: var(--tcw-border);\n flex-shrink: 0;\n margin: 0 var(--tcw-space-3);\n}\n\n.tcw-toolbar-group {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n padding: 0 var(--tcw-space-2);\n}\n\n.tcw-toolbar-spacer {\n flex: 1;\n}\n\n.tcw-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight);\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-control-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-on-bg);\n color: var(--tcw-on-fg);\n font-weight: var(--tcw-weight-strong);\n box-shadow: var(--tcw-on-ring);\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: var(--tcw-control-h);\n height: var(--tcw-control-h);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-control-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 width: var(--tcw-icon);\n height: var(--tcw-icon);\n}\n\n.tcw-badge-count {\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n padding: 1px var(--tcw-space-3);\n border-radius: var(--tcw-tag-radius);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n/* === Dropdown === */\n\n.tcw-dropdown-trigger {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight);\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-control-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: var(--tcw-space-3);\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n z-index: 50;\n width: max-content;\n max-width: min(340px, calc(100vw - 16px));\n padding: var(--tcw-menu-pad);\n max-height: 420px;\n overflow-y: auto;\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\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 min-height: var(--tcw-menu-item-h);\n padding: var(--tcw-space-1) var(--tcw-space-4);\n font-size: var(--tcw-font-size);\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: start;\n border-radius: var(--tcw-menu-item-radius);\n gap: var(--tcw-space-5);\n}\n\n.tcw-dropdown-item:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n/* A menu row led by an icon (chart types): icon then label, not spread apart. */\n.tcw-dropdown-item--icon {\n justify-content: flex-start;\n gap: var(--tcw-space-4);\n}\n\n.tcw-dropdown-item svg,\n.tcw-flyout-item svg {\n flex-shrink: 0;\n}\n\n/* The drawing-group button's icon holder: a plain box for the swapped SVG. */\n.tcw-sidebar-icon {\n display: inline-flex;\n}\n\n.tcw-dropdown-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: var(--tcw-weight-strong);\n}\n\n/* Timeframe menu: pick on the left, pin (star) on the right. */\n.tcw-tf-more {\n padding: 0 5px;\n}\n\n.tcw-tf-more svg {\n display: block;\n}\n\n.tcw-tf-row {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.tcw-tf-row .tcw-dropdown-item {\n flex: 1;\n min-width: 0;\n}\n\n.tcw-tf-star {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n flex-shrink: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-tf-star:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-tf-star.tcw-active {\n color: var(--tcw-accent);\n}\n\n.tcw-tf-star.tcw-active svg {\n fill: currentColor;\n}\n\n.tcw-tf-star:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n.tcw-tf-remove {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n flex-shrink: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-tf-row:hover .tcw-tf-remove,\n.tcw-tf-remove:focus-visible {\n opacity: 1;\n}\n\n/* No hover on touch screens: keep it visible rather than a hidden tap target. */\n@media (hover: none) {\n .tcw-tf-remove { opacity: 1; }\n}\n\n.tcw-tf-remove:hover {\n color: var(--tcw-red);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-tf-remove:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n/* Typed interval, under the list: stays in view while the list scrolls. Out to the menu's edges over\n its padding, and no further: past them, the menu scrolled a few px both ways. */\n.tcw-tf-custom {\n position: sticky;\n bottom: calc(-1 * var(--tcw-menu-pad));\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin: 4px calc(-1 * var(--tcw-menu-pad)) calc(-1 * var(--tcw-menu-pad));\n padding: 6px calc(var(--tcw-menu-pad) + 4px) 8px;\n border-top: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-elevated);\n}\n\n.tcw-tf-custom-hint:empty {\n display: none;\n}\n\n.tcw-tf-custom-hint {\n flex-basis: 100%;\n width: 0;\n min-width: 100%;\n color: var(--tcw-red);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.35;\n}\n\n.tcw-tf-custom-input {\n flex: 1;\n /* Fills the row: its own width would follow the font (16px on touch). */\n width: 0;\n min-width: 0;\n height: 26px;\n padding: 0 8px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text);\n font: inherit;\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n font-size: var(--tcw-font-size-sm);\n}\n\n.tcw-tf-custom-input::placeholder {\n color: var(--tcw-text-dim);\n}\n\n.tcw-tf-custom-input:focus {\n outline: none;\n border-color: var(--tcw-accent);\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\n}\n\n.tcw-tf-custom-input[aria-invalid='true'] {\n border-color: var(--tcw-red);\n box-shadow: 0 0 0 2px var(--tcw-red-soft);\n}\n\n.tcw-tf-custom-add {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n flex-shrink: 0;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n cursor: pointer;\n}\n\n.tcw-tf-custom-add:hover {\n border-color: var(--tcw-accent);\n color: var(--tcw-accent);\n}\n\n.tcw-tf-custom-add:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: 1px;\n}\n\n.tcw-dropdown-label {\n text-transform: var(--tcw-label-case);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n letter-spacing: var(--tcw-label-tracking);\n padding: var(--tcw-space-4) var(--tcw-space-4) var(--tcw-space-2);\n font-weight: var(--tcw-weight-strong);\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: var(--tcw-font-size-xs);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-muted);\n padding: 2px 6px;\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-hover-bg);\n letter-spacing: 0.02em;\n}\n\n/* === Body === */\n\n.tcw-body {\n position: relative;\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/* === History pill (older bars loading at the left edge) === */\n\n.tcw-history-pill {\n position: absolute;\n top: 50%;\n left: 10px;\n z-index: 4;\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 5px 10px 5px 8px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-shadow-sm);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n line-height: 1;\n white-space: nowrap;\n transform: translateY(-50%);\n opacity: 1;\n transition: opacity var(--tcw-dur-normal) var(--tcw-ease-out);\n pointer-events: none;\n}\n\n.tcw-history-pill--hidden {\n opacity: 0;\n}\n\n.tcw-history-pill--error {\n border-color: color-mix(in srgb, var(--tcw-red) 45%, var(--tcw-border));\n color: var(--tcw-red);\n}\n\n.tcw-history-spinner {\n width: 10px;\n height: 10px;\n border: 1.5px solid var(--tcw-accent-soft);\n border-top-color: var(--tcw-accent);\n border-radius: 50%;\n animation: tcw-history-spin 0.8s linear infinite;\n}\n\n.tcw-history-pill--error .tcw-history-spinner {\n border-color: currentColor;\n animation: none;\n}\n\n@keyframes tcw-history-spin {\n to { transform: rotate(360deg); }\n}\n\n/* === Loading overlay (candle skeleton) === */\n\n.tcw-loading-overlay {\n /* Uses a modifier class rather than the `hidden` attribute — the global\n `[hidden] { display: none !important }` rule above would cut the\n opacity transition off before it can play. */\n position: absolute;\n inset: 0;\n z-index: 5;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--tcw-bg);\n opacity: 1;\n transition: opacity var(--tcw-dur-slow) var(--tcw-ease-out);\n pointer-events: none;\n}\n\n.tcw-loading-overlay--hidden {\n opacity: 0;\n}\n\n.tcw-loading-card {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 14px;\n padding: 22px 26px 20px;\n border: 1px solid transparent;\n border-radius: var(--tcw-panel-radius);\n}\n\n/* A slow switch: the previous chart stays readable underneath, dimmed, so the\n click visibly registered without blanking the screen. */\n.tcw-loading-overlay--veil {\n background: color-mix(in srgb, var(--tcw-bg) 55%, transparent);\n}\n\n.tcw-loading-overlay--veil .tcw-loading-card {\n background: var(--tcw-bg-elevated);\n border-color: var(--tcw-border);\n box-shadow: var(--tcw-menu-shadow);\n}\n\n.tcw-loading-candles {\n position: relative;\n display: flex;\n gap: 7px;\n height: 64px;\n}\n\n/* One candle: the element is the wick's column, ::before the wick, ::after the body. */\n.tcw-loading-candle {\n position: relative;\n width: 8px;\n height: 100%;\n color: var(--tcw-red);\n opacity: 0.28;\n animation: tcw-candle-light 1.6s var(--tcw-ease) infinite;\n animation-delay: var(--tcw-delay, 0ms);\n}\n\n.tcw-loading-candle--up { color: var(--tcw-green); }\n\n.tcw-loading-candle::before,\n.tcw-loading-candle::after {\n content: '';\n position: absolute;\n left: 50%;\n background: currentColor;\n transform: translateX(-50%);\n}\n\n.tcw-loading-candle::before {\n top: var(--tcw-wick-top);\n width: 1.5px;\n height: var(--tcw-wick-h);\n}\n\n.tcw-loading-candle::after {\n top: var(--tcw-body-top);\n width: 8px;\n height: var(--tcw-body-h);\n border-radius: 1.5px;\n}\n\n/* Each candle brightens and lifts slightly in turn, left to right. */\n@keyframes tcw-candle-light {\n 0%, 55%, 100% { opacity: 0.28; transform: translateY(0); }\n 20% { opacity: 1; transform: translateY(-2px); }\n}\n\n.tcw-loading-track {\n position: relative;\n width: 100%;\n min-width: 88px;\n height: 2px;\n border-radius: 1px;\n background: var(--tcw-border);\n overflow: hidden;\n}\n\n.tcw-loading-track > span {\n position: absolute;\n inset: 0;\n width: 40%;\n border-radius: 1px;\n background: linear-gradient(90deg, transparent, var(--tcw-accent), transparent);\n animation: tcw-loading-sweep 1.6s var(--tcw-ease) infinite;\n}\n\n@keyframes tcw-loading-sweep {\n from { transform: translateX(-100%); }\n to { transform: translateX(250%); }\n}\n\n/* The status text is announced, not shown — the candles say \"loading\". */\n.tcw-loading-label {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n.tcw-loading-overlay--error .tcw-loading-candles,\n.tcw-loading-overlay--error .tcw-loading-track {\n display: none;\n}\n\n/* A failure is shown: why the chart is empty and that a retry is running. */\n.tcw-loading-overlay--error .tcw-loading-label {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip-path: none;\n white-space: normal;\n max-width: 320px;\n text-align: center;\n color: var(--tcw-red);\n font-size: var(--tcw-font-size);\n}\n\n/* Reduced motion: nothing slides or lifts, but the candles still glow in\n turn and the track breathes, so the wait never looks frozen. */\n@media (prefers-reduced-motion: reduce) {\n .tcw-loading-candle {\n animation: tcw-candle-glow 2.4s ease-in-out infinite;\n animation-delay: var(--tcw-delay, 0ms);\n }\n .tcw-loading-track > span {\n width: 100%;\n background: var(--tcw-accent);\n animation: tcw-loading-breathe 2.4s ease-in-out infinite;\n }\n}\n\n@keyframes tcw-candle-glow {\n 0%, 60%, 100% { opacity: 0.28; }\n 25% { opacity: 0.9; }\n}\n\n@keyframes tcw-loading-breathe {\n 0%, 100% { opacity: 0.15; }\n 50% { opacity: 0.7; }\n}\n\n/* === On-chart indicator legend (WidgetIndicatorLegend) === */\n\n.tcw-ind-legend {\n position: absolute;\n z-index: 3;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1px;\n max-width: calc(100% - 140px);\n pointer-events: none;\n}\n\n.tcw-ind-legend--collapsed > .tcw-ind-legend-row {\n display: none;\n}\n\n.tcw-ind-legend-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n max-width: 100%;\n padding: 0 var(--tcw-space-2);\n border-radius: var(--tcw-radius-sm);\n /* The figures face at the size of the price legend above: one block, columns that line up. */\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n line-height: 19px;\n white-space: nowrap;\n color: var(--tcw-text-dim);\n /* A see-through ground, as under the price legend's rows: lines across the plot run\n behind the text. A host sets --tcw-legend-ground (transparent: none). */\n background: var(--tcw-legend-ground, color-mix(in srgb, var(--tcw-bg) 72%, transparent));\n pointer-events: auto;\n cursor: default;\n /* A narrow pane: the values shrink first, then the row is clipped. */\n overflow: hidden;\n}\n\n/* A pane's indicator: at the top of its pane, where the canvas title was,\n short enough to sit in the pane's header below the divider's grab zone. */\n.tcw-ind-legend-row--pane {\n position: absolute;\n z-index: 3;\n line-height: 15px;\n}\n\n.tcw-ind-legend-row:hover,\n.tcw-ind-legend-row:focus-within {\n background: color-mix(in srgb, var(--tcw-bg-elevated) 90%, transparent);\n box-shadow: 0 0 0 1px var(--tcw-border);\n}\n\n.tcw-ind-legend-name {\n padding: 0;\n border: none;\n background: none;\n font: inherit;\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n cursor: pointer;\n}\n\n.tcw-ind-legend-name:hover {\n color: var(--tcw-accent);\n}\n\n/* A compared symbol's name opens nothing. */\n.tcw-ind-legend-row--compare .tcw-ind-legend-name,\n.tcw-ind-legend-row--compare .tcw-ind-legend-name:hover {\n color: var(--tcw-text);\n cursor: default;\n}\n\n/* The values are one line of text: a narrow chart cuts the line, so the values\n before the cut stay whole and the one it falls in ends in an ellipsis. Values\n shrinking each on its own cut them all at once. */\n.tcw-ind-legend-values {\n display: block;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-ind-legend-values > * + * {\n margin-inline-start: var(--tcw-space-4);\n}\n\n/* Too narrow for a digit and an ellipsis (Bollinger's on a 320 phone, 6 px beside the buttons), the\n values would show a sliver: they hide, keeping their room so they come back with it, and the name\n reads alone. */\n.tcw-ind-legend-values--no-room {\n visibility: hidden;\n}\n\n/* A compare's line colour, as a short stroke of it before the name. */\n.tcw-ind-legend-swatch {\n flex: none;\n align-self: center;\n width: 10px;\n height: 3px;\n margin-inline-end: var(--tcw-space-2);\n border-radius: 1px;\n}\n\n.tcw-ind-legend-row--hidden .tcw-ind-legend-swatch,\n.tcw-ind-legend-row--hidden .tcw-ind-legend-name,\n.tcw-ind-legend-row--hidden .tcw-ind-legend-values {\n opacity: 0.45;\n}\n\n/* Show / settings / remove: on hover or keyboard focus (always on touch). Out of sight, not out of the\n page, so Tab reaches them in a row with nothing else to focus (a compare's) and a screen reader finds\n them; a button focused shows them all. */\n.tcw-ind-legend-actions {\n display: inline-flex;\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n gap: 1px;\n margin-left: -2px;\n}\n\n.tcw-ind-legend-row:hover .tcw-ind-legend-actions,\n.tcw-ind-legend-row:focus-within .tcw-ind-legend-actions {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip-path: none;\n}\n\n@media (hover: none) {\n .tcw-ind-legend-actions {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip-path: none;\n }\n\n /* Finger-sized targets. */\n .tcw-ind-legend-act,\n .tcw-ind-legend-toggle {\n min-width: 28px;\n min-height: 24px;\n }\n}\n\n.tcw-ind-legend-act {\n display: inline-grid;\n place-items: center;\n width: 20px;\n height: 18px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n\n.tcw-ind-legend-act:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ind-legend-act[data-act='remove']:hover {\n color: var(--tcw-red);\n}\n\n.tcw-ind-legend-toggle {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n margin-top: 1px;\n padding: 1px 5px;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n cursor: pointer;\n pointer-events: auto;\n}\n\n.tcw-ind-legend-toggle[hidden] {\n display: none;\n}\n\n.tcw-ind-legend-toggle:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ind-legend-name:focus-visible,\n.tcw-ind-legend-act:focus-visible,\n.tcw-ind-legend-toggle:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n/* === Sidebar === */\n\n.tcw-sidebar {\n width: var(--tcw-sidebar-w);\n flex-shrink: 0;\n background: var(--tcw-bg-surface);\n border-inline-end: var(--tcw-border-w) solid var(--tcw-border);\n display: flex;\n flex-direction: column;\n align-items: center;\n /* The buttons' own 1px margins at its ends make up the rest of the gap: as tall as its tools,\n 768 px high in the Print look, it doesn't scroll by those 2 px. */\n padding: calc(var(--tcw-space-3) - 1px) 0;\n /* On a short screen the tools scroll; the menus sit outside it. */\n overflow-x: hidden;\n overflow-y: auto;\n scrollbar-width: none;\n}\n.tcw-sidebar::-webkit-scrollbar {\n display: none;\n}\n.tcw-sidebar > * {\n flex-shrink: 0;\n}\n\n.tcw-tool-group-wrap {\n position: relative;\n}\n\n.tcw-sidebar-btn {\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\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-control-radius);\n}\n\n.tcw-sidebar-btn svg {\n width: var(--tcw-icon);\n height: var(--tcw-icon);\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-on-icon-fg);\n background: var(--tcw-on-icon-bg);\n box-shadow: var(--tcw-on-icon-ring);\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/* The drawing tools' sections: always a hairline (it groups the tools), even in\n looks that drop the rules between toolbar groups. */\n.tcw-sidebar-divider {\n width: 20px;\n height: max(1px, var(--tcw-sep-w));\n background: var(--tcw-divider);\n margin: 5px 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 margin-inline-start: 6px;\n overflow-y: auto;\n overscroll-behavior: contain;\n min-width: 180px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n z-index: 30;\n padding: var(--tcw-menu-pad);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n animation: tcw-slide-right var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n/* Spans the gap to the toolbar button: crossing it stays inside the menu. */\n.tcw-flyout::before {\n content: '';\n position: absolute;\n top: -1px;\n bottom: -1px;\n right: 100%;\n width: 8px;\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: var(--tcw-label-case);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n letter-spacing: var(--tcw-label-tracking);\n padding: var(--tcw-space-3) var(--tcw-space-4) var(--tcw-space-2);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-flyout-hint {\n padding: var(--tcw-space-3) var(--tcw-space-4) var(--tcw-space-1);\n border-top: 1px solid var(--tcw-border);\n margin-top: var(--tcw-space-2);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n\n.tcw-flyout-item {\n min-height: var(--tcw-menu-item-h);\n padding: var(--tcw-space-1) var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n color: var(--tcw-text-dim);\n cursor: pointer;\n width: 100%;\n display: flex;\n align-items: center;\n gap: 10px;\n border: none;\n background: transparent;\n text-align: start;\n font-family: inherit;\n border-radius: var(--tcw-menu-item-radius);\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.tcw-flyout-item:focus-visible {\n outline: none;\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n box-shadow: inset 0 0 0 1px var(--tcw-accent);\n}\n\n.tcw-flyout-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: var(--tcw-weight-strong);\n}\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(12, 12, 10, 0.42);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\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/* A text drawing's words typed in place, over its box on the chart; under any dialog. */\n.tcw-inline-text {\n position: fixed;\n inset: 0;\n z-index: 90;\n pointer-events: none;\n}\n.tcw-inline-text-input {\n position: absolute;\n box-sizing: border-box;\n margin: 0;\n border: 1px solid var(--tcw-accent);\n border-radius: var(--tcw-radius-xs);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n outline: none;\n overflow: hidden;\n resize: none;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n pointer-events: auto;\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: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-dialog-radius);\n width: 520px;\n max-width: 92vw;\n max-height: 82vh;\n max-height: 82dvh;\n display: flex;\n flex-direction: column;\n box-shadow: var(--tcw-dialog-shadow);\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: var(--tcw-space-5) var(--tcw-space-6);\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n/* A dialog's title is phi times its text (21 to 13). */\n.tcw-modal-header h3 {\n font-size: var(--tcw-font-size-display);\n font-weight: var(--tcw-weight-strong);\n margin: 0;\n color: var(--tcw-text);\n letter-spacing: -0.015em;\n}\n\n.tcw-modal-close {\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\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-control-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 /* Four tabs in a long language on a phone: they wrap rather than clip. No overflow here: in the\n dialog's column it would let a long body squash the tabs, and clip the underline of the active one. */\n flex-wrap: wrap;\n flex-shrink: 0;\n gap: var(--tcw-space-2);\n padding: var(--tcw-tabs-pad-block) var(--tcw-space-6);\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-modal-tab {\n flex-shrink: 0;\n white-space: nowrap;\n height: var(--tcw-tab-h);\n padding: var(--tcw-tab-pad);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight);\n color: var(--tcw-text-muted);\n border: none;\n background: transparent;\n cursor: pointer;\n border-bottom: var(--tcw-tab-line) solid transparent;\n border-radius: var(--tcw-tab-radius);\n margin-bottom: calc(var(--tcw-tab-line) / -2);\n transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n font-family: inherit;\n letter-spacing: -0.005em;\n}\n\n.tcw-modal-tab:hover {\n color: var(--tcw-text-dim);\n background: var(--tcw-tab-hover);\n}\n\n.tcw-modal-tab.tcw-active {\n color: var(--tcw-tab-on-fg);\n background: var(--tcw-tab-on-bg);\n border-bottom-color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-modal-body {\n padding: var(--tcw-space-6);\n overflow-y: auto;\n flex: 1;\n}\n\n.tcw-settings-section {\n margin-bottom: var(--tcw-space-6);\n}\n\n.tcw-settings-section:last-child {\n margin-bottom: 0;\n}\n\n.tcw-settings-section-title {\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n color: var(--tcw-text-muted);\n margin-bottom: var(--tcw-space-4);\n}\n\n.tcw-settings-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--tcw-space-4) 0;\n}\n\n.tcw-settings-row + .tcw-settings-row {\n border-top: 1px solid var(--tcw-divider);\n}\n\n/* A number field's hint goes on a line of its own, under the field. */\n.tcw-settings-row--number {\n flex-wrap: wrap;\n}\n\n.tcw-settings-hint {\n flex-basis: 100%;\n padding-top: var(--tcw-space-2);\n color: var(--tcw-red);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.35;\n text-align: end;\n}\n\n/* Empty, it takes no room but stays rendered: a live region that appears with its text is often not read out. */\n.tcw-settings-hint:empty {\n padding-top: 0;\n}\n\n.tcw-settings-label {\n font-size: var(--tcw-font-size);\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: var(--tcw-radius-xs);\n}\n\n.tcw-color-hex {\n font-size: var(--tcw-font-size-xs);\n /* Hex letters vary in width in a sans face: a monospaced one keeps the codes one width. */\n font-family: ui-monospace, 'Cascadia Mono', 'SF Mono', Menlo, Consolas, monospace;\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-muted);\n min-width: 64px;\n letter-spacing: 0.01em;\n}\n\n/* A colour left to the part itself: the swatch shows where the picker starts, faded. */\n.tcw-color-auto input[type='color'] {\n opacity: 0.45;\n border-style: dashed;\n}\n\n.tcw-color-auto .tcw-color-hex {\n font-family: inherit;\n font-style: italic;\n}\n\n.tcw-color-auto-btn {\n height: 24px;\n padding: 0 8px;\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n background: transparent;\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-color-auto-btn:hover,\n.tcw-color-auto-btn:focus-visible {\n color: var(--tcw-text);\n border-color: var(--tcw-accent);\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: var(--tcw-font-size-sm);\n font-family: inherit;\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-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: var(--tcw-space-5) var(--tcw-space-6);\n border-top: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n border-radius: 0 0 var(--tcw-dialog-radius) var(--tcw-dialog-radius);\n}\n\n.tcw-reset-link {\n font-size: var(--tcw-font-size-sm);\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: var(--tcw-space-4) var(--tcw-space-6);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n background: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n border: none;\n border-radius: var(--tcw-control-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}\n\n.tcw-done-btn:hover {\n background: var(--tcw-accent-hover);\n}\n\n.tcw-done-btn:disabled { opacity: 0.45; cursor: not-allowed; }\n\n.tcw-done-btn:active {\n transform: translateY(0.5px);\n}\n\n/* === Status Bar === */\n\n.tcw-statusbar {\n /* Above sidebar buttons that overflow a short chart; menus (z 30+) stay on top. */\n position: relative;\n z-index: 1;\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: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n flex-shrink: 0;\n}\n\n/* The bar holds the keyboard when a refit hides every button it could go to. */\n.tcw-statusbar:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n.tcw-status-right {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-inline-start: auto;\n /* Never narrower than what it holds, so the clock at its end stays whole: the range presets give way instead. */\n flex: none;\n white-space: nowrap;\n}\n\n/* Range presets + go to date, bottom left. The bar takes the room the rest leaves and\n clips what's past it; WidgetStatusBar.fit folds that under \"more\". Logical margins,\n so right to left it keeps its gap before the right group. */\n.tcw-range-bar {\n display: flex;\n align-items: center;\n gap: 1px;\n margin-block: -4px;\n margin-inline: -8px 12px;\n min-width: 0;\n overflow: hidden;\n}\n\n/* A narrow widget (a phone, a narrow column, a grid's cell): the range presets close up. */\n.tcw-root[data-tcw-narrow] .tcw-range-btn[data-range] {\n padding: 4px 5px;\n}\n\n/* What the bar has folded, and \"more\" while nothing is. */\n.tcw-statusbar [data-tcw-folded],\n.tcw-statusbar:not(.tcw-statusbar--folded) .tcw-range-more {\n display: none;\n}\n\n.tcw-range-btn {\n flex-shrink: 0;\n padding: 4px 7px;\n font: inherit;\n font-weight: var(--tcw-weight-strong);\n letter-spacing: 0.02em;\n color: var(--tcw-text-muted);\n background: transparent;\n border: none;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-range-btn:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-range-btn:active {\n color: var(--tcw-accent);\n}\n\n.tcw-range-btn:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n.tcw-range-goto,\n.tcw-range-more {\n display: inline-grid;\n place-items: center;\n padding: 4px 6px;\n}\n\n.tcw-range-goto {\n margin-inline-start: 6px;\n}\n\n.tcw-range-goto svg,\n.tcw-range-more svg {\n display: block;\n}\n\n.tcw-status-indicator {\n display: flex;\n align-items: center;\n gap: 7px;\n font-weight: var(--tcw-weight);\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(31, 168, 116, 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 3;\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(232, 80, 91, 0.2);\n}\n\n/* === Watchlist === */\n\n.tcw-watchlist {\n width: 220px;\n flex-shrink: 0;\n background: var(--tcw-bg-surface);\n border-inline-start: 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 position: relative;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 8px 6px 8px;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n/* The shown list's name: opens the lists menu. */\n.tcw-watchlist-name {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 6px;\n height: var(--tcw-control-h-sm);\n padding: 0 6px;\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n text-align: start;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n}\n.tcw-watchlist-name::after {\n content: '';\n flex: none;\n width: 0;\n height: 0;\n margin-inline-start: auto;\n border: 4px solid transparent;\n border-top-color: currentColor;\n border-bottom-width: 0;\n opacity: 0.7;\n}\n\n.tcw-watchlist-add {\n flex: none;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-lg);\n line-height: 1;\n cursor: pointer;\n}\n\n.tcw-watchlist-name:hover,\n.tcw-watchlist-add:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n.tcw-watchlist-name:focus-visible,\n.tcw-watchlist-add:focus-visible,\n.tcw-watchlist-input:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* The lists menu, under the header. */\n.tcw-watchlist-menu {\n top: calc(100% - 2px);\n left: 6px;\n right: 6px;\n margin-top: 0;\n}\n.tcw-watchlist-count {\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n font-size: var(--tcw-font-size-xs);\n}\n.tcw-watchlist-menu .tcw-danger {\n color: var(--tcw-red);\n}\n\n/* Naming a list in place. */\n.tcw-watchlist-input {\n flex: 1;\n min-width: 0;\n height: var(--tcw-control-h-sm);\n padding: 0 8px;\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n}\n\n.tcw-watchlist-empty {\n padding: 16px 14px;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.5;\n}\n\n/*\n * A row's remove button shows on hover or focus, in a column of its own after\n * the numbers: over them, it hid the price and the change of the row the\n * keyboard was on.\n */\n.tcw-watchlist-remove {\n display: grid;\n place-items: center;\n width: var(--tcw-watchlist-remove);\n height: var(--tcw-watchlist-remove);\n border: 0;\n border-radius: var(--tcw-radius-sm);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size);\n line-height: 1;\n opacity: 0;\n cursor: pointer;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-watchlist-row:hover .tcw-watchlist-remove,\n.tcw-watchlist-row:focus-within .tcw-watchlist-remove {\n opacity: 1;\n}\n.tcw-watchlist-remove:hover {\n color: var(--tcw-red);\n}\n.tcw-watchlist-row.tcw-watchlist-dragging {\n opacity: 0.45;\n}\n\n.tcw-watchlist-list {\n flex: 1;\n overflow-y: auto;\n padding: 4px 0;\n}\n\n.tcw-watchlist-row {\n --tcw-watchlist-remove: 20px;\n position: relative;\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-inline-start: 2px solid transparent;\n outline: none;\n}\n\n.tcw-watchlist-row.tcw-watchlist-removable {\n grid-template-columns: 1fr auto auto var(--tcw-watchlist-remove);\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-inline-start-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-row.tcw-watchlist-active {\n background: var(--tcw-accent-soft);\n border-inline-start-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-symbol {\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n font-weight: var(--tcw-weight);\n}\n\n.tcw-watchlist-change {\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n font-weight: var(--tcw-weight);\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/* === Toast === */\n\n.tcw-toast-icon {\n display: inline-flex;\n vertical-align: -2px;\n margin-inline-end: 7px;\n color: var(--tcw-accent);\n}\n.tcw-toast-error .tcw-toast-icon { color: var(--tcw-red); }\n\n/* Over an open dialog: above its backdrop, at the window's foot. */\n.tcw-toast.tcw-toast-over {\n position: fixed;\n z-index: 120;\n}\n\n.tcw-toast {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translate(-50%, 12px);\n z-index: 40;\n padding: var(--tcw-space-4) var(--tcw-space-5);\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-toast-radius);\n box-shadow: var(--tcw-menu-shadow);\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight);\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 bar ===\n * A transport over the foot of the main pane: step back / play / step\n * forward, where the replay is (its date and a track with the played part\n * filled), its pace (speed, step), and the ways out (pick another bar, back\n * to now). Only --tcw-* tokens; its sizes come from the look's own ladder.\n * The widget sets where it sits (--tcw-replay-foot, --tcw-replay-plot-*)\n * from the main pane, and the tier (data-fit) from the room it has.\n */\n\n/* Picking the replay start: the bars right of the pointer would be hidden. */\n.tcw-replay-shade {\n position: absolute;\n z-index: 4;\n pointer-events: none;\n background: color-mix(in srgb, var(--tcw-bg) 62%, transparent);\n border-inline-start: 1.5px dashed var(--tcw-accent);\n}\n\n.tcw-replay-bar {\n /* Buttons are the look's controls; Play two small steps above them. */\n --tcw-replay-btn: var(--tcw-control-h);\n --tcw-replay-play: calc(var(--tcw-control-h) + 2 * var(--tcw-space-2));\n --tcw-replay-track-w: calc(var(--tcw-space-7) * 6);\n --tcw-replay-track-min: calc(var(--tcw-space-7) * 3);\n --tcw-replay-rail: var(--tcw-space-2);\n --tcw-replay-head-w: var(--tcw-space-2);\n --tcw-replay-head-h: var(--tcw-space-5);\n position: absolute;\n /* On the main pane's foot (over the volume, clear of the bottom panes), above the time axis without them. */\n bottom: calc(var(--tcw-replay-foot, 30px) + var(--tcw-space-4));\n inset-inline: var(--tcw-replay-plot-start, 0px) var(--tcw-replay-plot-end, 0px);\n /* Centred on the plot by its margins: an entrance on `transform` would undo a translate. */\n margin-inline: auto;\n box-sizing: border-box;\n width: max-content;\n max-width: calc(100% - var(--tcw-replay-plot-start, 0px) - var(--tcw-replay-plot-end, 0px) - 2 * var(--tcw-space-4));\n z-index: 25;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n padding: var(--tcw-space-3);\n background: var(--tcw-bg-elevated);\n background: color-mix(in srgb, var(--tcw-bg-elevated) var(--tcw-surface-opacity, 100%), transparent);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n /* The look's menu shadow carries its hairline (Print, Terminal, Capsule): no border of its own on top. */\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.2;\n animation: tcw-sel-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n.tcw-replay-group,\n.tcw-replay-slot {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-2);\n min-width: 0;\n}\n.tcw-replay-bar [hidden] { display: none !important; }\n/* The step field on a single step: nothing there, no gap for it. */\n.tcw-replay-slot:empty { display: none; }\n\n/* Hairlines between the groups where the look draws separators (Print, Terminal); a gap in the others. */\n.tcw-replay-sep {\n flex: none;\n align-self: stretch;\n width: var(--tcw-sep-w);\n margin-block: var(--tcw-space-2);\n background: var(--tcw-divider);\n}\n\n/* --- Buttons --- */\n.tcw-replay-btn {\n flex: none;\n display: inline-grid;\n place-items: center;\n inline-size: var(--tcw-replay-btn);\n block-size: var(--tcw-replay-btn);\n padding: 0;\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n cursor: pointer;\n transition:\n background-color 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}\n.tcw-replay-btn > svg,\n.tcw-replay-text-btn svg { width: var(--tcw-icon); height: var(--tcw-icon); flex: none; }\n.tcw-replay-btn:hover { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-replay-btn:active { background: var(--tcw-active-bg); transform: scale(0.94); }\n.tcw-replay-btn:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n\n/* Play: the one filled control. Its focus ring stands off the fill, or it would vanish into it. */\n.tcw-replay-btn.tcw-replay-play {\n inline-size: var(--tcw-replay-play);\n block-size: var(--tcw-replay-play);\n background: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n}\n.tcw-replay-btn.tcw-replay-play:hover { background: var(--tcw-accent-hover); color: var(--tcw-accent-ink); }\n.tcw-replay-btn.tcw-replay-play:focus-visible {\n box-shadow: 0 0 0 var(--tcw-space-1) var(--tcw-bg-elevated), 0 0 0 calc(2 * var(--tcw-space-1)) var(--tcw-accent-line);\n}\n\n.tcw-replay-btn:disabled,\n.tcw-replay-text-btn:disabled,\n.tcw-replay-scrubber:disabled,\n.tcw-replay-speed:disabled { opacity: 0.4; cursor: default; transform: none; }\n/* Nothing left to play: a muted fill, not a faded accent that reads as pressed. */\n.tcw-replay-btn.tcw-replay-play:disabled { background: var(--tcw-active-bg); color: var(--tcw-text-muted); opacity: 1; }\n\n/* --- Where the replay is --- */\n.tcw-replay-timeline {\n flex: 1 1 auto;\n gap: var(--tcw-space-4);\n}\n.tcw-replay-time {\n flex: none;\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text);\n white-space: nowrap;\n}\n.tcw-replay-group[aria-busy='true'] .tcw-replay-time,\n.tcw-replay-group[aria-busy='true'] .tcw-replay-hint { color: var(--tcw-text-muted); }\n\n.tcw-root input[type='range'].tcw-replay-scrubber {\n --tcw-replay-rest: var(--tcw-border-strong);\n flex: 1 1 var(--tcw-replay-track-w);\n min-inline-size: var(--tcw-replay-track-min);\n inline-size: var(--tcw-replay-track-w);\n block-size: var(--tcw-replay-btn);\n margin: 0;\n padding: 0;\n appearance: none;\n -webkit-appearance: none;\n background: transparent;\n border: 0;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n}\n/* Measured at its least: the bar's width with no slack in the track. */\n.tcw-replay-bar[data-measure] { max-width: none; animation: none; }\n.tcw-replay-bar[data-measure] input[type='range'].tcw-replay-scrubber { inline-size: var(--tcw-replay-track-min); flex: none; }\n.tcw-root input[type='range'].tcw-replay-scrubber:hover { --tcw-replay-rest: var(--tcw-text-muted); }\n.tcw-root input[type='range'].tcw-replay-scrubber:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n/* The played part in the accent, the rest a rail; Firefox fills it itself. */\n.tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-runnable-track {\n block-size: var(--tcw-replay-rail);\n border-radius: var(--tcw-radius-xs);\n background: linear-gradient(to right, var(--tcw-accent) 0 var(--tcw-replay-done, 0%), var(--tcw-replay-rest) var(--tcw-replay-done, 0%) 100%);\n}\n.tcw-root input[type='range'].tcw-replay-scrubber::-moz-range-track { block-size: var(--tcw-replay-rail); border-radius: var(--tcw-radius-xs); background: var(--tcw-replay-rest); }\n.tcw-root input[type='range'].tcw-replay-scrubber::-moz-range-progress { block-size: var(--tcw-replay-rail); border-radius: var(--tcw-radius-xs); background: var(--tcw-accent); }\n/* A playhead, as the chart marks the replay's cut: a short upright in ink, rounded as the look rounds. */\n.tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n inline-size: var(--tcw-replay-head-w);\n block-size: var(--tcw-replay-head-h);\n margin-top: calc((var(--tcw-replay-rail) - var(--tcw-replay-head-h)) / 2);\n border: 0;\n border-radius: var(--tcw-radius-xs);\n background: var(--tcw-text);\n box-shadow: 0 0 0 var(--tcw-space-1) var(--tcw-bg-elevated);\n transition: transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-root input[type='range'].tcw-replay-scrubber:hover::-webkit-slider-thumb,\n.tcw-root input[type='range'].tcw-replay-scrubber:active::-webkit-slider-thumb { transform: scaleY(1.25); }\n.tcw-root input[type='range'].tcw-replay-scrubber::-moz-range-thumb {\n inline-size: var(--tcw-replay-head-w);\n block-size: var(--tcw-replay-head-h);\n border: 0;\n border-radius: var(--tcw-radius-xs);\n background: var(--tcw-text);\n box-shadow: 0 0 0 var(--tcw-space-1) var(--tcw-bg-elevated);\n}\n\n/* --- Pace: speed and step, each a labelled field --- */\n.tcw-replay-chip {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n}\n.tcw-replay-chip-label {\n font-size: var(--tcw-font-size-xs);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n color: var(--tcw-text-muted);\n white-space: nowrap;\n}\n.tcw-root .tcw-replay-chip select.tcw-replay-speed {\n block-size: var(--tcw-replay-btn);\n padding-block: 0;\n padding-inline-start: var(--tcw-space-4);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n}\n\n/* --- The ways out, and picking --- */\n.tcw-replay-text-btn {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n block-size: var(--tcw-replay-btn);\n padding-inline: var(--tcw-space-4);\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-weight: var(--tcw-weight);\n white-space: nowrap;\n cursor: pointer;\n transition: background-color var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease), transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-replay-text-btn:hover { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-replay-text-btn:active { background: var(--tcw-active-bg); transform: scale(0.97); }\n.tcw-replay-text-btn:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n/* Random bar: outlined, the one thing to press while picking. */\n.tcw-replay-text-btn.tcw-replay-ghost { border: var(--tcw-border-w) solid var(--tcw-border-strong); color: var(--tcw-text); }\n/* The close glyph is the phone's: on wider bars the words say it. */\n.tcw-replay-close-icon { display: none; }\n/* At the last bar, the way back to now is the next thing to do. */\n.tcw-replay-bar--ended .tcw-replay-realtime { background: var(--tcw-accent); color: var(--tcw-accent-ink); }\n.tcw-replay-bar--ended .tcw-replay-realtime:hover { background: var(--tcw-accent-hover); color: var(--tcw-accent-ink); }\n\n.tcw-replay-hint {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n padding-inline: var(--tcw-space-3);\n color: var(--tcw-text-dim);\n white-space: nowrap;\n}\n.tcw-replay-hint > svg { flex: none; width: var(--tcw-icon); height: var(--tcw-icon); color: var(--tcw-accent); }\n\n/* --- Narrower: the fields lose their captions (they stay their names) --- */\n.tcw-replay-bar:is([data-fit='compact'], [data-fit='stack']) .tcw-replay-chip-label {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* --- A phone, or a narrow chart: two rows across the plot, where the replay is on top --- */\n.tcw-replay-bar[data-fit='stack'] {\n /* Touch targets: 40 px (44 for Play) at least, as the toolbar's on a phone. */\n --tcw-replay-btn: max(40px, var(--tcw-control-h));\n --tcw-replay-play: max(44px, calc(var(--tcw-control-h) + 2 * var(--tcw-space-2)));\n inset-inline: var(--tcw-space-4);\n width: auto;\n max-width: none;\n margin-inline: 0;\n flex-wrap: wrap;\n gap: var(--tcw-space-2);\n}\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-sep { display: none; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-timeline {\n order: -2;\n /* The first row, beside the close button; the rest wraps below. */\n flex: 1 1 calc(100% - var(--tcw-replay-btn) - 2 * var(--tcw-space-2));\n box-sizing: border-box;\n padding-inline-start: var(--tcw-space-3);\n}\n.tcw-replay-bar[data-fit='stack'] input[type='range'].tcw-replay-scrubber { block-size: var(--tcw-menu-item-h); min-inline-size: 0; }\n/* Back to realtime closes the bar from the first row, a glyph touch users know. */\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-exits { display: contents; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-realtime { order: -1; inline-size: var(--tcw-replay-btn); padding: 0; justify-content: center; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-realtime .tcw-replay-text { display: none; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-close-icon { display: inline-flex; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-transport { flex: 1 0 auto; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-hint { white-space: normal; flex: 1 0 100%; padding-block: var(--tcw-space-2); }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-picking { display: contents; }\n\n/* While the bar holds the plot's foot, what lives there makes room: the toasts and the phone's drawing button. */\n.tcw-root[data-tcw-replay] > .tcw-toast:not(.tcw-toast-over) {\n bottom: calc(var(--tcw-replay-lift, 0px) + var(--tcw-space-4));\n}\n.tcw-root[data-tcw-narrow][data-tcw-replay] > .tcw-body > .tcw-sidebar-fab {\n bottom: calc(var(--tcw-replay-lift, 0px) + var(--tcw-space-4));\n}\n\n@media (forced-colors: active) {\n .tcw-replay-bar { border: 1px solid CanvasText; }\n .tcw-replay-btn.tcw-replay-play { border: 1px solid ButtonText; }\n .tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-runnable-track { background: GrayText; }\n .tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-thumb { background: Highlight; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tcw-replay-bar { animation: none; }\n .tcw-replay-btn,\n .tcw-replay-text-btn,\n .tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-thumb { transition: none; }\n}\n\n/* === Responsive === */\n\n@media (max-width: 768px) {\n .tcw-toolbar {\n padding: 0 4px;\n height: max(44px, var(--tcw-toolbar-h)); /* Apple HIG minimum touch target */\n }\n .tcw-toolbar-sep {\n display: none;\n }\n .tcw-btn,\n .tcw-dropdown-trigger {\n height: max(40px, var(--tcw-control-h)); /* fatter tap target */\n padding: 0 12px;\n font-size: var(--tcw-font-size);\n }\n .tcw-btn-icon {\n width: max(40px, var(--tcw-control-h));\n height: max(40px, var(--tcw-control-h));\n }\n .tcw-sidebar {\n width: max(44px, var(--tcw-sidebar-w));\n }\n .tcw-sidebar-btn {\n width: max(40px, var(--tcw-control-h));\n height: max(40px, var(--tcw-control-h));\n }\n .tcw-modal {\n width: 94vw;\n border-radius: var(--tcw-dialog-radius);\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 top: auto;\n /* Above the on-screen keyboard (the widget sets it from visualViewport). */\n bottom: var(--tcw-keyboard-inset, 0px);\n padding-left: env(safe-area-inset-left, 0px);\n padding-right: env(safe-area-inset-right, 0px);\n left: 0;\n right: 0;\n transform: none;\n /* The border and the safe-area padding inside the screen's width. */\n box-sizing: border-box;\n width: 100vw;\n max-width: 100vw;\n /* Less the on-screen keyboard: a sheet's top never goes above the screen. */\n max-height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n max-height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 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 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 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 padding-bottom: max(14px, env(safe-area-inset-bottom));\n }\n\n /* Larger tap targets inside sheets: taller, not more padding, so a tab's text stays inside its chip. */\n .tcw-modal-tab {\n min-height: 40px;\n padding-inline: 16px;\n }\n .tcw-dropdown-item {\n padding: 12px 12px;\n font-size: var(--tcw-font-size-lg);\n }\n}\n\n/* === Price alerts panel === */\n\n.tcw-alerts-panel {\n position: absolute;\n top: var(--tcw-panel-top);\n inset-inline-end: 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: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-weight-strong);\n font-size: var(--tcw-font-size);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent-ink);\n background: var(--tcw-accent);\n border: none;\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n font-variant-numeric: tabular-nums;\n}\n.tcw-alerts-row-note {\n margin-top: 2px;\n font-size: var(--tcw-font-size-xs);\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n padding: 2px 5px;\n border-radius: var(--tcw-tag-radius);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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 max-height: 40dvh;\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: var(--tcw-panel-top);\n inset-inline-end: 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-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm); 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: var(--tcw-font-size-sm);\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: var(--tcw-weight-strong); }\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\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/* === 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/*\n * Placing a bracket: a strip at the foot of the chart, over its time axis\n * (30 px, the chart's TIME_AXIS_HEIGHT), clear of the tags along its top; its\n * name and Place in the side's colour. Centred by its margins, not a\n * transform: the entrance animation ends on `transform: none`, which left it\n * starting at the middle.\n */\n.tcw-bracket-bar {\n position: absolute;\n bottom: calc(30px + var(--tcw-space-5));\n inset-inline: 0;\n margin-inline: auto;\n box-sizing: border-box;\n width: max-content;\n max-width: calc(100% - 2 * var(--tcw-space-4));\n z-index: 45;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n padding-block: var(--tcw-space-3);\n padding-inline: var(--tcw-space-5) var(--tcw-space-3);\n background: var(--tcw-bg-elevated);\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-bracket-bar[data-side='buy'] { --tcw-side: var(--tcw-green); }\n.tcw-bracket-bar[data-side='sell'] { --tcw-side: var(--tcw-red); }\n/* The name gives way first: in German or Russian it would push Place off a phone. */\n.tcw-bracket-label {\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-side, var(--tcw-text));\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n/* The replay bar has the chart's foot while it shows: the bracket's goes to the top. */\n.tcw-root[data-tcw-replay] .tcw-bracket-bar {\n top: var(--tcw-space-4);\n bottom: auto;\n}\n.tcw-bracket-hint {\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.tcw-bracket-cancel,\n.tcw-bracket-confirm {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-control-h);\n padding-inline: var(--tcw-space-5);\n border-radius: var(--tcw-control-radius);\n font: inherit;\n font-size: var(--tcw-font-size);\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-bracket-cancel {\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n background: transparent;\n color: var(--tcw-text);\n}\n.tcw-bracket-cancel:hover { background: var(--tcw-hover-bg); }\n/* The ground's own colour reads on the side's: dark on the dark theme's light greens, paper on the light theme's deep ones. */\n.tcw-bracket-confirm {\n border: none;\n background: var(--tcw-side, var(--tcw-accent));\n color: var(--tcw-bg);\n font-weight: var(--tcw-weight-strong);\n}\n.tcw-bracket-confirm:hover { background: color-mix(in srgb, var(--tcw-side, var(--tcw-accent)) 86%, var(--tcw-text)); }\n.tcw-bracket-cancel:focus-visible,\n.tcw-bracket-confirm:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n@media (max-width: 640px) {\n .tcw-bracket-bar {\n inset-inline: var(--tcw-space-4);\n width: auto;\n max-width: none;\n }\n .tcw-bracket-hint { display: none; }\n .tcw-bracket-label { margin-inline-end: auto; }\n .tcw-bracket-cancel,\n .tcw-bracket-confirm { height: 34px; }\n}\n\n@media (forced-colors: active) {\n .tcw-bracket-bar { border: 1px solid CanvasText; }\n .tcw-bracket-confirm { border: 1px solid ButtonText; }\n .tcw-bracket-cancel:focus-visible,\n .tcw-bracket-confirm:focus-visible { outline: 2px solid Highlight; }\n}\n\n/* === Drawing style + templates popover === */\n\n.tcw-style-panel {\n position: absolute;\n bottom: 12px;\n inset-inline-start: var(--tcw-panel-left);\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-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n}\n.tcw-style-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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-control-radius);\n color: var(--tcw-text-dim);\n cursor: pointer;\n font-size: var(--tcw-font-size-xs);\n}\n.tcw-style-width span { width: 16px; background: currentColor; border-radius: var(--tcw-radius-xs); }\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent-ink);\n background: var(--tcw-accent);\n border: none;\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-xs); 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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n background: transparent;\n border: none;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n text-align: start;\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: end;\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-dim);\n}\n\n/* === Indicator settings dialog === */\n\n/* Narrow on a desktop; on a phone a sheet across the screen like every dialog. */\n@media (min-width: 641px) {\n .tcw-modal-narrow {\n max-width: 360px;\n }\n}\n.tcw-indi-input {\n width: 110px;\n height: 30px;\n padding: 0 8px;\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\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-select {\n width: 150px;\n padding-right: 4px;\n cursor: pointer;\n}\n/* A level: its value and a remove button. */\n.tcw-indi-level {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n.tcw-indi-remove {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-indi-remove:hover {\n color: var(--tcw-red);\n background: var(--tcw-hover-bg);\n}\n.tcw-indi-remove:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n.tcw-indi-add {\n margin-top: 8px;\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: var(--tcw-panel-top);\n inset-inline-end: 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-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-weight-strong);\n font-size: var(--tcw-font-size);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n/* A compare: its colour and symbol, then how it is compared, taking the room left before its button. */\n.tcw-tree-compare {\n justify-content: flex-start;\n}\n.tcw-tree-compare .tcw-tree-name {\n flex: 0 1 auto;\n}\n.tcw-tree-compare .tcw-tree-del {\n flex: none;\n margin-inline-start: auto;\n}\n.tcw-tree-way {\n flex: 1 1 0;\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-size: var(--tcw-font-size-xs);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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/* A drawing row's grip: dragged, it moves the drawing up or down the order. */\n.tcw-tree-btn.tcw-tree-grip {\n flex: none;\n cursor: grab;\n touch-action: none;\n}\n.tcw-tree-row:not(:hover) .tcw-tree-grip:not(:focus-visible) {\n opacity: 0.45;\n}\n/* The row a dragged drawing would take the place of. */\n.tcw-tree-row.tcw-tree-drop {\n box-shadow: inset 0 0 0 1px var(--tcw-accent);\n}\n/* A drawing's name selects it on the chart. */\n.tcw-tree-name.tcw-tree-pick {\n flex: 1 1 auto;\n cursor: pointer;\n}\n.tcw-tree-btn.tcw-tree-del:hover {\n background: var(--tcw-red-soft);\n color: var(--tcw-red);\n}\n.tcw-tree-group .tcw-tree-name {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-weight: var(--tcw-weight-strong);\n}\n.tcw-tree-group .tcw-tree-name svg {\n flex: none;\n color: var(--tcw-text-muted);\n}\n.tcw-tree-member {\n margin-left: 14px;\n padding-left: 10px;\n border-inline-start: 1px solid var(--tcw-border-strong);\n border-radius: 0 var(--tcw-radius-sm) var(--tcw-radius-sm) 0;\n}\n.tcw-tree-rename {\n flex: 1;\n min-width: 0;\n padding: 3px 6px;\n border: 1px solid var(--tcw-accent-line);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-tree-rename:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\n}\n.tcw-tree-empty {\n padding: 8px;\n font-size: var(--tcw-font-size-sm);\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 max-height: 30dvh;\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 /* Except the loader's slow glow (opacity only): without it a long wait\n looks frozen. */\n .tcw-root .tcw-loading-candle,\n .tcw-root .tcw-loading-track > span {\n animation-duration: 2.4s !important;\n animation-iteration-count: infinite !important;\n animation-delay: var(--tcw-delay, 0ms) !important;\n }\n}\n\n/* --- Drawing settings dialog --- */\n.tcw-drawing-text {\n min-height: 56px;\n resize: vertical;\n font-family: inherit;\n}\n/* The text a drawing writes takes the dialog's width, under its name. */\n.tcw-text-row {\n flex-direction: column;\n align-items: stretch;\n gap: var(--tcw-space-3);\n}\n.tcw-text-row .tcw-drawing-text { box-sizing: border-box; width: 100%; }\n.tcw-levels-editor { display: grid; gap: var(--tcw-space-3); }\n/* Two columns of levels on a desktop, as a Fibonacci tool has a dozen. */\n.tcw-levels-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--tcw-space-3) var(--tcw-space-6);\n max-height: 260px;\n overflow-y: auto;\n padding-inline-end: var(--tcw-space-1);\n}\n@media (max-width: 640px) {\n .tcw-levels-grid { grid-template-columns: minmax(0, 1fr); }\n}\n.tcw-level-row {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto auto;\n align-items: center;\n gap: var(--tcw-space-3);\n}\n.tcw-level-row .tcw-indi-input { box-sizing: border-box; width: 100%; min-width: 0; }\n.tcw-level-row input[type='checkbox'] { accent-color: var(--tcw-accent); }\n.tcw-level-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: 0;\n border-radius: var(--tcw-radius-sm, 4px);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-level-remove:hover { color: var(--tcw-text); background: var(--tcw-bg-elevated); }\n.tcw-level-remove:focus-visible { outline: 2px solid var(--tcw-accent); outline-offset: 1px; }\n.tcw-level-add { justify-self: start; }\n\n/* --- Context menu (right-click on a drawing) --- */\n.tcw-context-menu {\n position: absolute;\n z-index: 70;\n min-width: 200px;\n /* Taller than the room (many templates, say), it scrolls. */\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: var(--tcw-menu-pad);\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n /* Frosted with the other menus (`ui.blur` above 0): the chart under it blurred, not sharp behind its words. */\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n}\n.tcw-context-item {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n width: 100%;\n min-height: var(--tcw-menu-item-h);\n padding: var(--tcw-space-1) var(--tcw-space-4);\n border: 0;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size);\n text-align: start;\n cursor: pointer;\n}\n.tcw-context-item svg, .tcw-context-icon { flex: none; width: 14px; height: 14px; color: var(--tcw-text-muted); }\n.tcw-context-item:hover, .tcw-context-item:focus-visible { background: var(--tcw-hover-bg); outline: none; }\n.tcw-context-item:focus-visible { box-shadow: inset 0 0 0 1px var(--tcw-accent); }\n.tcw-context-danger, .tcw-context-danger svg { color: var(--tcw-red); }\n.tcw-context-sep { height: 1px; margin: var(--tcw-space-2) var(--tcw-space-4); background: var(--tcw-divider); }\n.tcw-context-label { flex: 1; min-width: 0; }\n/* A shortcut, a count, and the mark of a submenu, at the row's end. */\n.tcw-context-key, .tcw-context-count {\n flex: none;\n margin-inline-start: var(--tcw-space-5);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-muted);\n}\n.tcw-context-item svg.tcw-context-more { width: 12px; height: 12px; }\n/* Right to left, a submenu opens to the left: its marks point there. */\n[dir='rtl'] .tcw-context-more, [dir='rtl'] .tcw-context-back > svg { transform: scaleX(-1); }\n/* No keyboard under a finger: the keys stay named to a screen reader only. */\n@media (hover: none) { .tcw-context-key { display: none; } }\n.tcw-context-item[aria-expanded='true'] { background: var(--tcw-hover-bg); }\n/* The choice made among radios: a dot where a switch has its tick. */\n.tcw-context-dot { display: grid; place-items: center; }\n.tcw-context-dot::after { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--tcw-text); }\n/* An entry that can be removed: its x on the row in hand, always on a touch screen. */\n.tcw-context-row { display: flex; align-items: center; border-radius: var(--tcw-menu-item-radius); }\n.tcw-context-row .tcw-context-item { flex: 1; min-width: 0; }\n.tcw-context-row:hover { background: var(--tcw-hover-bg); }\n.tcw-context-row:hover .tcw-context-item { background: transparent; }\n.tcw-context-remove {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n margin-inline-end: var(--tcw-space-1);\n border: 0;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-context-row:hover .tcw-context-remove, .tcw-context-row:focus-within .tcw-context-remove { opacity: 1; }\n.tcw-context-remove:hover { color: var(--tcw-red); background: var(--tcw-hover-bg); }\n@media (hover: none) { .tcw-context-remove { opacity: 1; } }\n/* --- Toolbar over a selected drawing --- */\n.tcw-sel-toolbar {\n position: absolute;\n z-index: 65;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-divider);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n font-family: var(--tcw-font);\n white-space: nowrap;\n animation: tcw-sel-in var(--tcw-dur-fast) var(--tcw-ease-out);\n}\n@keyframes tcw-sel-in { from { opacity: 0; transform: translateY(3px); } }\n.tcw-sel-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n min-width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n padding: 0 6px;\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-sel-btn svg { flex: none; }\n.tcw-sel-btn:hover, .tcw-sel-btn[aria-expanded=\"true\"] { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-sel-btn:focus-visible, .tcw-sel-swatch:focus-visible, .tcw-sel-option:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--tcw-accent); }\n.tcw-sel-btn.tcw-sel-on { color: var(--tcw-accent); background: var(--tcw-accent-soft); }\n.tcw-sel-danger:hover { color: var(--tcw-red); background: var(--tcw-red-soft); }\n.tcw-sel-color {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tcw-text) 25%, transparent);\n}\n/* The fill picker: a square, where the line colour is a dot. */\n.tcw-sel-fill { border-radius: 3px; }\n/* The text colour picker: a letter over a bar in the text's colour. */\n.tcw-sel-text {\n font-weight: var(--tcw-weight-strong);\n font-size: var(--tcw-font-size-sm);\n line-height: 1;\n padding-bottom: 1px;\n border-bottom: 3px solid var(--c, currentColor);\n}\n.tcw-sel-width {\n display: inline-block;\n width: 16px;\n height: var(--w, 1px);\n max-height: 6px;\n border-radius: 1px;\n background: currentColor;\n}\n.tcw-sel-sep { flex: none; width: 1px; height: 18px; margin: 0 3px; background: var(--tcw-divider); }\n.tcw-sel-pop {\n position: absolute;\n z-index: 66;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 120px;\n padding: 4px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-divider);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n font-family: var(--tcw-font);\n}\n.tcw-sel-pop--color {\n display: grid;\n grid-template-columns: repeat(4, 24px);\n gap: 6px;\n min-width: 0;\n padding: 8px;\n}\n.tcw-sel-swatch {\n width: 24px;\n height: 24px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tcw-text) 20%, transparent);\n cursor: pointer;\n transition: transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-sel-swatch:hover { transform: scale(1.1); }\n.tcw-sel-swatch.tcw-sel-on { box-shadow: 0 0 0 2px var(--tcw-bg-elevated), 0 0 0 4px var(--tcw-accent); }\n.tcw-sel-option {\n display: flex;\n align-items: center;\n gap: 10px;\n min-height: var(--tcw-menu-item-h);\n padding: 4px 10px;\n border: 0;\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n text-align: start;\n cursor: pointer;\n}\n.tcw-sel-option:hover { background: var(--tcw-bg-surface); }\n.tcw-sel-option.tcw-sel-on { color: var(--tcw-accent); }\n@media (prefers-reduced-motion: reduce) {\n .tcw-sel-toolbar { animation: none; }\n .tcw-sel-swatch { transition: none; }\n}\n\n/* --- The account: a panel under the chart; its head the tabs, the totals, a new order and its close. --- */\n.tcw-account-dock {\n flex: none;\n}\n.tcw-account {\n display: flex;\n flex-direction: column;\n /* 233, on the widget's φ ladder. */\n height: 233px;\n border-top: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n}\n.tcw-account-head {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-height: calc(var(--tcw-space-6) + var(--tcw-space-5));\n padding-inline: var(--tcw-space-4) var(--tcw-space-3);\n border-bottom: 1px solid var(--tcw-divider);\n}\n.tcw-account-tabs {\n display: flex;\n gap: var(--tcw-space-1);\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.tcw-account-tab {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-tab-h);\n padding: var(--tcw-tab-pad);\n border: 0;\n border-radius: var(--tcw-tab-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n cursor: pointer;\n}\n.tcw-account-tab:hover { color: var(--tcw-text); background: var(--tcw-tab-hover); }\n.tcw-account-tab[aria-selected='true'] {\n color: var(--tcw-tab-on-fg);\n background: var(--tcw-tab-on-bg);\n font-weight: var(--tcw-weight-strong);\n box-shadow: inset 0 calc(-1 * var(--tcw-tab-line)) 0 var(--tcw-accent);\n}\n/* A tab's count: a figure in a soft pill. */\n.tcw-account-count {\n min-width: 1.6em;\n padding-inline: var(--tcw-space-2);\n border-radius: 999px;\n background: var(--tcw-hover-bg);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n text-align: center;\n}\n/* The open and realised P&L, on every tab, in the mono figures. Short of room, they keep their start: the open P&L's words stay whole. */\n.tcw-account-totals {\n display: flex;\n flex: 1;\n justify-content: flex-end;\n justify-content: safe flex-end;\n gap: var(--tcw-space-5);\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.tcw-account-new {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-control-h);\n padding-inline: var(--tcw-space-4);\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n cursor: pointer;\n}\n.tcw-account-new:hover { background: var(--tcw-hover-bg); }\n.tcw-account-tab:focus-visible,\n.tcw-account-new:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n.tcw-account-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\n/* The rows: headings in the label case, figures set right in the mono type. */\n.tcw-account-table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-account-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n height: var(--tcw-control-h);\n padding-inline: var(--tcw-space-4);\n border-bottom: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-align: start;\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n white-space: nowrap;\n}\n.tcw-account-table td {\n height: calc(var(--tcw-control-h) + var(--tcw-space-2));\n padding-inline: var(--tcw-space-4);\n border-bottom: 1px solid var(--tcw-divider);\n color: var(--tcw-text);\n white-space: nowrap;\n}\n.tcw-account-table :is(th, td).tcw-num {\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n text-align: end;\n}\n.tcw-account-table tbody tr:hover td { background: var(--tcw-hover-bg); }\n.tcw-account-side { font-weight: var(--tcw-weight-strong); }\n.tcw-account-buy, .tcw-account-up { color: var(--tcw-green); }\n.tcw-account-sell, .tcw-account-down { color: var(--tcw-red); }\n.tcw-account-actions { display: flex; justify-content: flex-end; gap: var(--tcw-space-1); }\n.tcw-account-empty {\n margin: 0;\n padding: var(--tcw-space-6);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n text-align: center;\n}\n\n/*\n * A narrow widget (a phone, a narrow column): the totals go under the tabs,\n * and each row is a card of named figures. The headings stay for a screen\n * reader, unseen: the cells name themselves on screen. The panel is a step\n * of phi taller (377) for two cards and more, at most 45% of a phone's screen.\n */\n.tcw-root[data-tcw-narrow] .tcw-account {\n height: 377px;\n max-height: 45vh;\n max-height: 45dvh;\n}\n.tcw-root[data-tcw-narrow] .tcw-account-head { flex-wrap: wrap; padding-block: var(--tcw-space-2); }\n/* The tabs give way (they scroll): New order and the close keep the first line. */\n.tcw-root[data-tcw-narrow] .tcw-account-tabs { flex: 1 1 0; }\n.tcw-root[data-tcw-narrow] .tcw-account-totals { order: 3; flex-basis: 100%; justify-content: flex-start; padding-inline: var(--tcw-space-3); }\n.tcw-root[data-tcw-narrow] .tcw-account-table thead {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table,\n.tcw-root[data-tcw-narrow] .tcw-account-table tbody { display: block; }\n.tcw-root[data-tcw-narrow] .tcw-account-table tbody tr {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--tcw-space-2) var(--tcw-space-5);\n padding: var(--tcw-space-4);\n border-bottom: 1px solid var(--tcw-divider);\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table td {\n display: flex;\n justify-content: space-between;\n gap: var(--tcw-space-3);\n height: auto;\n padding: 0;\n border: 0;\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table td::before {\n content: attr(data-label);\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font);\n font-size: var(--tcw-font-size-xs);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table td:first-child,\n.tcw-root[data-tcw-narrow] .tcw-account-table td[data-label=''] { grid-column: 1 / -1; }\n.tcw-root[data-tcw-narrow] .tcw-account-table td[data-label='']::before { content: none; }\n.tcw-root[data-tcw-narrow] .tcw-account-table td[data-label=''] .tcw-account-actions { width: 100%; }\n.tcw-root[data-tcw-narrow] .tcw-account-table .tcw-tree-btn { width: 34px; height: 34px; }\n\n@media (forced-colors: active) {\n .tcw-account-tab[aria-selected='true'] { outline: 2px solid Highlight; }\n .tcw-account-tab:focus-visible,\n .tcw-account-new:focus-visible { outline: 2px solid Highlight; }\n}\n\n/* --- Named layouts --- */\n.tcw-layouts-btn { max-width: 190px; }\n.tcw-layouts-label {\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n.tcw-layouts-dirty {\n width: 6px;\n height: 6px;\n flex: none;\n border-radius: 50%;\n background: var(--tcw-accent);\n}\n.tcw-name-field { display: flex; flex-direction: column; gap: 6px; font-size: var(--tcw-font-size-sm); color: var(--tcw-text-dim); }\n.tcw-name-field .tcw-indi-input { width: 100%; height: 34px; font-size: var(--tcw-font-size); }\n\n/* --- Chart grid --- */\n.tcw-grid { background: var(--tcw-bg); }\n.tcw-grid-bar {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: calc(var(--tcw-control-h) + 8px);\n padding: 0 8px;\n border-bottom: 1px solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n overflow-x: auto;\n scrollbar-width: none;\n}\n.tcw-grid-bar::-webkit-scrollbar { display: none; }\n.tcw-grid-group { display: flex; align-items: center; gap: 2px; flex: none; }\n.tcw-grid-label {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-right: 4px;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n letter-spacing: var(--tcw-label-tracking);\n text-transform: var(--tcw-label-case);\n color: var(--tcw-text-muted);\n}\n.tcw-grid-sync[aria-pressed=\"true\"] { color: var(--tcw-accent); }\n.tcw-grid-cells {\n flex: 1;\n min-height: 0;\n display: grid;\n gap: 1px;\n background: var(--tcw-border);\n}\n.tcw-grid-cell {\n position: relative;\n min-width: 0;\n min-height: 0;\n background: var(--tcw-bg);\n}\n.tcw-grid-cell-active::after {\n content: '';\n position: absolute;\n inset: 0;\n border: 1px solid var(--tcw-accent);\n pointer-events: none;\n z-index: 5;\n}\n\n/* --- Host toolbar buttons --- */\n.tcw-toolbar-host { display: inline-flex; align-items: center; gap: 2px; }\n.tcw-toolbar-host:empty { display: none; }\n.tcw-host-btn { display: inline-flex; align-items: center; gap: 4px; }\n\n/* --- Host sidebar buttons, status bar items, and the layer over the chart --- */\n.tcw-sidebar-host { display: flex; flex-direction: column; align-items: center; }\n.tcw-sidebar-host:empty { display: none; }\n/* Your items keep their width (the range presets fold for them), and on the left a gap\n before the right group, whose auto margin closes up when the bar is full. */\n.tcw-status-host { display: flex; align-items: center; gap: 10px; flex: none; }\n.tcw-statusbar > .tcw-status-host { margin-inline-end: var(--tcw-space-5); }\n.tcw-status-host:empty { display: none; }\n.tcw-status-host-item { white-space: nowrap; }\n.tcw-status-host-btn {\n margin: -4px -6px;\n padding: 4px 6px;\n font: inherit;\n color: inherit;\n background: transparent;\n border: none;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-status-host-btn:hover { color: var(--tcw-text); background: var(--tcw-hover-bg); }\n.tcw-status-host-btn:focus-visible { outline: 2px solid var(--tcw-accent); outline-offset: -2px; }\n/* Over the plot and under the widget's own overlays; the pointer reaches the chart unless an element of yours takes it. */\n.tcw-host-layer { position: absolute; inset: 0; z-index: 2; pointer-events: none; }\n\n/* --- Pane buttons (move, fold, maximise) --- */\n.tcw-pane-controls {\n position: absolute;\n z-index: 4;\n display: flex;\n gap: 1px;\n transform: translateX(-100%);\n padding: 1px;\n border-radius: var(--tcw-radius-sm);\n background: color-mix(in srgb, var(--tcw-bg) 80%, transparent);\n opacity: 0.55;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-pane-controls:hover,\n.tcw-pane-controls:focus-within { opacity: 1; }\n.tcw-pane-btn {\n display: inline-grid;\n place-items: center;\n width: 18px;\n height: 16px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-pane-btn:hover { color: var(--tcw-text); background: var(--tcw-hover-bg); }\n.tcw-pane-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--tcw-accent-soft); }\n\n/* --- Typed interval --- */\n.tcw-interval-input {\n position: absolute;\n z-index: 20;\n left: 50%;\n top: 40%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px 12px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg, 10px);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n}\n.tcw-interval-field {\n width: 150px;\n height: 36px;\n padding: 0 10px;\n font: inherit;\n font-size: var(--tcw-font-size-xl);\n font-weight: var(--tcw-weight-strong);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-accent);\n border-radius: var(--tcw-input-radius);\n outline: none;\n}\n.tcw-interval-field[aria-invalid] { border-color: var(--tcw-red); }\n.tcw-interval-hint { font-size: var(--tcw-font-size-xs); color: var(--tcw-text-muted); max-width: 170px; }\n\n/* --- Alerts: lines, moves, bar close, expiry --- */\n.tcw-alerts-source { grid-column: auto; }\n.tcw-alerts-row-fields {\n grid-column: 1 / -1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n}\n.tcw-alerts-row-fields[hidden] { display: none; }\n.tcw-alerts-row-fields > input[hidden] { display: none; }\n.tcw-alerts-row-fields:has(> input[hidden]) { grid-template-columns: 1fr; }\n.tcw-alerts-options { align-items: center; }\n.tcw-alerts-form .tcw-alerts-check {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text-dim);\n}\n.tcw-alerts-form .tcw-alerts-check input { width: auto; height: auto; }\n.tcw-alerts-form input[aria-invalid=\"true\"] { border-color: var(--tcw-red); }\n.tcw-alerts-row-meta { margin-top: 2px; font-size: var(--tcw-font-size-xs); color: var(--tcw-text-muted); }\n.tcw-alerts-expired { opacity: 0.6; }\n\n/* --- Signal marker note --- */\n.tcw-marker-tip {\n position: absolute;\n z-index: 12;\n pointer-events: none;\n padding: 6px 8px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-tooltip-radius);\n background: var(--tcw-tooltip-bg);\n color: var(--tcw-tooltip-fg);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.45;\n font-variant-numeric: tabular-nums;\n box-shadow: var(--tcw-menu-shadow);\n max-width: 240px;\n}\n.tcw-marker-tip strong { display: block; font-size: var(--tcw-font-size-sm); }\n\n/* === Navigation over the chart ===\n * Centred on the plot's bottom edge, shown while a mouse is over the chart. */\n.tcw-nav {\n position: absolute;\n z-index: 15;\n display: flex;\n gap: 2px;\n padding: 3px;\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: calc(var(--tcw-control-radius) + 3px);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n opacity: 0;\n pointer-events: none;\n transform: translate(-50%, calc(-100% - 12px));\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-nav.tcw-nav-shown {\n opacity: 1;\n pointer-events: auto;\n}\n.tcw-nav-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n touch-action: none;\n}\n.tcw-nav-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n.tcw-nav-btn:active {\n background: var(--tcw-active-bg);\n}\n.tcw-nav-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n.tcw-nav-btn svg {\n width: var(--tcw-icon);\n height: var(--tcw-icon);\n}\n@media (hover: none) {\n .tcw-nav { display: none; }\n}\n\n/* === Symbol info ===\n * Top left, beside the drawing tools: the panels on the right stay clear. */\n.tcw-syminfo {\n position: absolute;\n top: var(--tcw-panel-top);\n inset-inline-start: var(--tcw-panel-left);\n z-index: 38;\n width: 288px;\n max-height: calc(100% - var(--tcw-panel-top) - 12px);\n display: flex;\n flex-direction: column;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\n overflow: hidden;\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-syminfo-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 9px 12px;\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n border-bottom: 1px solid var(--tcw-border);\n}\n.tcw-syminfo-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-syminfo-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\n.tcw-syminfo-body,\n.tcw-syminfo-news {\n padding: 12px 14px;\n overflow-y: auto;\n}\n.tcw-syminfo-body {\n display: grid;\n gap: 10px;\n}\n.tcw-syminfo-symbol {\n font-size: var(--tcw-font-size-lg);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n}\n.tcw-syminfo-desc {\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text-dim);\n}\n.tcw-syminfo-meta {\n margin-top: 2px;\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n.tcw-syminfo-quote {\n display: flex;\n align-items: baseline;\n gap: 10px;\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n.tcw-syminfo-price {\n font-size: var(--tcw-font-size-display);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n}\n.tcw-syminfo-change { font-size: var(--tcw-font-size-sm); }\n.tcw-syminfo-change.tcw-up { color: var(--tcw-green); }\n.tcw-syminfo-change.tcw-down { color: var(--tcw-red); }\n.tcw-syminfo-status {\n display: flex;\n align-items: center;\n gap: 7px;\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text-dim);\n}\n.tcw-syminfo-status::before,\n.tcw-status-market::before {\n content: '';\n flex: none;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n}\n.tcw-syminfo-status[data-state='open']::before,\n.tcw-syminfo-status[data-state='always']::before,\n.tcw-status-market[data-state='open']::before {\n background: var(--tcw-green);\n}\n.tcw-syminfo-stats {\n display: grid;\n gap: 4px;\n margin: 0;\n padding-top: 10px;\n border-top: 1px solid var(--tcw-divider);\n}\n.tcw-syminfo-stat {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-syminfo-stat dt { color: var(--tcw-text-muted); }\n.tcw-syminfo-stat dd {\n margin: 0;\n color: var(--tcw-text);\n text-align: end;\n font-variant-numeric: tabular-nums;\n overflow-wrap: anywhere;\n}\n.tcw-syminfo-news {\n border-top: 1px solid var(--tcw-divider);\n}\n.tcw-syminfo-news-title {\n margin-bottom: 8px;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text-muted);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n.tcw-syminfo-news-list {\n display: grid;\n gap: 10px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.tcw-syminfo-news-item {\n font-size: var(--tcw-font-size-sm);\n line-height: 1.4;\n color: var(--tcw-text);\n}\n.tcw-syminfo-news-item a {\n color: var(--tcw-text);\n text-decoration: none;\n}\n.tcw-syminfo-news-item a:hover { color: var(--tcw-accent); text-decoration: underline; }\n.tcw-syminfo-news-item a:focus-visible { outline: none; box-shadow: var(--tcw-ring); border-radius: var(--tcw-radius-xs); }\n.tcw-syminfo-news-meta,\n.tcw-syminfo-news-note {\n margin-top: 2px;\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n\n/* Numbers keep their sign on the left, and mixed text its own order, in a right-to-left widget too. */\n.tcw-watchlist-price,\n.tcw-watchlist-change,\n.tcw-syminfo-price,\n.tcw-syminfo-change {\n unicode-bidi: isolate;\n direction: ltr;\n}\n.tcw-syminfo-desc,\n.tcw-syminfo-meta,\n.tcw-syminfo-status,\n.tcw-syminfo-stat dd,\n.tcw-syminfo-news-meta {\n unicode-bidi: plaintext;\n}\n\n/* The market's status in the status bar. */\n.tcw-status-market {\n display: flex;\n align-items: center;\n gap: 7px;\n color: var(--tcw-text-muted);\n}\n\n@media (max-width: 640px) {\n .tcw-syminfo {\n top: auto;\n bottom: 0;\n left: 0;\n right: 0;\n width: 100vw;\n max-height: 70%;\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 0 0;\n }\n}\n\n/* === The look: how chosen controls show, floating bars, segmented intervals ===\n * Each switch sets variables on its own root, which its parts read: a grid's\n * look never reaches into a chart that has one of its own. */\n\n/* A chosen button (`ui.active`): a tinted fill (default), a solid pill, or an underline.\n * Dialog tabs are chips, or underlined in the underline look. Panels sit below the\n * toolbar and beside the drawing tools. */\n.tcw-root {\n --tcw-on-bg: var(--tcw-accent-soft);\n --tcw-on-fg: var(--tcw-accent);\n --tcw-on-ring: none;\n --tcw-on-icon-bg: var(--tcw-accent-soft);\n --tcw-on-icon-fg: var(--tcw-accent);\n --tcw-on-icon-ring: none;\n --tcw-tabs-pad-block: var(--tcw-space-4);\n --tcw-tab-h: var(--tcw-control-h);\n --tcw-tab-pad: 0 var(--tcw-space-5);\n --tcw-tab-line: 0px;\n --tcw-tab-radius: var(--tcw-control-radius);\n --tcw-tab-hover: var(--tcw-hover-bg);\n --tcw-tab-on-bg: var(--tcw-on-bg);\n --tcw-tab-on-fg: var(--tcw-on-fg);\n /* A menu's rows sit inside its padding with corners that follow its own: the menu's\n * corner less the padding between, so the two curves run parallel (Print: 5 - 3 = 2). */\n --tcw-menu-pad: var(--tcw-space-2);\n --tcw-menu-item-radius: max(0px, calc(var(--tcw-menu-radius) - var(--tcw-menu-pad)));\n --tcw-panel-top: calc(var(--tcw-toolbar-h) + var(--tcw-space-3));\n --tcw-panel-left: calc(var(--tcw-sidebar-w) + var(--tcw-space-5));\n}\n.tcw-root[data-tcw-active='solid'] {\n --tcw-on-bg: var(--tcw-text);\n --tcw-on-fg: var(--tcw-bg);\n --tcw-on-icon-bg: var(--tcw-text);\n --tcw-on-icon-fg: var(--tcw-bg);\n}\n/* Print picks a tool in ink blue on a tint: a solid square would outweigh the chart beside it. */\n.tcw-root[data-tcw-ui='print'][data-tcw-active='solid'] {\n --tcw-on-icon-bg: var(--tcw-accent-soft);\n --tcw-on-icon-fg: var(--tcw-accent);\n}\n.tcw-root[data-tcw-active='underline'] {\n --tcw-on-bg: var(--tcw-active-bg);\n --tcw-on-fg: var(--tcw-text);\n --tcw-on-ring: inset 0 -2px 0 var(--tcw-accent);\n --tcw-on-icon-bg: var(--tcw-active-bg);\n --tcw-on-icon-fg: var(--tcw-accent);\n --tcw-on-icon-ring: inset 2px 0 0 var(--tcw-accent);\n --tcw-tabs-pad-block: 0px;\n --tcw-tab-h: auto;\n --tcw-tab-pad: 11px 14px;\n --tcw-tab-line: 2px;\n --tcw-tab-radius: 0px;\n --tcw-tab-hover: transparent;\n --tcw-tab-on-bg: transparent;\n --tcw-tab-on-fg: var(--tcw-accent);\n}\n.tcw-root[data-tcw-toolbar='floating'] {\n --tcw-panel-top: calc(var(--tcw-toolbar-h) + 2 * var(--tcw-border-w) + 14px);\n}\n.tcw-root[data-tcw-sidebar='floating'] {\n --tcw-panel-left: calc(var(--tcw-sidebar-w) + 2 * var(--tcw-border-w) + 22px);\n}\n\n/* The toolbar as an island (`ui.toolbar: 'floating'`). */\n.tcw-root[data-tcw-toolbar='floating'] > .tcw-toolbar {\n margin: 8px 10px 0;\n padding-inline: calc(min(var(--tcw-toolbar-radius), var(--tcw-toolbar-h) / 2) / 2 + 8px);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-toolbar-radius);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n}\n\n/* The drawing tools as an island (`ui.sidebar: 'floating'`). */\n.tcw-root[data-tcw-sidebar='floating'] > .tcw-body > .tcw-sidebar {\n align-self: flex-start;\n max-height: calc(100% - 20px);\n margin: 10px 6px 10px 10px;\n padding-block: calc(min(var(--tcw-sidebar-radius), var(--tcw-sidebar-w) / 2) / 2 + 6px);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-sidebar-radius);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n}\n\n/* Frosted menus (`ui.blur` above 0): the chart shows through, blurred. */\n@supports (background: color-mix(in srgb, red 50%, transparent)) {\n .tcw-dropdown,\n .tcw-flyout,\n .tcw-context-menu {\n background: color-mix(in srgb, var(--tcw-bg-elevated) var(--tcw-surface-opacity), transparent);\n }\n}\n\n/* The interval buttons in one track (`ui.intervals: 'segmented'`). */\n.tcw-root[data-tcw-intervals='segmented'] > .tcw-toolbar > .tcw-tf-group {\n gap: 2px;\n margin: 0 4px;\n padding: 3px;\n border-radius: calc(var(--tcw-control-radius) + 3px);\n background: var(--tcw-hover-bg);\n}\n.tcw-root[data-tcw-intervals='segmented'] > .tcw-toolbar > .tcw-tf-group .tcw-btn {\n height: calc(var(--tcw-control-h) - 6px);\n padding: 0 9px;\n}\n\n/* Phones: the variants keep comfortable tap targets and room for the bar. */\n@media (max-width: 768px) {\n .tcw-root[data-tcw-intervals='segmented'] > .tcw-toolbar > .tcw-tf-group .tcw-btn {\n height: max(34px, calc(var(--tcw-control-h) - 6px));\n padding: 0 10px;\n }\n .tcw-root[data-tcw-toolbar='floating'] > .tcw-toolbar {\n margin: 6px 6px 0;\n padding-inline: 4px;\n }\n .tcw-root[data-tcw-sidebar='floating'] > .tcw-body > .tcw-sidebar {\n margin: 6px 4px 6px 6px;\n }\n}\n\n/* --- Phones and tablets --- */\n\n/* Taps without the grey flash or the double-tap zoom's wait. The chart area\n sets its own touch-action for its gestures. */\n.tcw-root {\n -webkit-tap-highlight-color: transparent;\n touch-action: manipulation;\n}\n\n/* iOS zooms the page into an input under 16 px when it takes focus. */\n@media (pointer: coarse) {\n .tcw-root input:not([type='color']):not([type='range']):not([type='checkbox']):not([type='radio']),\n .tcw-root select,\n .tcw-root textarea {\n font-size: max(16px, 1em);\n }\n}\n\n/* Sheets and lists scroll on their own, without dragging the page behind them. */\n.tcw-modal {\n overscroll-behavior: contain;\n}\n\n/* === The bars' newer parts ===\n * Interval sections and the chart type's icon, the Trade menu's button, undo\n * and redo off while idle, the tool menus' shortcuts and stars, the status\n * bar's clock and scale switches, and the grip of the selection toolbar. */\n\n/* The interval menu: each unit under its heading, a hairline between them. */\n.tcw-tf-section + .tcw-tf-section {\n margin-top: var(--tcw-space-2);\n padding-top: var(--tcw-space-1);\n border-top: 1px solid var(--tcw-divider);\n}\n\n/* The chart type: its icon alone, square. */\n.tcw-dropdown-trigger[data-role='charttype'] {\n justify-content: center;\n width: var(--tcw-control-h);\n padding: 0;\n}\n\n/* Undo and redo with nothing to do: there, quiet, not pressable. */\n.tcw-btn-icon:disabled {\n opacity: 0.35;\n cursor: default;\n background: transparent;\n color: var(--tcw-text-muted);\n}\n\n/* A tool menu's row: the tool, its shortcut, and a star beside it. */\n.tcw-flyout-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n}\n.tcw-flyout-row > .tcw-flyout-item {\n flex: 1;\n min-width: 0;\n}\n.tcw-flyout-name {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.tcw-flyout-key {\n flex: none;\n margin-inline-start: var(--tcw-space-5);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n.tcw-flyout-pin {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n/* Shown on the row in hand; always for a pinned tool, filled in ink blue; always on a touch screen. */\n.tcw-flyout-row:hover .tcw-flyout-pin,\n.tcw-flyout-row:focus-within .tcw-flyout-pin,\n.tcw-flyout-pin[aria-pressed='true'],\n.tcw-root[data-tcw-narrow] .tcw-flyout-pin {\n opacity: 1;\n}\n@media (hover: none) {\n .tcw-flyout-pin {\n opacity: 1;\n }\n}\n.tcw-flyout-pin:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n.tcw-flyout-pin[aria-pressed='true'] {\n color: var(--tcw-accent);\n}\n.tcw-flyout-pin[aria-pressed='true'] svg path {\n fill: currentColor;\n}\n\n/* The clock: the time in figures, the zone beside it; it opens the zones. */\n.tcw-status-clock,\n.tcw-status-scale-btn {\n height: var(--tcw-control-h-sm);\n padding: 0 var(--tcw-space-3);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-status-clock {\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n.tcw-status-clock:hover,\n.tcw-status-scale-btn:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n.tcw-status-clock:focus-visible,\n.tcw-status-scale-btn:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n/* The scale switches: %, log, auto, in ink blue while on. */\n.tcw-status-scale {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n padding-inline-start: var(--tcw-space-3);\n border-inline-start: var(--tcw-sep-w) solid var(--tcw-border);\n}\n.tcw-status-scale-btn[aria-pressed='true'] {\n color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n/* A narrow widget keeps the range presets and the clock: the scale switches (also in the\n settings and the scale's menu) give them the room, and the connection's word is left to\n screen readers beside its dot. */\n.tcw-root[data-tcw-narrow] .tcw-status-scale {\n display: none;\n}\n/* The market's status in a word (\"Closed\"), when even with everything folded under \"more\"\n the bar has no room: the full words are left to screen readers and the tooltip. */\n.tcw-status-market-short {\n display: none;\n}\n.tcw-statusbar--short-market .tcw-status-market-short {\n display: inline;\n}\n.tcw-root[data-tcw-narrow] .tcw-status-indicator > span:not(.tcw-status-dot),\n.tcw-statusbar--short-market .tcw-status-market-text {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* The selection toolbar's grip: dots to take it by. */\n.tcw-sel-grip {\n flex: none;\n width: var(--tcw-space-4);\n height: var(--tcw-control-h-sm);\n margin-inline: var(--tcw-space-1) var(--tcw-space-2);\n background-image: radial-gradient(circle, var(--tcw-text-muted) 1px, transparent 1.4px);\n background-size: 4px 4px;\n background-position: center;\n opacity: 0.7;\n cursor: grab;\n touch-action: none;\n}\n.tcw-sel-grip:active {\n cursor: grabbing;\n}\n\n/* --- A narrow widget (a phone, or a narrow column): data-tcw-narrow ---\n Set from the widget's own width, below 641px. The toolbar keeps the\n chart's own controls (symbol, interval, type, indicators) and puts the\n rest under \"more\"; the drawing tools wait behind a button over the chart;\n a grid shows one chart at a time, picked by its tab. */\n\n.tcw-toolbar-more,\n.tcw-sidebar-fab,\n.tcw-tf-current,\n.tcw-grid-tabs {\n display: none;\n}\n\n/* The toolbar fits itself too (on a tablet, a window half a screen wide):\n the right-hand buttons that don't fit fold under \"more\" (`--collapsed`\n shows it), a host's left-hand ones last, and `--icons` drops the menus'\n labels and the interval buttons. Narrow folds them all. */\n.tcw-toolbar [data-tcw-folded],\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-toolbar-overflow {\n display: none;\n}\n.tcw-toolbar--collapsed > .tcw-toolbar-more,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar > .tcw-toolbar-more {\n display: inline-flex;\n margin-inline-start: auto;\n}\n.tcw-toolbar--icons.tcw-toolbar--tf-menu > .tcw-tf-group,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar.tcw-toolbar--tf-menu > .tcw-tf-group {\n display: none;\n}\n.tcw-toolbar--icons .tcw-tf-more,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-tf-more {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 10px;\n}\n.tcw-toolbar--icons .tcw-tf-current,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-tf-current {\n display: inline;\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent);\n}\n.tcw-toolbar--icons .tcw-trigger-label,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-trigger-label {\n display: none;\n}\n\n/* The drawing tools lie over the chart when opened, from its edge. */\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n /* Under the toolbar (20), whose menus open over it. */\n z-index: 18;\n box-shadow: var(--tcw-menu-shadow);\n transform: translateX(-100%);\n visibility: hidden;\n transition: transform var(--tcw-dur-normal) var(--tcw-ease-out), visibility 0s linear var(--tcw-dur-normal);\n}\n.tcw-root[data-tcw-narrow][dir='rtl'] > .tcw-body > .tcw-sidebar {\n transform: translateX(100%);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar.tcw-sidebar-open {\n transform: none;\n visibility: visible;\n transition: transform var(--tcw-dur-normal) var(--tcw-ease-out), visibility 0s;\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-flyout {\n z-index: 19;\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n /* Over the plot, in from its left edge (the widget sets where it starts): the\n price axis stays on the chart's right in either direction, so a\n right-to-left widget keeps the button on the left too, off the axis. */\n left: calc(var(--tcw-fab-plot-left, 0px) + 10px);\n /* Clear of the time axis. */\n bottom: 44px;\n z-index: 17;\n width: 44px;\n height: 44px;\n padding: 0;\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: 999px;\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text);\n box-shadow: var(--tcw-menu-shadow);\n cursor: pointer;\n transition: background var(--tcw-dur-fast), color var(--tcw-dur-fast), border-color var(--tcw-dur-fast);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab.tcw-active {\n background: var(--tcw-accent);\n border-color: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab[aria-expanded='true'] {\n visibility: hidden;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar,\n .tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar.tcw-sidebar-open {\n transition: none;\n }\n}\n\n/* A narrow grid: one chart at a time, a tab for each. */\n.tcw-grid[data-tcw-narrow] > .tcw-grid-bar > .tcw-grid-tabs {\n display: flex;\n}\n.tcw-grid-tab {\n white-space: nowrap;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells {\n display: flex;\n flex-direction: column;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells > .tcw-grid-cell {\n flex: 1;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells > .tcw-grid-cell:not(.tcw-grid-cell-current) {\n display: none;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells > .tcw-grid-cell-active::after {\n display: none;\n}\n\n/* Phones: menus open as sheets from the bottom, in reach of a thumb and\n never off screen (a menu's own place may be off the side of a phone). */\n@media (max-width: 640px) {\n .tcw-dropdown,\n .tcw-context-menu {\n position: fixed !important;\n /* Above the on-screen keyboard (the indicators' search). */\n inset: auto 0 var(--tcw-keyboard-inset, 0px) 0 !important;\n margin: 0 !important;\n width: auto;\n max-width: none;\n max-height: 70vh !important;\n max-height: 70dvh !important;\n overflow-y: auto;\n overscroll-behavior: contain;\n z-index: 80;\n padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px));\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 0 0;\n border-bottom: none;\n }\n .tcw-dropdown-item,\n .tcw-context-item {\n min-height: 44px;\n }\n}\n", Xt = "/* === Base controls: fields, selects, checks, sliders, calendar, scrollbars ===\n *\n * One look for every form control in the widget, from tokens. Fields are\n * quiet until used: a faint fill and hairline, a firmer line on hover, and\n * on focus the line turns accent (no ring). Selects and date fields open\n * the widget's own list and calendar (formControls.ts).\n */\n\n.tcw-root {\n color-scheme: dark;\n\n --tcw-field-bg: rgba(230, 227, 220, 0.04);\n --tcw-field-bg-hover: rgba(230, 227, 220, 0.06);\n --tcw-field-bg-focus: rgba(230, 227, 220, 0.03);\n --tcw-field-line: rgba(230, 227, 220, 0.12);\n --tcw-field-line-hover: rgba(230, 227, 220, 0.22);\n --tcw-field-line-focus: var(--tcw-accent-line);\n --tcw-field-placeholder: var(--tcw-text-muted);\n --tcw-check-line: rgba(230, 227, 220, 0.3);\n --tcw-scroll-thumb: rgba(230, 227, 220, 0.14);\n --tcw-scroll-thumb-hover: rgba(230, 227, 220, 0.26);\n /* Glyphs drawn in a field's background (a background image takes no currentColor). */\n --tcw-field-chevron: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.75l3 3 3-3' fill='none' stroke='%23918f8a' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n --tcw-field-calendar: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg fill='none' stroke='%23918f8a' stroke-width='1.3' stroke-linecap='round'%3E%3Crect x='2.5' y='3.5' width='11' height='10' rx='2'/%3E%3Cpath d='M2.5 6.5h11M5.5 2v3M10.5 2v3'/%3E%3C/g%3E%3C/svg%3E\");\n --tcw-check-mark: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.25l2.6 2.6L12 5.5' fill='none' stroke='%23131416' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n}\n\n.tcw-root[data-tcw-theme='light'] {\n color-scheme: light;\n\n /* Fields are white boxes on the paper, ruled in ink, as on a printed form. */\n --tcw-field-bg: #ffffff;\n --tcw-field-bg-hover: #ffffff;\n --tcw-field-bg-focus: #ffffff;\n --tcw-field-line: rgba(27, 29, 33, 0.16);\n --tcw-field-line-hover: rgba(27, 29, 33, 0.3);\n --tcw-check-line: rgba(27, 29, 33, 0.34);\n --tcw-scroll-thumb: rgba(27, 29, 33, 0.16);\n --tcw-scroll-thumb-hover: rgba(27, 29, 33, 0.3);\n --tcw-field-chevron: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.75l3 3 3-3' fill='none' stroke='%236a6e75' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n --tcw-field-calendar: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg fill='none' stroke='%236a6e75' stroke-width='1.3' stroke-linecap='round'%3E%3Crect x='2.5' y='3.5' width='11' height='10' rx='2'/%3E%3Cpath d='M2.5 6.5h11M5.5 2v3M10.5 2v3'/%3E%3C/g%3E%3C/svg%3E\");\n --tcw-check-mark: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.25l2.6 2.6L12 5.5' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n}\n\n/* --- Text, number, date and time fields, and selects --- */\n\n/* Fields speak the widget's type, not the browser's (a part's own font still wins).\n * The browser's control font resets the OpenType features, so --tcw-font-features\n * set on .tcw-root reaches every button and field only through this. */\n:where(.tcw-root) :where(input, select, textarea, button) {\n font-family: inherit;\n font-weight: inherit;\n letter-spacing: inherit;\n font-feature-settings: inherit;\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-settings-select,\n .tcw-settings-number,\n .tcw-goto-input,\n .tcw-watchlist-input,\n .tcw-indi-input,\n .tcw-style-name,\n .tcw-drawing-text,\n .tcw-replay-speed,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-alerts-form select\n) {\n border: 1px solid var(--tcw-field-line);\n border-radius: var(--tcw-input-radius);\n background-color: var(--tcw-field-bg);\n color: var(--tcw-text);\n outline: none;\n box-shadow: none;\n transition:\n border-color var(--tcw-dur-fast) var(--tcw-ease),\n background-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-settings-select,\n .tcw-settings-number,\n .tcw-goto-input,\n .tcw-watchlist-input,\n .tcw-indi-input,\n .tcw-style-name,\n .tcw-drawing-text,\n .tcw-replay-speed,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-alerts-form select\n):hover:not(:disabled, :focus) {\n border-color: var(--tcw-field-line-hover);\n background-color: var(--tcw-field-bg-hover);\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-settings-select,\n .tcw-settings-number,\n .tcw-goto-input,\n .tcw-watchlist-input,\n .tcw-indi-input,\n .tcw-style-name,\n .tcw-drawing-text,\n .tcw-replay-speed,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-alerts-form select\n):is(:focus, :focus-visible, [aria-expanded='true']) {\n border-color: var(--tcw-field-line-focus);\n background-color: var(--tcw-field-bg-focus);\n outline: none;\n box-shadow: none;\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-indi-input,\n .tcw-watchlist-input,\n .tcw-goto-input,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-settings-number\n):is([aria-invalid='true']):is(*, :hover, :focus) {\n /* As specific as the hover rule (its list holds the same :not) and later, so a wrong value stays red\n under the pointer and in focus. */\n border-color: var(--tcw-red);\n box-shadow: none;\n}\n\n.tcw-root :is(input, textarea)::placeholder {\n color: var(--tcw-field-placeholder);\n opacity: 1;\n}\n\n.tcw-root :is(input, select, textarea):disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Selects: the browser's arrow gives way to a fine chevron. */\n.tcw-root select:not([multiple]):not([size]) {\n appearance: none;\n -webkit-appearance: none;\n background-image: var(--tcw-field-chevron);\n background-repeat: no-repeat;\n background-size: 12px 12px;\n background-position: right 8px center;\n padding-inline-end: 26px;\n text-overflow: ellipsis;\n cursor: pointer;\n}\n\n.tcw-root[dir='rtl'] select:not([multiple]):not([size]),\n.tcw-root [dir='rtl'] select:not([multiple]):not([size]) {\n background-position: left 8px center;\n}\n\n/* A select laid out left to right inside a right-to-left widget (the chart's\n * own area is LTR, the replay's figures too) keeps its chevron on the right,\n * where its padding is. */\n.tcw-root[dir='rtl'] [dir='ltr'] select:not([multiple]):not([size]),\n.tcw-root[dir='rtl'] select[dir='ltr']:not([multiple]):not([size]) {\n background-position: right 8px center;\n}\n\n/* Number fields: the steppers show only on a field in use. */\n.tcw-root input[type='number']::-webkit-inner-spin-button,\n.tcw-root input[type='number']::-webkit-outer-spin-button {\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root input[type='number']:is(:hover, :focus)::-webkit-inner-spin-button {\n opacity: 0.55;\n}\n\n/* Date and time: the widget's calendar icon where the browser's own can be hidden. */\n@supports selector(::-webkit-calendar-picker-indicator) {\n .tcw-root input[type='date'] {\n background-image: var(--tcw-field-calendar);\n background-repeat: no-repeat;\n background-size: 15px 15px;\n background-position: right 8px center;\n padding-inline-end: 30px;\n cursor: text;\n }\n\n .tcw-root[dir='rtl'] input[type='date'],\n .tcw-root [dir='rtl'] input[type='date'] {\n background-position: left 8px center;\n }\n}\n\n.tcw-root input:is([type='date'], [type='time'])::-webkit-calendar-picker-indicator {\n display: none;\n}\n\n.tcw-root input:is([type='date'], [type='time'])::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n}\n\n/* --- Checkboxes and radios --- */\n\n.tcw-root input:is([type='checkbox'], [type='radio']) {\n appearance: none;\n -webkit-appearance: none;\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n margin: 0;\n border: 1.5px solid var(--tcw-check-line);\n border-radius: var(--tcw-radius-sm);\n background: transparent center / 14px 14px no-repeat;\n cursor: pointer;\n vertical-align: middle;\n transition:\n border-color var(--tcw-dur-fast) var(--tcw-ease),\n background-color var(--tcw-dur-fast) var(--tcw-ease),\n box-shadow var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root input[type='radio'] {\n border-radius: 50%;\n}\n\n.tcw-root input:is([type='checkbox'], [type='radio']):hover:not(:disabled) {\n border-color: var(--tcw-text-dim);\n}\n\n.tcw-root input[type='checkbox']:checked {\n border-color: var(--tcw-accent);\n background-color: var(--tcw-accent);\n background-image: var(--tcw-check-mark);\n}\n\n.tcw-root input[type='radio']:checked {\n border-color: var(--tcw-accent);\n background-image: radial-gradient(circle, var(--tcw-accent) 0 3.5px, transparent 4px);\n}\n\n.tcw-root input:is([type='checkbox'], [type='radio']):focus {\n outline: none;\n}\n\n.tcw-root input:is([type='checkbox'], [type='radio']):focus-visible {\n box-shadow: 0 0 0 3px var(--tcw-accent-soft);\n}\n\n/* --- Sliders --- */\n\n.tcw-root input[type='range'] {\n appearance: none;\n -webkit-appearance: none;\n height: 4px;\n border-radius: 999px;\n background: var(--tcw-field-line-hover);\n outline: none;\n cursor: pointer;\n}\n\n.tcw-root input[type='range']::-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 1px 3px rgba(0, 0, 0, 0.35);\n transition: transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root input[type='range']::-moz-range-thumb {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--tcw-accent);\n border: 2px solid var(--tcw-bg-elevated);\n}\n\n.tcw-root input[type='range']:hover::-webkit-slider-thumb {\n transform: scale(1.12);\n}\n\n.tcw-root input[type='range']:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 4px var(--tcw-accent-soft);\n}\n\n/* --- The select list --- */\n\n.tcw-select-menu {\n z-index: 120;\n padding: var(--tcw-menu-pad);\n max-width: min(360px, calc(100vw - 16px));\n font-size: var(--tcw-font-size);\n}\n\n.tcw-select-group {\n padding: var(--tcw-space-4) var(--tcw-space-4) var(--tcw-space-2);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text-muted);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-select-option {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n min-height: var(--tcw-menu-item-h);\n padding-block: 0;\n padding-inline: var(--tcw-space-3) var(--tcw-space-5);\n border-radius: var(--tcw-menu-item-radius);\n color: var(--tcw-text-dim);\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n}\n\n.tcw-select-option-text {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-select-check {\n flex-shrink: 0;\n width: 14px;\n height: 14px;\n}\n\n.tcw-select-option.tcw-active {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-select-option[aria-selected='true'] {\n color: var(--tcw-text);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-select-option[aria-selected='true'] .tcw-select-check {\n background: var(--tcw-accent);\n -webkit-mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.25l3 3L12.5 5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center / contain no-repeat;\n mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.25l3 3L12.5 5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center / contain no-repeat;\n}\n\n.tcw-select-option[aria-disabled='true'] {\n opacity: 0.4;\n cursor: default;\n background: none;\n}\n\n/* --- The calendar --- */\n\n.tcw-calendar {\n z-index: 120;\n width: 268px;\n padding: 10px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n.tcw-calendar-head {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-bottom: 8px;\n}\n\n.tcw-calendar-title {\n flex: 1;\n text-align: center;\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n letter-spacing: -0.01em;\n}\n\n.tcw-calendar-nav {\n display: inline-grid;\n place-items: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-radius-sm);\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}\n\n.tcw-calendar-nav svg {\n width: 16px;\n height: 16px;\n fill: none;\n stroke: currentColor;\n stroke-width: 1.6;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.tcw-calendar[dir='rtl'] .tcw-calendar-nav svg,\n[dir='rtl'] .tcw-calendar-nav svg {\n transform: scaleX(-1);\n}\n\n.tcw-calendar-nav:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-calendar-weekdays,\n.tcw-calendar-grid {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n}\n\n.tcw-calendar-weekdays {\n margin-bottom: 4px;\n padding: 3px 0;\n border-radius: var(--tcw-radius-sm);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-calendar-weekday {\n text-align: center;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text-muted);\n line-height: 20px;\n}\n\n.tcw-calendar-grid {\n row-gap: 2px;\n}\n\n.tcw-calendar-week {\n display: contents;\n}\n\n.tcw-calendar-day {\n position: relative;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-calendar-day:hover:not(:disabled) {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-calendar-day.tcw-outside {\n color: var(--tcw-text-muted);\n opacity: 0.55;\n}\n\n/* Today: accent figures over a short line. */\n.tcw-calendar-day.tcw-today {\n color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-calendar-day.tcw-today::after {\n content: '';\n position: absolute;\n left: 50%;\n bottom: 5px;\n width: 12px;\n height: 2px;\n margin-left: -6px;\n border-radius: 1px;\n background: currentColor;\n}\n\n.tcw-calendar-day[aria-selected='true'] {\n background: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n font-weight: var(--tcw-weight-strong);\n opacity: 1;\n}\n\n.tcw-calendar-day:disabled {\n opacity: 0.28;\n cursor: not-allowed;\n}\n\n.tcw-calendar-day:focus {\n outline: none;\n}\n\n.tcw-calendar-day:focus-visible {\n box-shadow: inset 0 0 0 1.5px var(--tcw-accent);\n}\n\n.tcw-calendar-foot {\n display: flex;\n justify-content: flex-end;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-calendar-today {\n height: 26px;\n padding: 0 10px;\n border: none;\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n color: var(--tcw-accent);\n font: inherit;\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n}\n\n.tcw-calendar-today:hover {\n background: var(--tcw-accent-soft);\n}\n\n.tcw-calendar-today:focus-visible,\n.tcw-calendar-nav:focus-visible {\n outline: none;\n box-shadow: inset 0 0 0 1.5px var(--tcw-accent);\n}\n\n/* --- Scrollbars: thin and rounded, a thumb on no track. Low specificity:\n a part that hides its bar keeps it hidden. --- */\n\n:where(.tcw-root) ::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n\n:where(.tcw-root) ::-webkit-scrollbar-track,\n:where(.tcw-root) ::-webkit-scrollbar-corner {\n background: transparent;\n}\n\n:where(.tcw-root) ::-webkit-scrollbar-thumb {\n background: var(--tcw-scroll-thumb);\n background-clip: padding-box;\n border: 3px solid transparent;\n border-radius: 999px;\n}\n\n:where(.tcw-root) ::-webkit-scrollbar-thumb:hover {\n background: var(--tcw-scroll-thumb-hover);\n background-clip: padding-box;\n border: 2.5px solid transparent;\n}\n\n/* Engines without the pseudo-elements take the standard properties. */\n@supports not selector(::-webkit-scrollbar) {\n :where(.tcw-root, .tcw-root *) {\n scrollbar-width: thin;\n scrollbar-color: var(--tcw-scroll-thumb) transparent;\n }\n}\n\n/* --- Switches: flat, no glow --- */\n\n.tcw-root .tcw-toggle.tcw-on {\n box-shadow: none;\n}\n\n.tcw-root .tcw-toggle::after {\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);\n}\n\n.tcw-root .tcw-toggle:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--tcw-accent-soft);\n}\n\n/* One choice of a few in a row (a radio group): the chosen one as the look shows a chosen button. */\n.tcw-segmented {\n display: inline-flex;\n flex-wrap: wrap;\n max-width: 100%;\n gap: 2px;\n padding: 2px;\n border-radius: calc(var(--tcw-control-radius) + 2px);\n background: var(--tcw-hover-bg);\n}\n.tcw-segment {\n height: calc(var(--tcw-control-h) - 4px);\n padding-inline: var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-segment:hover { color: var(--tcw-text); }\n.tcw-segment[aria-checked='true'] {\n background: var(--tcw-on-bg);\n color: var(--tcw-on-fg);\n font-weight: var(--tcw-weight-strong);\n box-shadow: var(--tcw-on-ring);\n}\n.tcw-segment:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A number between a − and a +: one field, the figure right-aligned in the chart's mono type. */\n.tcw-stepper {\n box-sizing: border-box;\n display: inline-flex;\n align-items: stretch;\n height: var(--tcw-control-h);\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-bg);\n overflow: hidden;\n}\n.tcw-stepper:focus-within { box-shadow: var(--tcw-ring); }\n.tcw-stepper .tcw-indi-input {\n width: 110px;\n height: auto;\n padding-inline: var(--tcw-space-3);\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n text-align: end;\n -moz-appearance: textfield;\n appearance: textfield;\n}\n.tcw-stepper .tcw-indi-input::-webkit-inner-spin-button,\n.tcw-stepper .tcw-indi-input::-webkit-outer-spin-button { margin: 0; -webkit-appearance: none; }\n.tcw-stepper .tcw-indi-input:focus { outline: none; box-shadow: none; }\n.tcw-stepper-btn {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h);\n border: none;\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n}\n.tcw-stepper-btn:hover { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-stepper-btn:focus-visible { outline: none; background: var(--tcw-hover-bg); color: var(--tcw-text); }\n\n/* Forced colours drop the box-shadow rings: an outline marks focus and the chosen choice. */\n@media (forced-colors: active) {\n .tcw-segment[aria-checked='true'] { outline: 2px solid Highlight; }\n .tcw-segment:focus-visible,\n .tcw-stepper-btn:focus-visible { outline: 2px solid Highlight; outline-offset: -2px; }\n .tcw-stepper:focus-within { outline: 2px solid Highlight; }\n}\n", Zt = "/* === The indicators dialog === */\n\n/* 610 wide, a Fibonacci number: the groups take 233 and the list 377 beside them (377 : 233 = phi).\n A fixed height, so the dialog keeps still while a search shortens the list. */\n.tcw-modal.tcw-ip {\n width: 610px;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n.tcw-ip-search,\n.tcw-ss-search {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n height: var(--tcw-control-h);\n margin: var(--tcw-space-4) var(--tcw-space-6);\n padding: 0 var(--tcw-space-4);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text-muted);\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease), box-shadow var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ip-search:focus-within,\n.tcw-ss-search:focus-within {\n border-color: var(--tcw-accent);\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-ip-search svg,\n.tcw-ss-search svg {\n flex: none;\n}\n\n.tcw-ip-search input,\n.tcw-ss-search input {\n flex: 1;\n min-width: 0;\n height: 100%;\n border: none;\n outline: none;\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size);\n}\n\n.tcw-ip-search input::placeholder,\n.tcw-ss-search input::placeholder {\n color: var(--tcw-text-muted);\n}\n\n.tcw-ip-body {\n display: grid;\n grid-template-columns: 233px minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-ip-nav,\n.tcw-set-nav {\n display: flex;\n flex-direction: column;\n gap: 1px;\n padding: var(--tcw-space-4) var(--tcw-space-3);\n /* Logical sides: in Arabic, Hebrew or Persian the tabs sit on the right. */\n border-inline-end: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n overflow-y: auto;\n border-end-start-radius: var(--tcw-dialog-radius);\n}\n\n.tcw-ip-tab,\n.tcw-set-tab {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size);\n text-align: start;\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ip-tab svg,\n.tcw-set-tab svg {\n flex: none;\n}\n\n/* The kinds start below a gap: favourites and templates are yours, the rest the library's. */\n.tcw-ip-tab[data-view='all'] {\n margin-top: var(--tcw-space-4);\n}\n\n.tcw-ip-tab:hover,\n.tcw-set-tab:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-ip-tab.tcw-active,\n.tcw-set-tab.tcw-active {\n background: var(--tcw-on-bg);\n color: var(--tcw-on-fg);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-ip-nav--searching .tcw-ip-tab.tcw-active {\n background: transparent;\n color: var(--tcw-text-dim);\n font-weight: var(--tcw-weight);\n}\n\n.tcw-ip-list {\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0 var(--tcw-space-4) var(--tcw-space-5);\n}\n\n/* Each kind's name stays at the top while its indicators scroll under it. */\n.tcw-ip-heading {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: var(--tcw-space-5) var(--tcw-space-4) var(--tcw-space-2);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-ip-list > :first-child:not(.tcw-ip-heading) {\n margin-top: var(--tcw-space-4);\n}\n\n.tcw-ip-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n border-radius: var(--tcw-menu-item-radius);\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ip-row:hover {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ip-add {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: 1;\n min-width: 0;\n height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size);\n text-align: start;\n cursor: pointer;\n}\n\n.tcw-ip-add:focus-visible,\n.tcw-ip-aside:focus-visible,\n.tcw-ip-tab:focus-visible,\n.tcw-set-tab:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-ip-add svg {\n flex: none;\n color: var(--tcw-text-muted);\n}\n\n.tcw-ip-name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-ip-short {\n flex: none;\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n}\n\n/* Where it draws, quietly at the row's end. */\n.tcw-ip-kind {\n flex: none;\n margin-inline-start: auto;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n/* How many are on the chart: ink on its wash, the figures in a column. */\n.tcw-ip-count {\n flex: none;\n display: inline-grid;\n place-items: center;\n min-width: var(--tcw-space-6);\n height: var(--tcw-space-6);\n padding: 0 var(--tcw-space-2);\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-accent-soft);\n color: var(--tcw-accent);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.tcw-ip-aside {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n/* Shown on the row in hand; always for a starred one, filled in ink; always on a touch screen. */\n.tcw-ip-row:hover .tcw-ip-aside,\n.tcw-ip-row:focus-within .tcw-ip-aside,\n.tcw-ip-star[aria-pressed='true'] {\n opacity: 1;\n}\n\n@media (hover: none) {\n .tcw-ip-aside {\n opacity: 1;\n }\n}\n\n.tcw-ip-aside:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ip-star[aria-pressed='true'] {\n color: var(--tcw-accent);\n}\n\n.tcw-ip-star[aria-pressed='true'] svg path {\n fill: currentColor;\n}\n\n.tcw-ip-remove:hover {\n color: var(--tcw-red);\n}\n\n.tcw-ip-save {\n flex: none;\n width: 100%;\n color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-ip-save svg {\n color: currentColor;\n}\n\n.tcw-ip-save:hover {\n background: var(--tcw-accent-soft);\n}\n\n.tcw-ip-empty {\n max-width: 34ch;\n padding: var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.5;\n text-wrap: pretty;\n}\n\n/* Heard by a screen reader, not seen. */\n.tcw-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* A phone: the dialog is the widget's sheet, as tall as a sheet goes, and the groups a row of chips. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-ip {\n /* Above the on-screen keyboard: the sheet's top stays on the screen. */\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-ip-search,\n .tcw-ss-search {\n margin-inline: var(--tcw-space-4);\n }\n\n .tcw-ip-body {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .tcw-ip-nav,\n .tcw-set-nav {\n flex-direction: row;\n gap: var(--tcw-space-2);\n padding: var(--tcw-space-3) var(--tcw-space-4);\n border-inline-end: none;\n border-bottom: 1px solid var(--tcw-divider);\n border-radius: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n }\n\n .tcw-ip-tab[data-view='all'] {\n margin-top: 0;\n margin-inline-start: var(--tcw-space-4);\n }\n\n .tcw-ip-tab,\n .tcw-set-tab {\n /* A finger's size, as the dialogs' other tabs on a phone. */\n min-height: 40px;\n border: var(--tcw-border-w) solid var(--tcw-border);\n }\n\n\n .tcw-ip-list {\n padding-inline: var(--tcw-space-3);\n }\n}\n\n/* === The indicator settings, and a drawing's === */\n\n/* One half step of phi under the indicators dialog: 610 / sqrt(phi) = 480. */\n@media (min-width: 641px) {\n .tcw-modal.tcw-modal-narrow.tcw-indi,\n .tcw-modal.tcw-modal-narrow.tcw-drawing-settings {\n width: 480px;\n max-width: 92vw;\n }\n}\n\n/* A line, or a kind of interval: ticked where it shows, its name, then what sets it. */\n.tcw-indi-plot-name {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-width: 0;\n cursor: pointer;\n}\n\n.tcw-indi-plot-name .tcw-settings-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Unticked, its name steps back. */\n.tcw-indi-plot-name:has(input:not(:checked)) .tcw-settings-label {\n color: var(--tcw-text-muted);\n}\n\n.tcw-indi-plot-controls,\n.tcw-indi-range {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n}\n\n/* A box ticked beside other controls in a row (bold, italics, a text box's background). */\n.tcw-inline-check {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-2);\n cursor: pointer;\n white-space: nowrap;\n}\n\n.tcw-indi-plot-controls .tcw-indi-select {\n width: 104px;\n}\n\n.tcw-indi-range {\n color: var(--tcw-text-muted);\n}\n\n.tcw-indi-range .tcw-indi-input {\n width: 68px;\n text-align: end;\n}\n\n.tcw-indi-range .tcw-indi-input:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Defaults on the left; Cancel and Ok on the right, one height for all three. */\n.tcw-indi .tcw-modal-footer,\n.tcw-set .tcw-modal-footer,\n.tcw-drawing-settings .tcw-modal-footer {\n gap: var(--tcw-space-4);\n}\n\n.tcw-footer-end {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n}\n\n.tcw-indi .tcw-modal-footer button,\n.tcw-set .tcw-modal-footer button,\n.tcw-drawing-settings .tcw-modal-footer button {\n height: var(--tcw-menu-item-h);\n padding-block: 0;\n}\n\n.tcw-footer-menu,\n.tcw-footer-cancel {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-2);\n padding-inline: var(--tcw-space-5);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-footer-cancel {\n border-color: var(--tcw-border-strong);\n color: var(--tcw-text);\n}\n\n.tcw-footer-menu:hover,\n.tcw-footer-menu[aria-expanded='true'],\n.tcw-footer-cancel:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-footer-menu:focus-visible,\n.tcw-footer-cancel:focus-visible,\n.tcw-indi .tcw-done-btn:focus-visible,\n.tcw-set .tcw-done-btn:focus-visible,\n.tcw-drawing-settings .tcw-done-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A drawing's switches: the box, then its name, a list without rules between. */\n.tcw-check-row {\n justify-content: flex-start;\n gap: var(--tcw-space-4);\n padding-block: var(--tcw-space-3);\n cursor: pointer;\n}\n\n.tcw-settings-row + .tcw-check-row,\n.tcw-check-row + .tcw-settings-row {\n border-top: 0;\n}\n\n/* A point: its name, then its price, date and time in columns; on a phone the price over the date and time. */\n.tcw-draw-point {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr);\n gap: var(--tcw-space-4);\n}\n\n.tcw-draw-point > .tcw-settings-label {\n white-space: nowrap;\n}\n\n.tcw-draw-point .tcw-indi-plot-controls {\n display: contents;\n}\n\n.tcw-draw-point input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n}\n\n.tcw-draw-point input[type='number'] {\n text-align: end;\n}\n\n@media (max-width: 640px) {\n .tcw-draw-point {\n grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);\n }\n\n .tcw-draw-point > .tcw-settings-label {\n grid-row: span 2;\n }\n\n .tcw-draw-point input[type='number'] {\n grid-column: span 2;\n }\n}\n\n.tcw-drawing-settings .tcw-indi-plot-controls input[type='number']:not(.tcw-draw-point *) {\n width: 68px;\n text-align: end;\n}\n\n/* The unit after a number (the fill's opacity in %). */\n.tcw-unit {\n margin-inline-start: calc(-1 * var(--tcw-space-2));\n color: var(--tcw-text-muted);\n}\n\n/* === The chart settings === */\n\n/* 776 x 610: half a step of phi wider than the indicators dialog (610 x sqrt(phi) = 776), as tall as it,\n so the dialog is a sqrt(phi) rectangle. The tabs take 233 down the side, as the indicator groups do. */\n.tcw-modal.tcw-set {\n width: 776px;\n max-width: 94vw;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n.tcw-set-body {\n display: grid;\n grid-template-columns: 233px minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n}\n\n.tcw-set-panel {\n min-width: 0;\n}\n\n/* A phone: the widget's sheet across the screen, the tabs a row of chips over the settings. After the rules above, which it overrides. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-set {\n width: 100vw;\n max-width: 100vw;\n /* Above the on-screen keyboard: the sheet's top stays on the screen. */\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-set-body {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n}\n\n/* === The symbol search, and the same dialog comparing === */\n\n/* As wide and as still as the indicators dialog: 610, a fixed height while a search shortens the list. */\n.tcw-modal.tcw-ss {\n width: 610px;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n/* Comparing: how the next symbol goes on the chart, under the search. */\n.tcw-ss-way {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n flex: none;\n margin: 0 var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n\n.tcw-ss-way > span {\n flex: none;\n}\n\n.tcw-root .tcw-ss-way-select {\n flex: 1;\n min-width: 0;\n height: var(--tcw-control-h);\n padding-block: 0;\n}\n\n/* The heads' height, which the rows scroll in below. */\n.tcw-modal.tcw-ss {\n --tcw-ss-head-h: var(--tcw-control-h);\n}\n\n/* Over the list: the kinds the rows come in, and their exchanges once there are two. The exchanges sit\n on the tabs' first line when the tabs wrap, not between their lines. */\n.tcw-ss-filters {\n display: flex;\n align-items: flex-start;\n gap: var(--tcw-space-4);\n flex: none;\n margin: 0 var(--tcw-space-6) var(--tcw-space-4);\n}\n\n/* The kinds as tabs (All, stock, crypto…), showing the one picked as the look shows a choice. */\n.tcw-ss-kinds {\n display: flex;\n flex-wrap: wrap;\n flex: 1;\n min-width: 0;\n gap: var(--tcw-space-2);\n}\n\n/* Where they scroll in one line, the tabs fade out at an end with more past it, so a tab cut there\n reads as more to scroll to. A mask: only its alpha counts, so what shows is drawn in the text's\n colour, which is opaque, and what fades goes to transparent. */\n.tcw-ss-kinds[data-more] {\n --tcw-ss-shown: currentColor;\n --tcw-ss-fade-start: var(--tcw-ss-shown);\n --tcw-ss-fade-end: var(--tcw-ss-shown);\n -webkit-mask-image: linear-gradient(to right, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n mask-image: linear-gradient(to right, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n}\n\n[dir='rtl'] .tcw-ss-kinds[data-more] {\n -webkit-mask-image: linear-gradient(to left, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n mask-image: linear-gradient(to left, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n}\n\n.tcw-ss-kinds[data-more~='start'] {\n --tcw-ss-fade-start: transparent;\n}\n\n.tcw-ss-kinds[data-more~='end'] {\n --tcw-ss-fade-end: transparent;\n}\n\n.tcw-ss-type {\n flex: none;\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-5);\n border: none;\n border-radius: var(--tcw-tab-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n/* A feed's words as it wrote them (\"Cổ phiếu\" stays so), only the first letter raised. */\n.tcw-ss-type::first-letter {\n text-transform: uppercase;\n}\n\n.tcw-ss-type:hover {\n background: var(--tcw-tab-hover);\n color: var(--tcw-text);\n}\n\n.tcw-ss-type[aria-pressed='true'] {\n background: var(--tcw-tab-on-bg);\n color: var(--tcw-tab-on-fg);\n box-shadow: inset 0 calc(-1 * var(--tcw-tab-line)) 0 var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-ss-type:focus-visible,\n.tcw-ss-remove:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* The exchanges at the end of the row, as wide as the longest up to 144. */\n.tcw-root .tcw-ss-exchange-filter {\n flex: none;\n width: auto;\n max-width: 144px;\n height: var(--tcw-control-h);\n margin-inline-start: auto;\n padding-block: 0;\n font-size: var(--tcw-font-size-sm);\n}\n\n/* What scrolls is one grid, and the heads, the list and each row are its subgrids, so a column is\n as wide in every row: the badge, the symbol up to 144 (89 x phi), the name the rest, the kind and\n the exchange up to 89 each, the check. An empty cell keeps its column. */\n.tcw-ss-results {\n display: grid;\n grid-template-columns: max-content fit-content(144px) minmax(0, 1fr) fit-content(89px) fit-content(89px) auto;\n align-content: start;\n column-gap: var(--tcw-space-4);\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n /* A row the arrows reach scrolls in below the heads, not under them. */\n scroll-padding-block-start: calc(var(--tcw-ss-head-h) + var(--tcw-space-2));\n padding: 0 var(--tcw-space-4) var(--tcw-space-5);\n}\n\n/* Comparing, under a heading of its own as well. */\n.tcw-ss--compare .tcw-ss-results {\n scroll-padding-block-start: calc(var(--tcw-ss-head-h) + var(--tcw-space-5) + var(--tcw-space-2) + var(--tcw-font-size-xs) * 1.5);\n}\n\n.tcw-ss-results > * {\n grid-column: 1 / -1;\n}\n\n.tcw-ss-columns,\n.tcw-ss-list,\n.tcw-ss-added,\n.tcw-ss-row,\n.tcw-ss-added-row {\n display: grid;\n grid-column: 1 / -1;\n /* Where subgrids aren't drawn: fixed columns, the rest sized row by row. */\n grid-template-columns: var(--tcw-control-h-sm) 89px minmax(0, 1fr) auto auto auto;\n grid-template-columns: subgrid;\n align-items: center;\n column-gap: inherit;\n}\n\n/* The heads stay at the top while the rows scroll under them. */\n.tcw-ss-columns {\n position: sticky;\n top: 0;\n z-index: 2;\n height: var(--tcw-ss-head-h);\n margin-bottom: var(--tcw-space-2);\n padding: 0 var(--tcw-space-4);\n background: var(--tcw-bg-elevated);\n box-shadow: 0 1px 0 var(--tcw-divider);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n white-space: nowrap;\n}\n\n.tcw-ss-head {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-ss-head:nth-child(1) { grid-column: 1; }\n.tcw-ss-head:nth-child(2) { grid-column: 2; }\n.tcw-ss-head:nth-child(3) { grid-column: 3; }\n.tcw-ss-head:nth-child(4) { grid-column: 4; justify-self: end; }\n.tcw-ss-head:nth-child(5) { grid-column: 5; justify-self: end; }\n\n.tcw-ss-row {\n min-height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border-radius: var(--tcw-menu-item-radius);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ss-row.tcw-selected {\n background: var(--tcw-hover-bg);\n}\n\n/* The logo, or the ticker's first letter on a tint of its kind's colour, cornered as the look's tags. */\n.tcw-ss-badge {\n --tcw-ss-kind: var(--tcw-text-dim);\n grid-column: 1;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n overflow: hidden;\n border-radius: var(--tcw-tag-radius);\n background: color-mix(in srgb, var(--tcw-ss-kind) 16%, transparent);\n color: var(--tcw-ss-kind);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n line-height: 1;\n}\n\n.tcw-ss-badge[data-kind='1'] { --tcw-ss-kind: var(--tcw-kind-1); }\n.tcw-ss-badge[data-kind='2'] { --tcw-ss-kind: var(--tcw-kind-2); }\n.tcw-ss-badge[data-kind='3'] { --tcw-ss-kind: var(--tcw-kind-3); }\n.tcw-ss-badge[data-kind='4'] { --tcw-ss-kind: var(--tcw-kind-4); }\n.tcw-ss-badge[data-kind='5'] { --tcw-ss-kind: var(--tcw-kind-5); }\n\nimg.tcw-ss-badge {\n background: transparent;\n object-fit: cover;\n}\n\n/* The figures of a ticker, in the mono face, left to right in any widget, at the start of its column;\n the chart's own in ink. */\n.tcw-ss-symbol {\n grid-column: 2;\n display: flex;\n justify-self: start;\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text);\n font-family: var(--tcw-font-mono);\n font-weight: var(--tcw-weight-strong);\n white-space: nowrap;\n}\n\n/* A venue before the ticker (\"BINANCE:\"), dim, is what a narrow column shortens; the ticker never\n shrinks (a share of a pixel would end it in an ellipsis), and is cut only when it alone is wider.\n A gap keeps the venue's ellipsis off the ticker (\"HYPERLIQ… GOLD\"). */\n.tcw-ss-venue {\n flex: 0 1 auto;\n min-width: 0;\n margin-inline-end: var(--tcw-space-1);\n overflow: hidden;\n color: var(--tcw-text-muted);\n font-weight: var(--tcw-weight);\n text-overflow: ellipsis;\n}\n\n.tcw-ss-ticker {\n flex: none;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-ss-row.tcw-current .tcw-ss-symbol {\n color: var(--tcw-accent);\n}\n\n.tcw-ss-symbol mark {\n background: transparent;\n color: var(--tcw-accent);\n}\n\n.tcw-ss-desc-cell {\n grid-column: 3;\n min-width: 0;\n}\n\n/* As wide as its words, at the start of the column, whichever way they run. */\n.tcw-ss-desc {\n display: block;\n width: fit-content;\n max-width: 100%;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-size: var(--tcw-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* The kind as the feed wrote it, and the exchange, each at the end of its column. */\n.tcw-ss-kind,\n.tcw-ss-exchange {\n justify-self: end;\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n font-size: var(--tcw-font-size-xs);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-ss-kind {\n grid-column: 4;\n color: var(--tcw-text-muted);\n}\n\n.tcw-ss-exchange {\n grid-column: 5;\n color: var(--tcw-text-dim);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n/* The chart's symbol, or one on it already: a check in the last column. */\n.tcw-ss-check {\n grid-column: 6;\n display: inline-grid;\n place-items: center;\n color: var(--tcw-accent);\n}\n\n.tcw-ss-heading[hidden] {\n display: none;\n}\n\n/* \"On the chart\" and \"Symbols\", under the heads while their rows scroll. */\n.tcw-ss-heading {\n position: sticky;\n top: var(--tcw-ss-head-h);\n z-index: 1;\n padding: var(--tcw-space-5) var(--tcw-space-4) var(--tcw-space-2);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-ss-added-row {\n min-height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border-radius: var(--tcw-menu-item-radius);\n}\n\n.tcw-ss-added-row:hover {\n background: var(--tcw-hover-bg);\n}\n\n/* How it is compared, across the name, kind and exchange; the line's colour, where it has one of its own, where the badges are. */\n.tcw-ss-way-cell {\n grid-column: 3 / 6;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-width: 0;\n}\n\n.tcw-ss-swatch {\n grid-column: 1;\n justify-self: center;\n width: var(--tcw-space-4);\n height: var(--tcw-space-4);\n border-radius: var(--tcw-radius-sm);\n}\n\n.tcw-ss-way-label {\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-size: var(--tcw-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-ss-remove {\n grid-column: 6;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n\n.tcw-ss-remove:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-red);\n}\n\n.tcw-ss-empty {\n max-width: 44ch;\n padding: var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.5;\n text-wrap: pretty;\n}\n\n/* Under a list cut short: how many more match, for typing to narrow. */\n.tcw-ss-more {\n padding: var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.5;\n}\n\n/* The way the dialog opens too: a letter typed on the chart. */\n.tcw-ss-foot {\n flex: none;\n padding: var(--tcw-space-5) var(--tcw-space-6);\n border-top: 1px solid var(--tcw-divider);\n border-radius: 0 0 var(--tcw-dialog-radius) var(--tcw-dialog-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n text-align: center;\n}\n\n/* === Go to === */\n\n/* 377: the step of phi under the search dialogs. */\n@media (min-width: 641px) {\n .tcw-modal.tcw-goto {\n width: 377px;\n }\n}\n\n.tcw-goto-form {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n\n.tcw-goto-fields {\n display: grid;\n gap: var(--tcw-space-5);\n padding: var(--tcw-space-6) var(--tcw-space-6) var(--tcw-space-4);\n}\n\n/* The date takes the room; the time 144 beside it; a range's end named above its two. */\n.tcw-goto-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 144px;\n gap: var(--tcw-space-3) var(--tcw-space-4);\n align-items: center;\n}\n\n.tcw-goto-label {\n grid-column: 1 / -1;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-root .tcw-goto-input {\n width: 100%;\n min-width: 0;\n height: var(--tcw-control-h);\n box-sizing: border-box;\n padding: 0 var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n font-variant-numeric: tabular-nums;\n}\n\n/* No time on daily bars: the date across the row. */\n.tcw-goto-input[type='date']:last-child {\n grid-column: 1 / -1;\n}\n\n/* The month under the fields, part of the dialog: no card of its own. */\n.tcw-calendar.tcw-goto-calendar {\n position: static;\n width: auto;\n padding: var(--tcw-space-4) var(--tcw-space-6) var(--tcw-space-5);\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n animation: none;\n}\n\n.tcw-goto-calendar .tcw-calendar-day {\n height: 34px;\n}\n\n.tcw-goto .tcw-modal-footer {\n justify-content: flex-end;\n gap: var(--tcw-space-4);\n}\n\n.tcw-goto .tcw-modal-footer button {\n height: var(--tcw-menu-item-h);\n padding-block: 0;\n}\n\n.tcw-goto .tcw-done-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A phone: both are the widget's sheet; the search as tall as a sheet goes, its symbols up to 89\n wide. The kind's column goes (the badge's colour still tells it), the tabs scroll in one line, and\n a row is a finger's height. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-ss {\n /* Above the on-screen keyboard: the sheet's top stays on the screen. */\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-ss-way,\n .tcw-ss-filters {\n margin-inline: var(--tcw-space-4);\n }\n\n .tcw-ss-kinds {\n flex-wrap: nowrap;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .tcw-ss-kinds::-webkit-scrollbar {\n display: none;\n }\n\n .tcw-root .tcw-ss-exchange-filter {\n max-width: 110px;\n }\n\n /* The ticker is the row's key: its column as wide as the widest ticker, up to 144 or 38.2% of the\n row, and the name gives way first. The exchange's up to 55, each cut in its own row. */\n .tcw-ss-results {\n grid-template-columns: max-content fit-content(min(144px, 38.2%)) minmax(0, 1fr) fit-content(55px) auto;\n }\n\n /* A venue counts for nothing in that width (its own is 0): it shows, dim and shortened, in what\n its ticker leaves, if that is 2em, a letter and an ellipsis as on the toolbar. With less, it\n wraps to a second line the cell clips, never a sliver (\"H.GOLD\"). The ticker comes first in the\n line, laid from the end, so it is the one that stays, at the column's start when alone. */\n .tcw-ss-symbol {\n justify-self: stretch;\n flex-direction: row-reverse;\n flex-wrap: wrap;\n justify-content: flex-end;\n align-content: flex-start;\n height: 1lh;\n }\n\n .tcw-ss-ticker {\n order: -1;\n }\n\n .tcw-ss-venue {\n flex: 1 1 2em;\n width: 0;\n }\n\n /* The head over the exchanges reads whole, over the gap before it if it must. */\n .tcw-ss-head:nth-child(5) {\n overflow: visible;\n }\n\n .tcw-ss-columns,\n .tcw-ss-list,\n .tcw-ss-added,\n .tcw-ss-row,\n .tcw-ss-added-row {\n grid-template-columns: var(--tcw-control-h-sm) 89px minmax(0, 1fr) auto auto;\n grid-template-columns: subgrid;\n }\n\n .tcw-ss-kind,\n .tcw-ss-head:nth-child(4) {\n display: none;\n }\n\n .tcw-ss-exchange,\n .tcw-ss-head:nth-child(5) {\n grid-column: 4;\n }\n\n .tcw-ss-check,\n .tcw-ss-remove {\n grid-column: 5;\n }\n\n .tcw-ss-way-cell {\n grid-column: 3 / 5;\n }\n\n .tcw-ss-row,\n .tcw-ss-added-row {\n min-height: 44px;\n }\n}\n\n/* Without a keyboard there are no letters to type on the chart. */\n@media (hover: none) and (pointer: coarse) {\n .tcw-ss-foot {\n display: none;\n }\n}\n\n/* === The shortcut sheet === */\n\n/* As wide and as still as the indicators dialog: 610, a fixed height while a search shortens the list. */\n.tcw-modal.tcw-hotkey-sheet {\n width: 610px;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n.tcw-hotkey-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0 var(--tcw-space-6) var(--tcw-space-5);\n border-top: 1px solid var(--tcw-divider);\n}\n\n/* Two columns as tall as their groups, inside the box that scrolls: on the box itself, of a fixed\n height, the groups past its foot went into columns to the side, out of reach. */\n.tcw-hotkey-columns {\n columns: 2;\n column-gap: var(--tcw-space-7);\n}\n\n/* A group keeps together in its column, its name above its rows. */\n.tcw-hotkey-group {\n break-inside: avoid;\n padding-top: var(--tcw-space-5);\n}\n\n.tcw-hotkey-heading {\n padding-bottom: var(--tcw-space-3);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n/* What it does on the left, its keys on the right, the keys in a column of their own. */\n.tcw-hotkey-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--tcw-space-4);\n min-height: calc(var(--tcw-space-6) + var(--tcw-space-3));\n padding: var(--tcw-space-2) 0;\n}\n\n.tcw-hotkey-label {\n min-width: 0;\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.4;\n}\n\n.tcw-hotkey-keys {\n display: inline-flex;\n align-items: baseline;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--tcw-space-2);\n flex: none;\n max-width: 55%;\n}\n\n/* A key: its name in the mono face on a key's face. */\n.tcw-hotkey-key,\n.tcw-cp-key {\n display: inline-block;\n min-width: calc(var(--tcw-space-6) - var(--tcw-space-2));\n padding: 0 var(--tcw-space-3);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-bottom-width: 2px;\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text-dim);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.6;\n text-align: center;\n white-space: nowrap;\n}\n\n/* A gesture is not a key: its words, quieter. */\n.tcw-hotkey-gesture {\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n white-space: nowrap;\n}\n\n.tcw-hotkey-sep {\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n}\n\n.tcw-hotkey-empty {\n padding: var(--tcw-space-6) 0;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n\n/* How to open it again, at its foot. */\n.tcw-hotkey-foot {\n flex: none;\n padding: var(--tcw-space-5) var(--tcw-space-6);\n border-top: 1px solid var(--tcw-divider);\n border-radius: 0 0 var(--tcw-dialog-radius) var(--tcw-dialog-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n}\n\n/* === The command palette === */\n\n/* 610 wide, a third of the way down: a launcher, not a form; its search is the dialogs' search row. */\n.tcw-modal.tcw-cp {\n top: 19.1%;\n transform: translate(-50%, 0);\n width: 610px;\n max-height: min(610px, 76.4vh);\n max-height: min(610px, 76.4dvh);\n animation: none;\n}\n\n.tcw-cp .tcw-cp-search {\n margin-top: var(--tcw-space-5);\n}\n\n.tcw-cp-results {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n /* A row the arrows reach scrolls in below its group's heading, not under it. */\n scroll-padding-block-start: calc(var(--tcw-space-5) + var(--tcw-space-2) + var(--tcw-font-size-xs) * 1.5);\n padding: 0 var(--tcw-space-4) var(--tcw-space-4);\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-cp-heading {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: var(--tcw-space-5) var(--tcw-space-4) var(--tcw-space-2);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-cp-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border-radius: var(--tcw-menu-item-radius);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size);\n cursor: pointer;\n}\n\n.tcw-cp-row.tcw-selected {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-cp-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* What is on now: its name in ink, a check at the end. */\n.tcw-cp-row.tcw-on .tcw-cp-label {\n color: var(--tcw-accent);\n}\n\n.tcw-cp-check {\n display: inline-grid;\n place-items: center;\n flex: none;\n color: var(--tcw-accent);\n}\n\n.tcw-cp-empty {\n padding: var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n\n/* === Layouts === */\n\n/* 480, as the settings of an indicator: a list of names and when they were saved. On a phone, the sheet's width. */\n.tcw-modal.tcw-layouts-dialog {\n max-height: min(610px, 86vh);\n max-height: min(610px, 86dvh);\n}\n@media (min-width: 641px) {\n .tcw-modal.tcw-layouts-dialog { width: 480px; }\n}\n\n.tcw-layouts-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: var(--tcw-space-3) var(--tcw-space-4) var(--tcw-space-5);\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-layouts-list {\n display: flex;\n flex-direction: column;\n gap: var(--tcw-space-1);\n}\n\n.tcw-layouts-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-2);\n padding-inline-end: var(--tcw-space-3);\n border-radius: var(--tcw-menu-item-radius);\n}\n\n.tcw-layouts-row:hover,\n.tcw-layouts-row:focus-within {\n background: var(--tcw-hover-bg);\n}\n\n/* A column for the check of the one open, so every name starts at the same place. */\n.tcw-layouts-open {\n display: grid;\n grid-template-columns: var(--tcw-space-5) minmax(0, 1fr);\n column-gap: var(--tcw-space-3);\n align-items: center;\n flex: 1;\n min-width: 0;\n padding: var(--tcw-space-3) var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n.tcw-layouts-open:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-layouts-name,\n.tcw-layouts-meta {\n grid-column: 2;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-layouts-name {\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-layouts-meta {\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.tcw-layouts-check {\n display: inline-grid;\n place-items: center;\n grid-column: 1;\n grid-row: 1 / span 2;\n color: var(--tcw-accent);\n}\n\n.tcw-layouts-open[aria-current='true'] .tcw-layouts-name {\n color: var(--tcw-accent);\n}\n\n/* Rename and delete show on the row in hand; always on a touch screen. */\n.tcw-layouts-row .tcw-account-actions {\n display: flex;\n gap: var(--tcw-space-1);\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-layouts-row:is(:hover, :focus-within) .tcw-account-actions,\n.tcw-layouts-row .tcw-account-actions:has(.tcw-layouts-confirm) {\n opacity: 1;\n}\n\n@media (hover: none) {\n .tcw-layouts-row .tcw-account-actions {\n opacity: 1;\n }\n}\n\n.tcw-layouts-confirm {\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-red);\n /* The accent fill's ink reads on the red too: dark on the dark theme's, white on the light's. */\n color: var(--tcw-accent-ink);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n}\n\n.tcw-layouts-confirm:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A phone: the sheets as tall as they go, the shortcuts in one column. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-hotkey-sheet {\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-hotkey-body {\n padding-inline: var(--tcw-space-4);\n }\n\n .tcw-hotkey-columns {\n columns: 1;\n }\n\n /* Their own heights outrank the sheet's: give them back its height, less the keyboard, and the palette its slide up. */\n .tcw-modal.tcw-cp,\n .tcw-modal.tcw-layouts-dialog {\n max-height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n max-height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-modal.tcw-cp {\n top: auto;\n transform: none;\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\n }\n\n .tcw-cp .tcw-cp-search {\n margin-top: var(--tcw-space-3);\n }\n\n :is(.tcw-hotkey-search, .tcw-cp-search, .tcw-layouts-search-row) {\n margin-inline: var(--tcw-space-4);\n }\n\n .tcw-cp-row {\n min-height: 44px;\n }\n}\n\n/* === The order ticket === */\n\n/* 480, as a drawing's settings: the side, the order, its stop and target, then the receipt. On a phone, the sheet's width. */\n.tcw-modal.tcw-order-ticket {\n max-height: min(610px, 92vh);\n max-height: min(610px, 92dvh);\n}\n@media (min-width: 641px) {\n .tcw-modal.tcw-order-ticket { width: 480px; }\n}\n.tcw-order-ticket[data-side='buy'] { --tcw-side: var(--tcw-green); }\n.tcw-order-ticket[data-side='sell'] { --tcw-side: var(--tcw-red); }\n\n.tcw-ticket-heading {\n display: flex;\n align-items: baseline;\n gap: var(--tcw-space-4);\n min-width: 0;\n}\n.tcw-ticket-symbol {\n overflow: hidden;\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.tcw-ticket-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n/* Buy and Sell: the chosen one filled with its colour, the ground's own colour on it. */\n.tcw-ticket-side {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--tcw-space-3);\n margin-bottom: var(--tcw-space-4);\n}\n.tcw-ticket-side-btn {\n height: 34px;\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size-lg);\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-ticket-side-btn:hover { color: var(--tcw-text); }\n.tcw-ticket-buy[aria-pressed='true'] { border-color: var(--tcw-green); background: var(--tcw-green); color: var(--tcw-bg); }\n.tcw-ticket-sell[aria-pressed='true'] { border-color: var(--tcw-red); background: var(--tcw-red); color: var(--tcw-bg); }\n.tcw-ticket-side-btn:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n\n/* A row's control goes under its name when they don't fit side by side (a long choice at 320 px). */\n.tcw-ticket-row {\n flex-wrap: wrap;\n gap: var(--tcw-space-3) var(--tcw-space-5);\n}\n.tcw-ticket-market {\n color: var(--tcw-text-dim);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n/* A stop or a target: its switch, its name with how far it is under it, then its price. */\n.tcw-ticket-optional {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--tcw-space-4);\n}\n.tcw-ticket-optional-name {\n display: flex;\n flex-direction: column;\n gap: var(--tcw-space-1);\n min-width: 0;\n}\n.tcw-ticket-away {\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n overflow-wrap: anywhere;\n /* Left to right inside, but at the name's start in either direction (the column's, not its own). */\n align-self: flex-start;\n}\n\n/* The receipt: under a torn-paper rule, each sum a label and a figure in the mono type. */\n.tcw-ticket-summary:not(:empty) {\n display: grid;\n gap: var(--tcw-space-2);\n margin: 0 var(--tcw-space-6) var(--tcw-space-4);\n padding-top: var(--tcw-space-4);\n border-top: var(--tcw-border-w) dashed var(--tcw-border-strong);\n}\n.tcw-ticket-summary-row {\n display: flex;\n justify-content: space-between;\n gap: var(--tcw-space-5);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-ticket-figure {\n color: var(--tcw-text);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n.tcw-ticket-figure.tcw-ticket-up { color: var(--tcw-green); }\n.tcw-ticket-figure.tcw-ticket-down { color: var(--tcw-red); }\n\n.tcw-ticket-problems {\n padding: 0 var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-red);\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-ticket-problems p { margin: var(--tcw-space-1) 0; }\n\n/* Cancel and Place alone, at the end, as tall as each other. */\n.tcw-order-ticket .tcw-modal-footer { justify-content: flex-end; }\n.tcw-order-ticket .tcw-modal-footer button { height: var(--tcw-menu-item-h); padding-block: 0; }\n.tcw-ticket-place {\n height: var(--tcw-menu-item-h);\n padding-inline: var(--tcw-space-6);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-side, var(--tcw-accent));\n color: var(--tcw-bg);\n font: inherit;\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n}\n.tcw-ticket-place:hover:not(:disabled) { background: color-mix(in srgb, var(--tcw-side, var(--tcw-accent)) 86%, var(--tcw-text)); }\n.tcw-ticket-place:disabled { opacity: 0.45; cursor: not-allowed; }\n.tcw-ticket-place:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n\n/* A phone: the ticket is a sheet above the keyboard, its controls a finger's size. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-order-ticket {\n max-height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n max-height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n .tcw-stepper .tcw-indi-input { width: 96px; }\n .tcw-stepper-btn, .tcw-segment { min-width: 34px; }\n .tcw-segment { height: 34px; }\n .tcw-stepper { height: 38px; }\n}\n\n/* Forced colours drop the box-shadow rings: an outline marks focus and the chosen side. */\n@media (forced-colors: active) {\n .tcw-ticket-side-btn[aria-pressed='true'] { outline: 2px solid Highlight; }\n .tcw-ticket-place { border: 1px solid ButtonText; }\n .tcw-ticket-side-btn:focus-visible,\n .tcw-ticket-place:focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }\n}\n", Qt = "/* === The dock: the panels by the chart, and their rail === */\n\n/* In the body's row after the chart: the panel of the page open beside the chart, the rail at the outer edge\n (both mirror in a right-to-left widget). */\n.tcw-dock {\n position: relative;\n display: flex;\n flex: none;\n min-height: 0;\n}\n\n/* The rail: as wide as the drawing tools on the other side, its buttons as theirs. */\n.tcw-dock-rail {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--tcw-space-2);\n width: var(--tcw-sidebar-w);\n padding: var(--tcw-space-3) 0;\n border-inline-start: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n}\n\n.tcw-dock-btn {\n display: inline-grid;\n place-items: center;\n flex: none;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-dock-btn svg {\n width: var(--tcw-icon);\n height: var(--tcw-icon);\n}\n\n.tcw-dock-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n/* The page open: in ink on its wash, as a tool in use on the other side. */\n.tcw-dock-btn[aria-pressed='true'] {\n background: var(--tcw-on-icon-bg, var(--tcw-accent-soft));\n color: var(--tcw-on-icon-fg, var(--tcw-accent));\n}\n\n.tcw-dock-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* The edge in focus shows as its line, in ink: a ring round a strip this thin reads as two lines. */\n.tcw-dock-resize:focus-visible {\n outline: none;\n}\n\n@media (forced-colors: active) {\n .tcw-dock-resize:is(:hover, :active, :focus-visible)::after {\n background: Highlight;\n }\n}\n\n/* The panel: 296 wide to start (377 / sqrt(phi)), from 233 to 377. */\n.tcw-dock-panel {\n position: relative;\n display: flex;\n flex-direction: column;\n width: var(--tcw-dock-w, 296px);\n min-height: 0;\n border-inline-start: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n}\n\n/* Its edge by the chart: a strip to drag, a line in ink while in hand. */\n.tcw-dock-resize {\n position: absolute;\n inset-block: 0;\n inset-inline-start: calc(var(--tcw-space-3) * -1);\n z-index: 3;\n width: calc(var(--tcw-space-3) * 2);\n cursor: col-resize;\n touch-action: none;\n}\n\n.tcw-dock-resize::after {\n content: '';\n position: absolute;\n inset-block: 0;\n inset-inline-start: calc(var(--tcw-space-3) - 1px);\n width: 2px;\n background: transparent;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-dock-resize:hover::after,\n.tcw-dock-resize:active::after,\n.tcw-dock-resize:focus-visible::after {\n background: var(--tcw-accent);\n}\n\n/* A page's header: 34 tall (21 + 13), or a control's height where that is more, and the rule under\n it. Its height and the page's scroll padding are both these, so they never part. */\n.tcw-dock-page {\n --tcw-dock-head-h: max(calc(var(--tcw-space-6) + var(--tcw-space-5)), var(--tcw-control-h));\n --tcw-dock-head-rule: 1px;\n}\n\n/* A page fills the panel and scrolls under its header; the floating panels it was lose their card. */\n.tcw-dock-panel > .tcw-dock-page {\n position: static;\n inset: auto;\n display: flex;\n flex-direction: column;\n flex: 1;\n width: auto;\n max-width: none;\n max-height: none;\n min-height: 0;\n margin: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n /* A row the keyboard moves to scrolls in below the header and its rule, not under them. */\n scroll-padding-block-start: calc(var(--tcw-dock-head-h) + var(--tcw-dock-head-rule));\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n animation: none;\n}\n\n/* One header for every page: its title, its own buttons, and the close at the end. */\n.tcw-dock-page > :is(.tcw-watchlist-header, .tcw-alerts-header, .tcw-tree-header, .tcw-datawin-header, .tcw-syminfo-header, .tcw-ladder-header) {\n position: sticky;\n top: 0;\n z-index: 2;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-2);\n flex: none;\n min-height: var(--tcw-dock-head-h);\n margin: 0;\n padding-block: 0;\n padding-inline: var(--tcw-space-5) var(--tcw-space-3);\n border-bottom: var(--tcw-dock-head-rule) solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-dock-page > :is(.tcw-alerts-header, .tcw-tree-header, .tcw-datawin-header, .tcw-syminfo-header) > span:first-child {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-dock-page :is(.tcw-watchlist-add, .tcw-watchlist-close, .tcw-alerts-close, .tcw-tree-close, .tcw-datawin-close, .tcw-syminfo-close, .tcw-ladder-close) {\n display: inline-grid;\n place-items: center;\n flex: none;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n\n.tcw-dock-page :is(.tcw-watchlist-add, .tcw-watchlist-close, .tcw-alerts-close, .tcw-tree-close, .tcw-datawin-close, .tcw-syminfo-close, .tcw-ladder-close):hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-dock-page :is(.tcw-watchlist-add, .tcw-watchlist-close, .tcw-alerts-close, .tcw-tree-close, .tcw-datawin-close, .tcw-syminfo-close, .tcw-ladder-close):focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* What scrolled in a box of its own on a floating panel scrolls with the page here (a phone's caps too). */\n.tcw-dock-page :is(.tcw-alerts-list, .tcw-datawin-body, .tcw-watchlist-list, .tcw-tree-list) {\n max-height: none;\n overflow-y: visible;\n}\n\n.tcw-dock-page .tcw-watchlist-list {\n flex: 1;\n}\n\n/* The watchlist was a bar of its own: its width and shadow are the panel's now. It scrolls as a page\n (no overflow of its own here: this rule, as specific as the page's and later, would win). */\n.tcw-dock-panel > .tcw-watchlist {\n width: auto;\n border-inline-start: none;\n box-shadow: none;\n}\n\n/* The symbol info's own padding sits under the header. */\n.tcw-dock-page.tcw-syminfo > .tcw-syminfo-body {\n padding: var(--tcw-space-5);\n}\n\n/* Narrow (a phone, a narrow column): no rail; the panel rises from the bottom over the chart, 61.8% tall. */\n.tcw-root[data-tcw-narrow] .tcw-dock-rail,\n.tcw-root[data-tcw-narrow] .tcw-dock-resize {\n display: none;\n}\n\n.tcw-root[data-tcw-narrow] .tcw-dock {\n position: static;\n}\n\n/* Above the chart's lines and tags, under its toasts; above the on-screen keyboard. */\n.tcw-root[data-tcw-narrow] .tcw-dock-panel {\n position: absolute;\n inset-inline: 0;\n bottom: var(--tcw-keyboard-inset, 0px);\n z-index: 38;\n width: auto;\n height: 61.8%;\n max-height: calc(100% - var(--tcw-keyboard-inset, 0px));\n border-inline-start: none;\n border-top: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 0 0;\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-dialog-shadow);\n padding-bottom: env(safe-area-inset-bottom, 0px);\n}\n\n.tcw-root[data-tcw-narrow] .tcw-dock-page > :is(.tcw-watchlist-header, .tcw-alerts-header, .tcw-tree-header, .tcw-datawin-header, .tcw-syminfo-header, .tcw-ladder-header) {\n background: var(--tcw-bg-elevated);\n}\n\n/* The small buttons in a panel's rows: the browser's padding left their icons 8 px wide in a 20 px button. */\n:is(.tcw-tree-btn, .tcw-tree-add, .tcw-alerts-del, .tcw-watchlist-remove) {\n padding: 0;\n}\n\n:is(.tcw-tree-btn, .tcw-tree-add, .tcw-alerts-del, .tcw-watchlist-remove) svg {\n flex: none;\n}\n\n/* A page's title as the others': the watchlist's is its list's name, a menu. */\n.tcw-dock-page .tcw-watchlist-name {\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-3);\n margin-inline-start: calc(var(--tcw-space-3) * -1);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n text-transform: none;\n letter-spacing: normal;\n flex: 0 1 auto;\n}\n\n/* Its caret beside the name, the add and close buttons at the end. */\n.tcw-dock-page .tcw-watchlist-name::after {\n margin-inline-start: var(--tcw-space-3);\n}\n\n.tcw-dock-page .tcw-watchlist-add {\n margin-inline-start: auto;\n}\n\n/* === The depth ladder, a page of the dock === */\n\n.tcw-ladder-title {\n flex: 1;\n min-width: 0;\n margin: 0;\n overflow: hidden;\n font: inherit;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n/*\n * Bid, price, ask: under the header, in the label case. The heading and each\n * row are grids of their own, so their columns are fixed shares: a row's\n * content (a mark of your orders) never moves its column off the others'.\n */\n.tcw-ladder-cols,\n.tcw-ladder-row {\n --tcw-ladder-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr);\n}\n.tcw-ladder-cols {\n position: sticky;\n top: calc(var(--tcw-space-6) + var(--tcw-space-5));\n z-index: 1;\n display: grid;\n grid-template-columns: var(--tcw-ladder-columns);\n align-items: center;\n height: var(--tcw-space-6);\n padding-inline: var(--tcw-space-3);\n border-bottom: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n.tcw-ladder-cols span:first-child { text-align: end; padding-inline-end: var(--tcw-space-4); }\n.tcw-ladder-cols span:nth-child(2) { text-align: center; }\n.tcw-ladder-cols span:last-child { padding-inline-start: var(--tcw-space-4); }\n\n.tcw-ladder-body { flex: 1; padding-inline: var(--tcw-space-3); }\n\n/* A row 21 tall: the bid's size, the price, the ask's size, in the mono figures. */\n.tcw-ladder-row {\n display: grid;\n grid-template-columns: var(--tcw-ladder-columns);\n height: var(--tcw-space-6);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n}\n/* A side's size over a bar grown from the price outward, as long as its share of the largest. */\n.tcw-ladder-cell {\n position: relative;\n isolation: isolate;\n display: flex;\n align-items: center;\n min-width: 0;\n padding-inline: var(--tcw-space-4);\n border: none;\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n cursor: pointer;\n}\n.tcw-ladder-cell::before {\n content: '';\n position: absolute;\n inset-block: 2px;\n z-index: -1;\n width: var(--w, 0%);\n border-radius: 1px;\n}\n.tcw-ladder-bid { justify-content: flex-end; }\n.tcw-ladder-bid::before { inset-inline-end: 0; background: var(--tcw-green-soft); }\n.tcw-ladder-ask { justify-content: flex-start; }\n.tcw-ladder-ask::before { inset-inline-start: 0; background: var(--tcw-red-soft); }\n.tcw-ladder-cell:not(:disabled):hover { background: var(--tcw-hover-bg); }\n.tcw-ladder-cell:disabled { cursor: default; }\n.tcw-ladder-cell:focus-visible { outline: none; box-shadow: inset var(--tcw-ring); }\n.tcw-ladder-price {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--tcw-space-2);\n min-width: 0;\n overflow: hidden;\n padding-inline: var(--tcw-space-3);\n border-inline: 1px solid var(--tcw-divider);\n white-space: nowrap;\n}\n.tcw-ladder-price.tcw-ask { color: var(--tcw-red); }\n.tcw-ladder-price.tcw-bid { color: var(--tcw-green); }\n/* Your orders at a price: their quantity, stamped in the side's colour. */\n.tcw-ladder-own {\n flex: none;\n padding-inline: var(--tcw-space-2);\n border-radius: 2px;\n color: var(--tcw-bg);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n}\n.tcw-ladder-own[data-side='buy'] { background: var(--tcw-green); }\n.tcw-ladder-own[data-side='sell'] { background: var(--tcw-red); }\n/* The spread, between the asks and the bids, on a torn-paper rule. */\n.tcw-ladder-spread {\n display: flex;\n align-items: center;\n justify-content: center;\n height: var(--tcw-space-6);\n border-block: 1px dashed var(--tcw-border-strong);\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n.tcw-ladder-empty {\n padding: var(--tcw-space-6);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n text-align: center;\n}\n\n/* Narrow (a finger, not a pointer): rows a control tall, 26 not 21. */\n.tcw-root[data-tcw-narrow] .tcw-ladder-row {\n height: var(--tcw-control-h);\n}\n\n/* Forced colours drop the bars' and the marks' fills: the bars show in the system's highlight, the marks framed. */\n@media (forced-colors: active) {\n .tcw-ladder-cell::before { forced-color-adjust: none; background: Highlight; opacity: 0.3; }\n .tcw-ladder-cell:focus-visible { outline: 2px solid Highlight; outline-offset: -2px; }\n .tcw-ladder-own { border: 1px solid CanvasText; }\n}\n", $t = /* @__PURE__ */ "toolbar,sidebar,statusBar,dock,alerts,objectTree,symbolInfo,symbolSearch,settings,indicatorSettings,drawingSettings,dataWindow,commandPalette,hotkeySheet,goToDate,replay,screenshot,copyImage,shareView,autoFib,themeToggle,fullscreen,accountPanel,orderTicket,bracketOrders,depthLadder,layouts,indicatorTemplates,compare,indicatorLegend,navigation,customTimeframes,intervalTyping,symbolTyping,dragDropImport,hotkeys,toasts,toolbar.symbol,toolbar.symbolInfo,toolbar.timeframes,toolbar.timeframeMenu,toolbar.chartType,toolbar.indicators,toolbar.layouts,toolbar.replay,toolbar.bracketOrders,toolbar.depthLadder,toolbar.accountPanel,toolbar.objectTree,toolbar.alerts,toolbar.screenshot,toolbar.settings,toolbar.themeToggle,toolbar.fullscreen,toolbar.compare,toolbar.undo,toolbar.redo,toolbar.trade,sidebar.cursor,sidebar.favorites,sidebar.lines,sidebar.fibonacci,sidebar.patterns,sidebar.forecasting,sidebar.annotation,sidebar.style,sidebar.magnet,sidebar.eraser,sidebar.zoomArea,sidebar.stayInDrawing,sidebar.undo,sidebar.redo,sidebar.clear,sidebar.lockAll,sidebar.hideAll,dock.watchlist,dock.alerts,dock.objectTree,dock.dataWindow,dock.symbolInfo,dock.depthLadder,statusBar.range,statusBar.goToDate,statusBar.market,statusBar.connection,statusBar.symbol,statusBar.clock,statusBar.scale,statusBar.rangeTimeframe,indicatorLegend.values,indicatorLegend.visibility,indicatorLegend.settings,indicatorLegend.remove,indicatorLegend.more,pane.move,pane.collapse,pane.maximize,navigation.zoom,navigation.scroll,navigation.reset,menu.chart,menu.chart.alert,menu.chart.order,menu.chart.orderTicket,menu.chart.horizontalLine,menu.chart.resetView,menu.chart.drawings,menu.chart.exportData,menu.chart.settings,menu.chart.scale,menu.chart.goToDate,menu.chart.paneScale,menu.priceAxisAdd,menu.chart.indicators,menu.chart.timezone,menu.drawing,menu.drawing.settings,menu.drawing.alert,menu.drawing.order,menu.drawing.group,menu.drawing.lock,menu.drawing.hide,menu.drawing.duplicate,menu.drawing.delete,selectionToolbar,hotkeys.commandPalette,hotkeys.symbolSearch,hotkeys.save,hotkeys.tools,hotkeys.invertScale,hotkeys.goToDate,hotkeys.help,hotkeys.resetView".split(","), en = new Set($t), tn = {
|
|
1227
|
+
...[...Ht, ...Ut].flatMap((e) => e.keys)
|
|
1228
|
+
])], Xt = "/* === 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/* Control tooltips (WidgetTooltip): quick to appear, slide in from the control. */\n.tcw-tooltip {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 60;\n max-width: 240px;\n padding: var(--tcw-space-3) var(--tcw-space-4);\n border-radius: var(--tcw-tooltip-radius);\n background: var(--tcw-tooltip-bg);\n color: var(--tcw-tooltip-fg);\n box-shadow: var(--tcw-tooltip-shadow);\n width: max-content;\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight);\n line-height: 1.35;\n overflow-wrap: anywhere;\n pointer-events: none;\n opacity: 0;\n visibility: hidden;\n transform: translate(var(--tcw-tip-dx, 0), var(--tcw-tip-dy, 0));\n transition:\n opacity 110ms var(--tcw-ease-out),\n transform 110ms var(--tcw-ease-out),\n visibility 0s linear 110ms;\n}\n\n.tcw-tooltip--visible {\n opacity: 1;\n visibility: visible;\n transform: none;\n transition:\n opacity 110ms var(--tcw-ease-out),\n transform 110ms var(--tcw-ease-out),\n visibility 0s;\n}\n\n/* The modal portal: carries the tokens and fonts, but no box of its own. */\n.tcw-root.tcw-portal {\n display: contents;\n}\n\n/* Fullscreen: the root fills the screen; the chart resizes with it. */\n.tcw-root:fullscreen {\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n}\n\n.tcw-root {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n font-family: var(--tcw-font);\n font-feature-settings: var(--tcw-font-features);\n font-size: var(--tcw-font-size);\n line-height: 1.4;\n color: #e6e3dc;\n background: #131416;\n font-variant-numeric: tabular-nums;\n position: relative;\n /* Clipped, not hidden: a box that hides its overflow still scrolls to what the keyboard lands on\n past its edge, and the whole widget slid aside until the next resize. Hidden where clip is unknown. */\n overflow: hidden;\n overflow: clip;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n\n /* --- Dark theme tokens (default) ---\n * Print at night: warm ink on an off-black, never pure white on black, so\n * text doesn't glare. Grey for everything that is normal; colour only where\n * it means something. */\n --tcw-bg: #131416;\n --tcw-bg-surface: #131416;\n --tcw-bg-elevated: #1b1c1f;\n --tcw-bg-overlay: rgba(19, 20, 22, 0.6);\n --tcw-border: #2a2b2f;\n --tcw-border-strong: #3a3b40;\n /* Tooltips are the ink turned over: light on the dark ground. */\n --tcw-tooltip-bg: #e6e3dc;\n --tcw-tooltip-fg: #131416;\n --tcw-text: #e6e3dc;\n --tcw-text-dim: #a9a6a0;\n --tcw-text-muted: #918f8a;\n\n /* Ink blue: links, focus and what you picked. --tcw-accent-ink is the text colour on an accent fill. */\n --tcw-accent: #7d9bff;\n --tcw-accent-hover: #98b0ff;\n --tcw-accent-ink: #131416;\n --tcw-accent-soft: rgba(125, 155, 255, 0.14);\n --tcw-accent-glow: rgba(125, 155, 255, 0.22);\n --tcw-accent-line: rgba(125, 155, 255, 0.55);\n\n --tcw-red: #e2706b;\n --tcw-red-soft: rgba(226, 112, 107, 0.12);\n --tcw-green: #4fae8a;\n --tcw-green-soft: rgba(79, 174, 138, 0.12);\n\n /* The kinds of symbol in the symbol search (stock, futures, index, crypto, forex): hues as far\n * from the accent's blue and the up and down green and red as from each other (0.11 in OKLab at\n * the least, where 0.02 is a step the eye just sees), so a badge is never taken for the chart's\n * symbol, a match or a move; each readable on a tint of itself, on the selected row too. */\n --tcw-kind-1: #4cbedf;\n --tcw-kind-2: #e8a144;\n --tcw-kind-3: #ca8cff;\n --tcw-kind-4: #f387c1;\n --tcw-kind-5: #a5c45d;\n\n --tcw-hover-bg: rgba(230, 227, 220, 0.06);\n --tcw-active-bg: rgba(230, 227, 220, 0.1);\n --tcw-divider: rgba(230, 227, 220, 0.07);\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 /* Spacing: Fibonacci numbers, so each step is near φ times the one before. */\n --tcw-space-1: 2px;\n --tcw-space-2: 3px;\n --tcw-space-3: 5px;\n --tcw-space-4: 8px;\n --tcw-space-5: 13px;\n --tcw-space-6: 21px;\n --tcw-space-7: 34px;\n\n /* The look (UI system): Print's values. The `ui` option sets them inline. */\n --tcw-radius-xs: 1px;\n --tcw-radius-sm: 2px;\n --tcw-radius: 3px;\n --tcw-radius-lg: 5px;\n --tcw-radius-xl: 8px;\n --tcw-control-radius: var(--tcw-radius);\n --tcw-input-radius: var(--tcw-radius);\n --tcw-menu-radius: var(--tcw-radius-lg);\n --tcw-dialog-radius: var(--tcw-radius-xl);\n --tcw-panel-radius: var(--tcw-radius-lg);\n --tcw-tooltip-radius: var(--tcw-radius-sm);\n --tcw-tag-radius: var(--tcw-radius-sm);\n --tcw-toast-radius: var(--tcw-radius-lg);\n --tcw-toolbar-radius: 0px;\n --tcw-sidebar-radius: 0px;\n --tcw-toolbar-h: 42px;\n --tcw-control-h: 26px;\n --tcw-control-h-sm: 20px;\n --tcw-icon: 16px;\n --tcw-sidebar-w: 42px;\n --tcw-menu-item-h: 33px;\n --tcw-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n --tcw-font-size: 13px;\n --tcw-font-size-sm: 11px;\n --tcw-font-size-xs: 10px;\n --tcw-font-size-lg: 15px;\n --tcw-font-size-xl: 18px;\n --tcw-font-size-display: 21px;\n --tcw-weight: 400;\n --tcw-weight-strong: 600;\n --tcw-label-case: uppercase;\n --tcw-label-tracking: 0.06em;\n --tcw-border-w: 1px;\n --tcw-sep-w: 1px;\n --tcw-menu-shadow: 0 0 0 1px var(--tcw-border), var(--tcw-shadow-md);\n --tcw-dialog-shadow: 0 0 0 1px var(--tcw-border), var(--tcw-shadow-lg);\n --tcw-tooltip-shadow: var(--tcw-shadow-sm);\n --tcw-blur: 0px;\n --tcw-surface-opacity: 100%;\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(125, 155, 255, 0.5);\n\n /* Type */\n --tcw-font-mono: 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n /* The faces as drawn: a tag means something else in each face (in IBM Plex, ss01 is a one-storey a).\n * The `ui` option never sets it, so a rule of yours on .tcw-root turns on your face's own. */\n --tcw-font-features: normal;\n}\n\n/* Print by day: ink on paper. */\n.tcw-root[data-tcw-theme='light'] {\n color: #1b1d21;\n background: #fbfaf6;\n\n --tcw-bg: #fbfaf6;\n --tcw-bg-surface: #fbfaf6;\n --tcw-bg-elevated: #ffffff;\n --tcw-bg-overlay: rgba(251, 250, 246, 0.8);\n --tcw-border: #dcd8cf;\n --tcw-border-strong: #c7c2b7;\n --tcw-tooltip-bg: #1b1d21;\n --tcw-tooltip-fg: #fbfaf6;\n --tcw-text: #1b1d21;\n --tcw-text-dim: #4a4e57;\n --tcw-text-muted: #6a6e75;\n\n /* A deeper ink blue: readable as text on paper, white text readable on it. */\n --tcw-accent: #2348c4;\n --tcw-accent-hover: #1b3a9f;\n --tcw-accent-ink: #ffffff;\n --tcw-accent-soft: rgba(35, 72, 196, 0.1);\n --tcw-accent-glow: rgba(35, 72, 196, 0.16);\n --tcw-accent-line: rgba(35, 72, 196, 0.45);\n --tcw-ring: 0 0 0 2px rgba(35, 72, 196, 0.4);\n\n /* Darker semantic colours: used as text on paper. */\n --tcw-red: #b8423f;\n --tcw-red-soft: rgba(184, 66, 63, 0.1);\n --tcw-green: #1f7a5c;\n --tcw-green-soft: rgba(31, 122, 92, 0.1);\n\n /* The same hues, deep enough to read on paper. */\n --tcw-kind-1: #06596e;\n --tcw-kind-2: #855402;\n --tcw-kind-3: #8238b2;\n --tcw-kind-4: #a12673;\n --tcw-kind-5: #415500;\n\n --tcw-hover-bg: rgba(27, 29, 33, 0.05);\n --tcw-active-bg: rgba(27, 29, 33, 0.08);\n --tcw-divider: #e7e3da;\n\n /* Warm shadows, as paper casts. */\n --tcw-shadow-sm: 0 1px 2px rgba(40, 34, 22, 0.06);\n --tcw-shadow-md: 0 4px 12px rgba(40, 34, 22, 0.08), 0 1px 3px rgba(40, 34, 22, 0.05);\n --tcw-shadow-lg: 0 12px 36px rgba(40, 34, 22, 0.13), 0 4px 12px rgba(40, 34, 22, 0.07);\n --tcw-shadow-xl: 0 24px 64px rgba(40, 34, 22, 0.17), 0 12px 24px rgba(40, 34, 22, 0.09);\n}\n\n/* === Toolbar === */\n\n.tcw-toolbar {\n display: flex;\n align-items: center;\n gap: 0;\n padding: 0 var(--tcw-space-4);\n height: var(--tcw-toolbar-h);\n border-bottom: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n flex-shrink: 0;\n position: relative;\n z-index: 20;\n}\n\n.tcw-toolbar-symbol {\n font-size: var(--tcw-font-size-lg);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n display: inline-flex;\n align-items: center;\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\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-control-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/* With the symbol search switched off, the button only names the symbol. */\n.tcw-toolbar-symbol[aria-disabled=\"true\"] {\n cursor: default;\n}\n\n.tcw-toolbar-symbol[aria-disabled=\"true\"]:hover {\n background: transparent;\n}\n\n/* With everything folded and still no room (a long symbol on a phone), the symbol gives way so\n \"more\" stays on the bar, a step at a time (`data-tcw-squeeze`). First its venue\n (\"HYPERLIQUID:xyz:\") is cut short before anything else shrinks, down to its first letter and an\n ellipsis, a gap keeping it off the ticker. That is 2em: a line's first letter is cut, never\n swapped for the ellipsis, so less shows a letter and a sliver (\"H.\"). The venue's column counts\n only those 2em in the button's smallest width, so the ticker stays whole and the buttons beside it\n give the rest. With room, the symbol shows as it always has. */\n.tcw-toolbar[data-tcw-squeeze='venue'] > .tcw-toolbar-symbol--venue {\n display: inline-grid;\n grid-template-columns: minmax(2em, max-content) auto;\n column-gap: var(--tcw-space-1);\n align-items: center;\n /* Shrinking is shared by width times this: the symbol takes it all until it is at its smallest. */\n flex-shrink: 1000;\n}\n\n.tcw-toolbar[data-tcw-squeeze='venue'] .tcw-toolbar-venue {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Then, with no room even for the ellipsis (a 320 phone in the Capsule look), the venue goes, the\n ticker whole; and last of all, the ticker is cut short. */\n.tcw-toolbar[data-tcw-squeeze='ticker'] .tcw-toolbar-venue,\n.tcw-toolbar[data-tcw-squeeze='cut'] .tcw-toolbar-venue {\n display: none;\n}\n\n.tcw-toolbar[data-tcw-squeeze='cut'] > .tcw-toolbar-symbol {\n min-width: 0;\n}\n\n.tcw-toolbar[data-tcw-squeeze='cut'] .tcw-toolbar-ticker {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-toolbar-sep {\n width: var(--tcw-sep-w);\n /* A button's height over phi: the rule stands as tall as the icons beside it. */\n height: calc(var(--tcw-control-h) / 1.618);\n background: var(--tcw-border);\n flex-shrink: 0;\n margin: 0 var(--tcw-space-3);\n}\n\n.tcw-toolbar-group {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n padding: 0 var(--tcw-space-2);\n}\n\n.tcw-toolbar-spacer {\n flex: 1;\n}\n\n.tcw-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight);\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-control-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-on-bg);\n color: var(--tcw-on-fg);\n font-weight: var(--tcw-weight-strong);\n box-shadow: var(--tcw-on-ring);\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: var(--tcw-control-h);\n height: var(--tcw-control-h);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-control-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 width: var(--tcw-icon);\n height: var(--tcw-icon);\n}\n\n.tcw-badge-count {\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n padding: 1px var(--tcw-space-3);\n border-radius: var(--tcw-tag-radius);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n/* === Dropdown === */\n\n.tcw-dropdown-trigger {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight);\n font-family: inherit;\n border: none;\n border-radius: var(--tcw-control-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: var(--tcw-space-3);\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n z-index: 50;\n width: max-content;\n max-width: min(340px, calc(100vw - 16px));\n padding: var(--tcw-menu-pad);\n max-height: 420px;\n overflow-y: auto;\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\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 min-height: var(--tcw-menu-item-h);\n padding: var(--tcw-space-1) var(--tcw-space-4);\n font-size: var(--tcw-font-size);\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: start;\n border-radius: var(--tcw-menu-item-radius);\n gap: var(--tcw-space-5);\n}\n\n.tcw-dropdown-item:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n/* A menu row led by an icon (chart types): icon then label, not spread apart. */\n.tcw-dropdown-item--icon {\n justify-content: flex-start;\n gap: var(--tcw-space-4);\n}\n\n.tcw-dropdown-item svg,\n.tcw-flyout-item svg {\n flex-shrink: 0;\n}\n\n/* The drawing-group button's icon holder: a plain box for the swapped SVG. */\n.tcw-sidebar-icon {\n display: inline-flex;\n}\n\n.tcw-dropdown-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: var(--tcw-weight-strong);\n}\n\n/* Timeframe menu: pick on the left, pin (star) on the right. */\n.tcw-tf-more {\n padding: 0 5px;\n}\n\n.tcw-tf-more svg {\n display: block;\n}\n\n.tcw-tf-row {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.tcw-tf-row .tcw-dropdown-item {\n flex: 1;\n min-width: 0;\n}\n\n.tcw-tf-star {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n flex-shrink: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-tf-star:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-tf-star.tcw-active {\n color: var(--tcw-accent);\n}\n\n.tcw-tf-star.tcw-active svg {\n fill: currentColor;\n}\n\n.tcw-tf-star:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n.tcw-tf-remove {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n flex-shrink: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-tf-row:hover .tcw-tf-remove,\n.tcw-tf-remove:focus-visible {\n opacity: 1;\n}\n\n/* No hover on touch screens: keep it visible rather than a hidden tap target. */\n@media (hover: none) {\n .tcw-tf-remove { opacity: 1; }\n}\n\n.tcw-tf-remove:hover {\n color: var(--tcw-red);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-tf-remove:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n/* Typed interval, under the list: stays in view while the list scrolls. Out to the menu's edges over\n its padding, and no further: past them, the menu scrolled a few px both ways. */\n.tcw-tf-custom {\n position: sticky;\n bottom: calc(-1 * var(--tcw-menu-pad));\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin: 4px calc(-1 * var(--tcw-menu-pad)) calc(-1 * var(--tcw-menu-pad));\n padding: 6px calc(var(--tcw-menu-pad) + 4px) 8px;\n border-top: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-elevated);\n}\n\n.tcw-tf-custom-hint:empty {\n display: none;\n}\n\n.tcw-tf-custom-hint {\n flex-basis: 100%;\n width: 0;\n min-width: 100%;\n color: var(--tcw-red);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.35;\n}\n\n.tcw-tf-custom-input {\n flex: 1;\n /* Fills the row: its own width would follow the font (16px on touch). */\n width: 0;\n min-width: 0;\n height: 26px;\n padding: 0 8px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text);\n font: inherit;\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n font-size: var(--tcw-font-size-sm);\n}\n\n.tcw-tf-custom-input::placeholder {\n color: var(--tcw-text-dim);\n}\n\n.tcw-tf-custom-input:focus {\n outline: none;\n border-color: var(--tcw-accent);\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\n}\n\n.tcw-tf-custom-input[aria-invalid='true'] {\n border-color: var(--tcw-red);\n box-shadow: 0 0 0 2px var(--tcw-red-soft);\n}\n\n.tcw-tf-custom-add {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n flex-shrink: 0;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n cursor: pointer;\n}\n\n.tcw-tf-custom-add:hover {\n border-color: var(--tcw-accent);\n color: var(--tcw-accent);\n}\n\n.tcw-tf-custom-add:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: 1px;\n}\n\n.tcw-dropdown-label {\n text-transform: var(--tcw-label-case);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n letter-spacing: var(--tcw-label-tracking);\n padding: var(--tcw-space-4) var(--tcw-space-4) var(--tcw-space-2);\n font-weight: var(--tcw-weight-strong);\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: var(--tcw-font-size-xs);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-muted);\n padding: 2px 6px;\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-hover-bg);\n letter-spacing: 0.02em;\n}\n\n/* === Body === */\n\n.tcw-body {\n position: relative;\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/* === History pill (older bars loading at the left edge) === */\n\n.tcw-history-pill {\n position: absolute;\n top: 50%;\n left: 10px;\n z-index: 4;\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 5px 10px 5px 8px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-shadow-sm);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n line-height: 1;\n white-space: nowrap;\n transform: translateY(-50%);\n opacity: 1;\n transition: opacity var(--tcw-dur-normal) var(--tcw-ease-out);\n pointer-events: none;\n}\n\n.tcw-history-pill--hidden {\n opacity: 0;\n}\n\n.tcw-history-pill--error {\n border-color: color-mix(in srgb, var(--tcw-red) 45%, var(--tcw-border));\n color: var(--tcw-red);\n}\n\n.tcw-history-spinner {\n width: 10px;\n height: 10px;\n border: 1.5px solid var(--tcw-accent-soft);\n border-top-color: var(--tcw-accent);\n border-radius: 50%;\n animation: tcw-history-spin 0.8s linear infinite;\n}\n\n.tcw-history-pill--error .tcw-history-spinner {\n border-color: currentColor;\n animation: none;\n}\n\n@keyframes tcw-history-spin {\n to { transform: rotate(360deg); }\n}\n\n/* === Loading overlay (candle skeleton) === */\n\n.tcw-loading-overlay {\n /* Uses a modifier class rather than the `hidden` attribute — the global\n `[hidden] { display: none !important }` rule above would cut the\n opacity transition off before it can play. */\n position: absolute;\n inset: 0;\n z-index: 5;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--tcw-bg);\n opacity: 1;\n transition: opacity var(--tcw-dur-slow) var(--tcw-ease-out);\n pointer-events: none;\n}\n\n.tcw-loading-overlay--hidden {\n opacity: 0;\n}\n\n.tcw-loading-card {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 14px;\n padding: 22px 26px 20px;\n border: 1px solid transparent;\n border-radius: var(--tcw-panel-radius);\n}\n\n/* A slow switch: the previous chart stays readable underneath, dimmed, so the\n click visibly registered without blanking the screen. */\n.tcw-loading-overlay--veil {\n background: color-mix(in srgb, var(--tcw-bg) 55%, transparent);\n}\n\n.tcw-loading-overlay--veil .tcw-loading-card {\n background: var(--tcw-bg-elevated);\n border-color: var(--tcw-border);\n box-shadow: var(--tcw-menu-shadow);\n}\n\n.tcw-loading-candles {\n position: relative;\n display: flex;\n gap: 7px;\n height: 64px;\n}\n\n/* One candle: the element is the wick's column, ::before the wick, ::after the body. */\n.tcw-loading-candle {\n position: relative;\n width: 8px;\n height: 100%;\n color: var(--tcw-red);\n opacity: 0.28;\n animation: tcw-candle-light 1.6s var(--tcw-ease) infinite;\n animation-delay: var(--tcw-delay, 0ms);\n}\n\n.tcw-loading-candle--up { color: var(--tcw-green); }\n\n.tcw-loading-candle::before,\n.tcw-loading-candle::after {\n content: '';\n position: absolute;\n left: 50%;\n background: currentColor;\n transform: translateX(-50%);\n}\n\n.tcw-loading-candle::before {\n top: var(--tcw-wick-top);\n width: 1.5px;\n height: var(--tcw-wick-h);\n}\n\n.tcw-loading-candle::after {\n top: var(--tcw-body-top);\n width: 8px;\n height: var(--tcw-body-h);\n border-radius: 1.5px;\n}\n\n/* Each candle brightens and lifts slightly in turn, left to right. */\n@keyframes tcw-candle-light {\n 0%, 55%, 100% { opacity: 0.28; transform: translateY(0); }\n 20% { opacity: 1; transform: translateY(-2px); }\n}\n\n.tcw-loading-track {\n position: relative;\n width: 100%;\n min-width: 88px;\n height: 2px;\n border-radius: 1px;\n background: var(--tcw-border);\n overflow: hidden;\n}\n\n.tcw-loading-track > span {\n position: absolute;\n inset: 0;\n width: 40%;\n border-radius: 1px;\n background: linear-gradient(90deg, transparent, var(--tcw-accent), transparent);\n animation: tcw-loading-sweep 1.6s var(--tcw-ease) infinite;\n}\n\n@keyframes tcw-loading-sweep {\n from { transform: translateX(-100%); }\n to { transform: translateX(250%); }\n}\n\n/* The status text is announced, not shown — the candles say \"loading\". */\n.tcw-loading-label {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n.tcw-loading-overlay--error .tcw-loading-candles,\n.tcw-loading-overlay--error .tcw-loading-track {\n display: none;\n}\n\n/* A failure is shown: why the chart is empty and that a retry is running. */\n.tcw-loading-overlay--error .tcw-loading-label {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip-path: none;\n white-space: normal;\n max-width: 320px;\n text-align: center;\n color: var(--tcw-red);\n font-size: var(--tcw-font-size);\n}\n\n/* Reduced motion: nothing slides or lifts, but the candles still glow in\n turn and the track breathes, so the wait never looks frozen. */\n@media (prefers-reduced-motion: reduce) {\n .tcw-loading-candle {\n animation: tcw-candle-glow 2.4s ease-in-out infinite;\n animation-delay: var(--tcw-delay, 0ms);\n }\n .tcw-loading-track > span {\n width: 100%;\n background: var(--tcw-accent);\n animation: tcw-loading-breathe 2.4s ease-in-out infinite;\n }\n}\n\n@keyframes tcw-candle-glow {\n 0%, 60%, 100% { opacity: 0.28; }\n 25% { opacity: 0.9; }\n}\n\n@keyframes tcw-loading-breathe {\n 0%, 100% { opacity: 0.15; }\n 50% { opacity: 0.7; }\n}\n\n/* === On-chart indicator legend (WidgetIndicatorLegend) === */\n\n.tcw-ind-legend {\n position: absolute;\n z-index: 3;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1px;\n max-width: calc(100% - 140px);\n pointer-events: none;\n}\n\n.tcw-ind-legend--collapsed > .tcw-ind-legend-row {\n display: none;\n}\n\n.tcw-ind-legend-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n max-width: 100%;\n padding: 0 var(--tcw-space-2);\n border-radius: var(--tcw-radius-sm);\n /* The figures face at the size of the price legend above: one block, columns that line up. */\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n line-height: 19px;\n white-space: nowrap;\n color: var(--tcw-text-dim);\n /* A see-through ground, as under the price legend's rows: lines across the plot run\n behind the text. A host sets --tcw-legend-ground (transparent: none). */\n background: var(--tcw-legend-ground, color-mix(in srgb, var(--tcw-bg) 72%, transparent));\n pointer-events: auto;\n cursor: default;\n /* A narrow pane: the values shrink first, then the row is clipped. */\n overflow: hidden;\n}\n\n/* A pane's indicator: at the top of its pane, where the canvas title was,\n short enough to sit in the pane's header below the divider's grab zone. */\n.tcw-ind-legend-row--pane {\n position: absolute;\n z-index: 3;\n line-height: 15px;\n}\n\n.tcw-ind-legend-row:hover,\n.tcw-ind-legend-row:focus-within {\n background: color-mix(in srgb, var(--tcw-bg-elevated) 90%, transparent);\n box-shadow: 0 0 0 1px var(--tcw-border);\n}\n\n.tcw-ind-legend-name {\n padding: 0;\n border: none;\n background: none;\n font: inherit;\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n cursor: pointer;\n}\n\n.tcw-ind-legend-name:hover {\n color: var(--tcw-accent);\n}\n\n/* A compared symbol's name opens nothing. */\n.tcw-ind-legend-row--compare .tcw-ind-legend-name,\n.tcw-ind-legend-row--compare .tcw-ind-legend-name:hover {\n color: var(--tcw-text);\n cursor: default;\n}\n\n/* The values are one line of text: a narrow chart cuts the line, so the values\n before the cut stay whole and the one it falls in ends in an ellipsis. Values\n shrinking each on its own cut them all at once. */\n.tcw-ind-legend-values {\n display: block;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-ind-legend-values > * + * {\n margin-inline-start: var(--tcw-space-4);\n}\n\n/* Too narrow for a digit and an ellipsis (Bollinger's on a 320 phone, 6 px beside the buttons), the\n values would show a sliver: they hide, keeping their room so they come back with it, and the name\n reads alone. */\n.tcw-ind-legend-values--no-room {\n visibility: hidden;\n}\n\n/* A compare's line colour, as a short stroke of it before the name. */\n.tcw-ind-legend-swatch {\n flex: none;\n align-self: center;\n width: 10px;\n height: 3px;\n margin-inline-end: var(--tcw-space-2);\n border-radius: 1px;\n}\n\n.tcw-ind-legend-row--hidden .tcw-ind-legend-swatch,\n.tcw-ind-legend-row--hidden .tcw-ind-legend-name,\n.tcw-ind-legend-row--hidden .tcw-ind-legend-values {\n opacity: 0.45;\n}\n\n/* Show / settings / remove: on hover or keyboard focus (always on touch). Out of sight, not out of the\n page, so Tab reaches them in a row with nothing else to focus (a compare's) and a screen reader finds\n them; a button focused shows them all. */\n.tcw-ind-legend-actions {\n display: inline-flex;\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n gap: 1px;\n margin-left: -2px;\n}\n\n.tcw-ind-legend-row:hover .tcw-ind-legend-actions,\n.tcw-ind-legend-row:focus-within .tcw-ind-legend-actions {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip-path: none;\n}\n\n@media (hover: none) {\n .tcw-ind-legend-actions {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip-path: none;\n }\n\n /* Finger-sized targets. */\n .tcw-ind-legend-act,\n .tcw-ind-legend-toggle {\n min-width: 28px;\n min-height: 24px;\n }\n}\n\n.tcw-ind-legend-act {\n display: inline-grid;\n place-items: center;\n width: 20px;\n height: 18px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n\n.tcw-ind-legend-act:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ind-legend-act[data-act='remove']:hover {\n color: var(--tcw-red);\n}\n\n.tcw-ind-legend-toggle {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n margin-top: 1px;\n padding: 1px 5px;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n cursor: pointer;\n pointer-events: auto;\n}\n\n.tcw-ind-legend-toggle[hidden] {\n display: none;\n}\n\n.tcw-ind-legend-toggle:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ind-legend-name:focus-visible,\n.tcw-ind-legend-act:focus-visible,\n.tcw-ind-legend-toggle:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n/* === Sidebar === */\n\n.tcw-sidebar {\n width: var(--tcw-sidebar-w);\n flex-shrink: 0;\n background: var(--tcw-bg-surface);\n border-inline-end: var(--tcw-border-w) solid var(--tcw-border);\n display: flex;\n flex-direction: column;\n align-items: center;\n /* The buttons' own 1px margins at its ends make up the rest of the gap: as tall as its tools,\n 768 px high in the Print look, it doesn't scroll by those 2 px. */\n padding: calc(var(--tcw-space-3) - 1px) 0;\n /* On a short screen the tools scroll; the menus sit outside it. */\n overflow-x: hidden;\n overflow-y: auto;\n scrollbar-width: none;\n}\n.tcw-sidebar::-webkit-scrollbar {\n display: none;\n}\n.tcw-sidebar > * {\n flex-shrink: 0;\n}\n\n.tcw-tool-group-wrap {\n position: relative;\n}\n\n.tcw-sidebar-btn {\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\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-control-radius);\n}\n\n.tcw-sidebar-btn svg {\n width: var(--tcw-icon);\n height: var(--tcw-icon);\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-on-icon-fg);\n background: var(--tcw-on-icon-bg);\n box-shadow: var(--tcw-on-icon-ring);\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/* The drawing tools' sections: always a hairline (it groups the tools), even in\n looks that drop the rules between toolbar groups. */\n.tcw-sidebar-divider {\n width: 20px;\n height: max(1px, var(--tcw-sep-w));\n background: var(--tcw-divider);\n margin: 5px 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 margin-inline-start: 6px;\n overflow-y: auto;\n overscroll-behavior: contain;\n min-width: 180px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n z-index: 30;\n padding: var(--tcw-menu-pad);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n animation: tcw-slide-right var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n/* Spans the gap to the toolbar button: crossing it stays inside the menu. */\n.tcw-flyout::before {\n content: '';\n position: absolute;\n top: -1px;\n bottom: -1px;\n right: 100%;\n width: 8px;\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: var(--tcw-label-case);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n letter-spacing: var(--tcw-label-tracking);\n padding: var(--tcw-space-3) var(--tcw-space-4) var(--tcw-space-2);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-flyout-hint {\n padding: var(--tcw-space-3) var(--tcw-space-4) var(--tcw-space-1);\n border-top: 1px solid var(--tcw-border);\n margin-top: var(--tcw-space-2);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n\n.tcw-flyout-item {\n min-height: var(--tcw-menu-item-h);\n padding: var(--tcw-space-1) var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n color: var(--tcw-text-dim);\n cursor: pointer;\n width: 100%;\n display: flex;\n align-items: center;\n gap: 10px;\n border: none;\n background: transparent;\n text-align: start;\n font-family: inherit;\n border-radius: var(--tcw-menu-item-radius);\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.tcw-flyout-item:focus-visible {\n outline: none;\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n box-shadow: inset 0 0 0 1px var(--tcw-accent);\n}\n\n.tcw-flyout-item.tcw-active {\n color: var(--tcw-accent);\n background: var(--tcw-accent-soft);\n font-weight: var(--tcw-weight-strong);\n}\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(12, 12, 10, 0.42);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\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/* A text drawing's words typed in place, over its box on the chart; under any dialog. */\n.tcw-inline-text {\n position: fixed;\n inset: 0;\n z-index: 90;\n pointer-events: none;\n}\n.tcw-inline-text-input {\n position: absolute;\n box-sizing: border-box;\n margin: 0;\n border: 1px solid var(--tcw-accent);\n border-radius: var(--tcw-radius-xs);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n outline: none;\n overflow: hidden;\n resize: none;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n pointer-events: auto;\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: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-dialog-radius);\n width: 520px;\n max-width: 92vw;\n max-height: 82vh;\n max-height: 82dvh;\n display: flex;\n flex-direction: column;\n box-shadow: var(--tcw-dialog-shadow);\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: var(--tcw-space-5) var(--tcw-space-6);\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n/* A dialog's title is phi times its text (21 to 13). */\n.tcw-modal-header h3 {\n font-size: var(--tcw-font-size-display);\n font-weight: var(--tcw-weight-strong);\n margin: 0;\n color: var(--tcw-text);\n letter-spacing: -0.015em;\n}\n\n.tcw-modal-close {\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\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-control-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 /* Four tabs in a long language on a phone: they wrap rather than clip. No overflow here: in the\n dialog's column it would let a long body squash the tabs, and clip the underline of the active one. */\n flex-wrap: wrap;\n flex-shrink: 0;\n gap: var(--tcw-space-2);\n padding: var(--tcw-tabs-pad-block) var(--tcw-space-6);\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n.tcw-modal-tab {\n flex-shrink: 0;\n white-space: nowrap;\n height: var(--tcw-tab-h);\n padding: var(--tcw-tab-pad);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight);\n color: var(--tcw-text-muted);\n border: none;\n background: transparent;\n cursor: pointer;\n border-bottom: var(--tcw-tab-line) solid transparent;\n border-radius: var(--tcw-tab-radius);\n margin-bottom: calc(var(--tcw-tab-line) / -2);\n transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n font-family: inherit;\n letter-spacing: -0.005em;\n}\n\n.tcw-modal-tab:hover {\n color: var(--tcw-text-dim);\n background: var(--tcw-tab-hover);\n}\n\n.tcw-modal-tab.tcw-active {\n color: var(--tcw-tab-on-fg);\n background: var(--tcw-tab-on-bg);\n border-bottom-color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-modal-body {\n padding: var(--tcw-space-6);\n overflow-y: auto;\n flex: 1;\n}\n\n.tcw-settings-section {\n margin-bottom: var(--tcw-space-6);\n}\n\n.tcw-settings-section:last-child {\n margin-bottom: 0;\n}\n\n.tcw-settings-section-title {\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n color: var(--tcw-text-muted);\n margin-bottom: var(--tcw-space-4);\n}\n\n.tcw-settings-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--tcw-space-4) 0;\n}\n\n.tcw-settings-row + .tcw-settings-row {\n border-top: 1px solid var(--tcw-divider);\n}\n\n/* A number field's hint goes on a line of its own, under the field. */\n.tcw-settings-row--number {\n flex-wrap: wrap;\n}\n\n.tcw-settings-hint {\n flex-basis: 100%;\n padding-top: var(--tcw-space-2);\n color: var(--tcw-red);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.35;\n text-align: end;\n}\n\n/* Empty, it takes no room but stays rendered: a live region that appears with its text is often not read out. */\n.tcw-settings-hint:empty {\n padding-top: 0;\n}\n\n.tcw-settings-label {\n font-size: var(--tcw-font-size);\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: var(--tcw-radius-xs);\n}\n\n.tcw-color-hex {\n font-size: var(--tcw-font-size-xs);\n /* Hex letters vary in width in a sans face: a monospaced one keeps the codes one width. */\n font-family: ui-monospace, 'Cascadia Mono', 'SF Mono', Menlo, Consolas, monospace;\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-muted);\n min-width: 64px;\n letter-spacing: 0.01em;\n}\n\n/* A colour left to the part itself: the swatch shows where the picker starts, faded. */\n.tcw-color-auto input[type='color'] {\n opacity: 0.45;\n border-style: dashed;\n}\n\n.tcw-color-auto .tcw-color-hex {\n font-family: inherit;\n font-style: italic;\n}\n\n.tcw-color-auto-btn {\n height: 24px;\n padding: 0 8px;\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n background: transparent;\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-radius-sm);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-color-auto-btn:hover,\n.tcw-color-auto-btn:focus-visible {\n color: var(--tcw-text);\n border-color: var(--tcw-accent);\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: var(--tcw-font-size-sm);\n font-family: inherit;\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-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: var(--tcw-space-5) var(--tcw-space-6);\n border-top: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n border-radius: 0 0 var(--tcw-dialog-radius) var(--tcw-dialog-radius);\n}\n\n.tcw-reset-link {\n font-size: var(--tcw-font-size-sm);\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: var(--tcw-space-4) var(--tcw-space-6);\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n background: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n border: none;\n border-radius: var(--tcw-control-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}\n\n.tcw-done-btn:hover {\n background: var(--tcw-accent-hover);\n}\n\n.tcw-done-btn:disabled { opacity: 0.45; cursor: not-allowed; }\n\n.tcw-done-btn:active {\n transform: translateY(0.5px);\n}\n\n/* === Status Bar === */\n\n.tcw-statusbar {\n /* Above sidebar buttons that overflow a short chart; menus (z 30+) stay on top. */\n position: relative;\n z-index: 1;\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: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n flex-shrink: 0;\n}\n\n/* The bar holds the keyboard when a refit hides every button it could go to. */\n.tcw-statusbar:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n.tcw-status-right {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-inline-start: auto;\n /* Never narrower than what it holds, so the clock at its end stays whole: the range presets give way instead. */\n flex: none;\n white-space: nowrap;\n}\n\n/* Range presets + go to date, bottom left. The bar takes the room the rest leaves and\n clips what's past it; WidgetStatusBar.fit folds that under \"more\". Logical margins,\n so right to left it keeps its gap before the right group. */\n.tcw-range-bar {\n display: flex;\n align-items: center;\n gap: 1px;\n margin-block: -4px;\n margin-inline: -8px 12px;\n min-width: 0;\n overflow: hidden;\n}\n\n/* A narrow widget (a phone, a narrow column, a grid's cell): the range presets close up. */\n.tcw-root[data-tcw-narrow] .tcw-range-btn[data-range] {\n padding: 4px 5px;\n}\n\n/* What the bar has folded, and \"more\" while nothing is. */\n.tcw-statusbar [data-tcw-folded],\n.tcw-statusbar:not(.tcw-statusbar--folded) .tcw-range-more {\n display: none;\n}\n\n.tcw-range-btn {\n flex-shrink: 0;\n padding: 4px 7px;\n font: inherit;\n font-weight: var(--tcw-weight-strong);\n letter-spacing: 0.02em;\n color: var(--tcw-text-muted);\n background: transparent;\n border: none;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-range-btn:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-range-btn:active {\n color: var(--tcw-accent);\n}\n\n.tcw-range-btn:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n.tcw-range-goto,\n.tcw-range-more {\n display: inline-grid;\n place-items: center;\n padding: 4px 6px;\n}\n\n.tcw-range-goto {\n margin-inline-start: 6px;\n}\n\n.tcw-range-goto svg,\n.tcw-range-more svg {\n display: block;\n}\n\n.tcw-status-indicator {\n display: flex;\n align-items: center;\n gap: 7px;\n font-weight: var(--tcw-weight);\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(31, 168, 116, 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 3;\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(232, 80, 91, 0.2);\n}\n\n/* === Watchlist === */\n\n.tcw-watchlist {\n width: 220px;\n flex-shrink: 0;\n background: var(--tcw-bg-surface);\n border-inline-start: 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 position: relative;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 8px 6px 8px;\n border-bottom: 1px solid var(--tcw-divider);\n}\n\n/* The shown list's name: opens the lists menu. */\n.tcw-watchlist-name {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 6px;\n height: var(--tcw-control-h-sm);\n padding: 0 6px;\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n text-align: start;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n}\n.tcw-watchlist-name::after {\n content: '';\n flex: none;\n width: 0;\n height: 0;\n margin-inline-start: auto;\n border: 4px solid transparent;\n border-top-color: currentColor;\n border-bottom-width: 0;\n opacity: 0.7;\n}\n\n.tcw-watchlist-add {\n flex: none;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-lg);\n line-height: 1;\n cursor: pointer;\n}\n\n.tcw-watchlist-name:hover,\n.tcw-watchlist-add:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n.tcw-watchlist-name:focus-visible,\n.tcw-watchlist-add:focus-visible,\n.tcw-watchlist-input:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* The lists menu, under the header. */\n.tcw-watchlist-menu {\n top: calc(100% - 2px);\n left: 6px;\n right: 6px;\n margin-top: 0;\n}\n.tcw-watchlist-count {\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n font-size: var(--tcw-font-size-xs);\n}\n.tcw-watchlist-menu .tcw-danger {\n color: var(--tcw-red);\n}\n\n/* Naming a list in place. */\n.tcw-watchlist-input {\n flex: 1;\n min-width: 0;\n height: var(--tcw-control-h-sm);\n padding: 0 8px;\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n}\n\n.tcw-watchlist-empty {\n padding: 16px 14px;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.5;\n}\n\n/*\n * A row's remove button shows on hover or focus, in a column of its own after\n * the numbers: over them, it hid the price and the change of the row the\n * keyboard was on.\n */\n.tcw-watchlist-remove {\n display: grid;\n place-items: center;\n width: var(--tcw-watchlist-remove);\n height: var(--tcw-watchlist-remove);\n border: 0;\n border-radius: var(--tcw-radius-sm);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size);\n line-height: 1;\n opacity: 0;\n cursor: pointer;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-watchlist-row:hover .tcw-watchlist-remove,\n.tcw-watchlist-row:focus-within .tcw-watchlist-remove {\n opacity: 1;\n}\n.tcw-watchlist-remove:hover {\n color: var(--tcw-red);\n}\n.tcw-watchlist-row.tcw-watchlist-dragging {\n opacity: 0.45;\n}\n\n.tcw-watchlist-list {\n flex: 1;\n overflow-y: auto;\n padding: 4px 0;\n}\n\n.tcw-watchlist-row {\n --tcw-watchlist-remove: 20px;\n position: relative;\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-inline-start: 2px solid transparent;\n outline: none;\n}\n\n.tcw-watchlist-row.tcw-watchlist-removable {\n grid-template-columns: 1fr auto auto var(--tcw-watchlist-remove);\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-inline-start-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-row.tcw-watchlist-active {\n background: var(--tcw-accent-soft);\n border-inline-start-color: var(--tcw-accent);\n}\n\n.tcw-watchlist-symbol {\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n font-weight: var(--tcw-weight);\n}\n\n.tcw-watchlist-change {\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n font-weight: var(--tcw-weight);\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/* === Toast === */\n\n.tcw-toast-icon {\n display: inline-flex;\n vertical-align: -2px;\n margin-inline-end: 7px;\n color: var(--tcw-accent);\n}\n.tcw-toast-error .tcw-toast-icon { color: var(--tcw-red); }\n\n/* Over an open dialog: above its backdrop, at the window's foot. */\n.tcw-toast.tcw-toast-over {\n position: fixed;\n z-index: 120;\n}\n\n.tcw-toast {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translate(-50%, 12px);\n z-index: 40;\n padding: var(--tcw-space-4) var(--tcw-space-5);\n background: var(--tcw-bg-elevated);\n border: 1px solid var(--tcw-border-strong);\n border-radius: var(--tcw-toast-radius);\n box-shadow: var(--tcw-menu-shadow);\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight);\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 bar ===\n * A transport over the foot of the main pane: step back / play / step\n * forward, where the replay is (its date and a track with the played part\n * filled), its pace (speed, step), and the ways out (pick another bar, back\n * to now). Only --tcw-* tokens; its sizes come from the look's own ladder.\n * The widget sets where it sits (--tcw-replay-foot, --tcw-replay-plot-*)\n * from the main pane, and the tier (data-fit) from the room it has.\n */\n\n/* Picking the replay start: the bars right of the pointer would be hidden. */\n.tcw-replay-shade {\n position: absolute;\n z-index: 4;\n pointer-events: none;\n background: color-mix(in srgb, var(--tcw-bg) 62%, transparent);\n border-inline-start: 1.5px dashed var(--tcw-accent);\n}\n\n.tcw-replay-bar {\n /* Buttons are the look's controls; Play two small steps above them. */\n --tcw-replay-btn: var(--tcw-control-h);\n --tcw-replay-play: calc(var(--tcw-control-h) + 2 * var(--tcw-space-2));\n --tcw-replay-track-w: calc(var(--tcw-space-7) * 6);\n --tcw-replay-track-min: calc(var(--tcw-space-7) * 3);\n --tcw-replay-rail: var(--tcw-space-2);\n --tcw-replay-head-w: var(--tcw-space-2);\n --tcw-replay-head-h: var(--tcw-space-5);\n position: absolute;\n /* On the main pane's foot (over the volume, clear of the bottom panes), above the time axis without them. */\n bottom: calc(var(--tcw-replay-foot, 30px) + var(--tcw-space-4));\n inset-inline: var(--tcw-replay-plot-start, 0px) var(--tcw-replay-plot-end, 0px);\n /* Centred on the plot by its margins: an entrance on `transform` would undo a translate. */\n margin-inline: auto;\n box-sizing: border-box;\n width: max-content;\n max-width: calc(100% - var(--tcw-replay-plot-start, 0px) - var(--tcw-replay-plot-end, 0px) - 2 * var(--tcw-space-4));\n z-index: 25;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n padding: var(--tcw-space-3);\n background: var(--tcw-bg-elevated);\n background: color-mix(in srgb, var(--tcw-bg-elevated) var(--tcw-surface-opacity, 100%), transparent);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n /* The look's menu shadow carries its hairline (Print, Terminal, Capsule): no border of its own on top. */\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.2;\n animation: tcw-sel-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n.tcw-replay-group,\n.tcw-replay-slot {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-2);\n min-width: 0;\n}\n.tcw-replay-bar [hidden] { display: none !important; }\n/* The step field on a single step: nothing there, no gap for it. */\n.tcw-replay-slot:empty { display: none; }\n\n/* Hairlines between the groups where the look draws separators (Print, Terminal); a gap in the others. */\n.tcw-replay-sep {\n flex: none;\n align-self: stretch;\n width: var(--tcw-sep-w);\n margin-block: var(--tcw-space-2);\n background: var(--tcw-divider);\n}\n\n/* --- Buttons --- */\n.tcw-replay-btn {\n flex: none;\n display: inline-grid;\n place-items: center;\n inline-size: var(--tcw-replay-btn);\n block-size: var(--tcw-replay-btn);\n padding: 0;\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n cursor: pointer;\n transition:\n background-color 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}\n.tcw-replay-btn > svg,\n.tcw-replay-text-btn svg { width: var(--tcw-icon); height: var(--tcw-icon); flex: none; }\n.tcw-replay-btn:hover { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-replay-btn:active { background: var(--tcw-active-bg); transform: scale(0.94); }\n.tcw-replay-btn:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n\n/* Play: the one filled control. Its focus ring stands off the fill, or it would vanish into it. */\n.tcw-replay-btn.tcw-replay-play {\n inline-size: var(--tcw-replay-play);\n block-size: var(--tcw-replay-play);\n background: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n}\n.tcw-replay-btn.tcw-replay-play:hover { background: var(--tcw-accent-hover); color: var(--tcw-accent-ink); }\n.tcw-replay-btn.tcw-replay-play:focus-visible {\n box-shadow: 0 0 0 var(--tcw-space-1) var(--tcw-bg-elevated), 0 0 0 calc(2 * var(--tcw-space-1)) var(--tcw-accent-line);\n}\n\n.tcw-replay-btn:disabled,\n.tcw-replay-text-btn:disabled,\n.tcw-replay-scrubber:disabled,\n.tcw-replay-speed:disabled { opacity: 0.4; cursor: default; transform: none; }\n/* Nothing left to play: a muted fill, not a faded accent that reads as pressed. */\n.tcw-replay-btn.tcw-replay-play:disabled { background: var(--tcw-active-bg); color: var(--tcw-text-muted); opacity: 1; }\n\n/* --- Where the replay is --- */\n.tcw-replay-timeline {\n flex: 1 1 auto;\n gap: var(--tcw-space-4);\n}\n.tcw-replay-time {\n flex: none;\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text);\n white-space: nowrap;\n}\n.tcw-replay-group[aria-busy='true'] .tcw-replay-time,\n.tcw-replay-group[aria-busy='true'] .tcw-replay-hint { color: var(--tcw-text-muted); }\n\n.tcw-root input[type='range'].tcw-replay-scrubber {\n --tcw-replay-rest: var(--tcw-border-strong);\n flex: 1 1 var(--tcw-replay-track-w);\n min-inline-size: var(--tcw-replay-track-min);\n inline-size: var(--tcw-replay-track-w);\n block-size: var(--tcw-replay-btn);\n margin: 0;\n padding: 0;\n appearance: none;\n -webkit-appearance: none;\n background: transparent;\n border: 0;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n}\n/* Measured at its least: the bar's width with no slack in the track. */\n.tcw-replay-bar[data-measure] { max-width: none; animation: none; }\n.tcw-replay-bar[data-measure] input[type='range'].tcw-replay-scrubber { inline-size: var(--tcw-replay-track-min); flex: none; }\n.tcw-root input[type='range'].tcw-replay-scrubber:hover { --tcw-replay-rest: var(--tcw-text-muted); }\n.tcw-root input[type='range'].tcw-replay-scrubber:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n/* The played part in the accent, the rest a rail; Firefox fills it itself. */\n.tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-runnable-track {\n block-size: var(--tcw-replay-rail);\n border-radius: var(--tcw-radius-xs);\n background: linear-gradient(to right, var(--tcw-accent) 0 var(--tcw-replay-done, 0%), var(--tcw-replay-rest) var(--tcw-replay-done, 0%) 100%);\n}\n.tcw-root input[type='range'].tcw-replay-scrubber::-moz-range-track { block-size: var(--tcw-replay-rail); border-radius: var(--tcw-radius-xs); background: var(--tcw-replay-rest); }\n.tcw-root input[type='range'].tcw-replay-scrubber::-moz-range-progress { block-size: var(--tcw-replay-rail); border-radius: var(--tcw-radius-xs); background: var(--tcw-accent); }\n/* A playhead, as the chart marks the replay's cut: a short upright in ink, rounded as the look rounds. */\n.tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n inline-size: var(--tcw-replay-head-w);\n block-size: var(--tcw-replay-head-h);\n margin-top: calc((var(--tcw-replay-rail) - var(--tcw-replay-head-h)) / 2);\n border: 0;\n border-radius: var(--tcw-radius-xs);\n background: var(--tcw-text);\n box-shadow: 0 0 0 var(--tcw-space-1) var(--tcw-bg-elevated);\n transition: transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-root input[type='range'].tcw-replay-scrubber:hover::-webkit-slider-thumb,\n.tcw-root input[type='range'].tcw-replay-scrubber:active::-webkit-slider-thumb { transform: scaleY(1.25); }\n.tcw-root input[type='range'].tcw-replay-scrubber::-moz-range-thumb {\n inline-size: var(--tcw-replay-head-w);\n block-size: var(--tcw-replay-head-h);\n border: 0;\n border-radius: var(--tcw-radius-xs);\n background: var(--tcw-text);\n box-shadow: 0 0 0 var(--tcw-space-1) var(--tcw-bg-elevated);\n}\n\n/* --- Pace: speed and step, each a labelled field --- */\n.tcw-replay-chip {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n}\n.tcw-replay-chip-label {\n font-size: var(--tcw-font-size-xs);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n color: var(--tcw-text-muted);\n white-space: nowrap;\n}\n.tcw-root .tcw-replay-chip select.tcw-replay-speed {\n block-size: var(--tcw-replay-btn);\n padding-block: 0;\n padding-inline-start: var(--tcw-space-4);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n}\n\n/* --- The ways out, and picking --- */\n.tcw-replay-text-btn {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n block-size: var(--tcw-replay-btn);\n padding-inline: var(--tcw-space-4);\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-weight: var(--tcw-weight);\n white-space: nowrap;\n cursor: pointer;\n transition: background-color var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease), transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-replay-text-btn:hover { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-replay-text-btn:active { background: var(--tcw-active-bg); transform: scale(0.97); }\n.tcw-replay-text-btn:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n/* Random bar: outlined, the one thing to press while picking. */\n.tcw-replay-text-btn.tcw-replay-ghost { border: var(--tcw-border-w) solid var(--tcw-border-strong); color: var(--tcw-text); }\n/* The close glyph is the phone's: on wider bars the words say it. */\n.tcw-replay-close-icon { display: none; }\n/* At the last bar, the way back to now is the next thing to do. */\n.tcw-replay-bar--ended .tcw-replay-realtime { background: var(--tcw-accent); color: var(--tcw-accent-ink); }\n.tcw-replay-bar--ended .tcw-replay-realtime:hover { background: var(--tcw-accent-hover); color: var(--tcw-accent-ink); }\n\n.tcw-replay-hint {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n padding-inline: var(--tcw-space-3);\n color: var(--tcw-text-dim);\n white-space: nowrap;\n}\n.tcw-replay-hint > svg { flex: none; width: var(--tcw-icon); height: var(--tcw-icon); color: var(--tcw-accent); }\n\n/* --- Narrower: the fields lose their captions (they stay their names) --- */\n.tcw-replay-bar:is([data-fit='compact'], [data-fit='stack']) .tcw-replay-chip-label {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* --- A phone, or a narrow chart: two rows across the plot, where the replay is on top --- */\n.tcw-replay-bar[data-fit='stack'] {\n /* Touch targets: 40 px (44 for Play) at least, as the toolbar's on a phone. */\n --tcw-replay-btn: max(40px, var(--tcw-control-h));\n --tcw-replay-play: max(44px, calc(var(--tcw-control-h) + 2 * var(--tcw-space-2)));\n inset-inline: var(--tcw-space-4);\n width: auto;\n max-width: none;\n margin-inline: 0;\n flex-wrap: wrap;\n gap: var(--tcw-space-2);\n}\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-sep { display: none; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-timeline {\n order: -2;\n /* The first row, beside the close button; the rest wraps below. */\n flex: 1 1 calc(100% - var(--tcw-replay-btn) - 2 * var(--tcw-space-2));\n box-sizing: border-box;\n padding-inline-start: var(--tcw-space-3);\n}\n.tcw-replay-bar[data-fit='stack'] input[type='range'].tcw-replay-scrubber { block-size: var(--tcw-menu-item-h); min-inline-size: 0; }\n/* Back to realtime closes the bar from the first row, a glyph touch users know. */\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-exits { display: contents; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-realtime { order: -1; inline-size: var(--tcw-replay-btn); padding: 0; justify-content: center; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-realtime .tcw-replay-text { display: none; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-close-icon { display: inline-flex; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-transport { flex: 1 0 auto; }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-hint { white-space: normal; flex: 1 0 100%; padding-block: var(--tcw-space-2); }\n.tcw-replay-bar[data-fit='stack'] .tcw-replay-picking { display: contents; }\n\n/* While the bar holds the plot's foot, what lives there makes room: the toasts and the phone's drawing button. */\n.tcw-root[data-tcw-replay] > .tcw-toast:not(.tcw-toast-over) {\n bottom: calc(var(--tcw-replay-lift, 0px) + var(--tcw-space-4));\n}\n.tcw-root[data-tcw-narrow][data-tcw-replay] > .tcw-body > .tcw-sidebar-fab {\n bottom: calc(var(--tcw-replay-lift, 0px) + var(--tcw-space-4));\n}\n\n@media (forced-colors: active) {\n .tcw-replay-bar { border: 1px solid CanvasText; }\n .tcw-replay-btn.tcw-replay-play { border: 1px solid ButtonText; }\n .tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-runnable-track { background: GrayText; }\n .tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-thumb { background: Highlight; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tcw-replay-bar { animation: none; }\n .tcw-replay-btn,\n .tcw-replay-text-btn,\n .tcw-root input[type='range'].tcw-replay-scrubber::-webkit-slider-thumb { transition: none; }\n}\n\n/* === Responsive === */\n\n@media (max-width: 768px) {\n .tcw-toolbar {\n padding: 0 4px;\n height: max(44px, var(--tcw-toolbar-h)); /* Apple HIG minimum touch target */\n }\n .tcw-toolbar-sep {\n display: none;\n }\n .tcw-btn,\n .tcw-dropdown-trigger {\n height: max(40px, var(--tcw-control-h)); /* fatter tap target */\n padding: 0 12px;\n font-size: var(--tcw-font-size);\n }\n .tcw-btn-icon {\n width: max(40px, var(--tcw-control-h));\n height: max(40px, var(--tcw-control-h));\n }\n .tcw-sidebar {\n width: max(44px, var(--tcw-sidebar-w));\n }\n .tcw-sidebar-btn {\n width: max(40px, var(--tcw-control-h));\n height: max(40px, var(--tcw-control-h));\n }\n .tcw-modal {\n width: 94vw;\n border-radius: var(--tcw-dialog-radius);\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 top: auto;\n /* Above the on-screen keyboard (the widget sets it from visualViewport). */\n bottom: var(--tcw-keyboard-inset, 0px);\n padding-left: env(safe-area-inset-left, 0px);\n padding-right: env(safe-area-inset-right, 0px);\n left: 0;\n right: 0;\n transform: none;\n /* The border and the safe-area padding inside the screen's width. */\n box-sizing: border-box;\n width: 100vw;\n max-width: 100vw;\n /* Less the on-screen keyboard: a sheet's top never goes above the screen. */\n max-height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n max-height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 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 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 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 padding-bottom: max(14px, env(safe-area-inset-bottom));\n }\n\n /* Larger tap targets inside sheets: taller, not more padding, so a tab's text stays inside its chip. */\n .tcw-modal-tab {\n min-height: 40px;\n padding-inline: 16px;\n }\n .tcw-dropdown-item {\n padding: 12px 12px;\n font-size: var(--tcw-font-size-lg);\n }\n}\n\n/* === Price alerts panel === */\n\n.tcw-alerts-panel {\n position: absolute;\n top: var(--tcw-panel-top);\n inset-inline-end: 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: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-weight-strong);\n font-size: var(--tcw-font-size);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent-ink);\n background: var(--tcw-accent);\n border: none;\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n font-variant-numeric: tabular-nums;\n}\n.tcw-alerts-row-note {\n margin-top: 2px;\n font-size: var(--tcw-font-size-xs);\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n padding: 2px 5px;\n border-radius: var(--tcw-tag-radius);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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 max-height: 40dvh;\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: var(--tcw-panel-top);\n inset-inline-end: 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-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm); 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: var(--tcw-font-size-sm);\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: var(--tcw-weight-strong); }\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\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/* === 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/*\n * Placing a bracket: a strip at the foot of the chart, over its time axis\n * (30 px, the chart's TIME_AXIS_HEIGHT), clear of the tags along its top; its\n * name and Place in the side's colour. Centred by its margins, not a\n * transform: the entrance animation ends on `transform: none`, which left it\n * starting at the middle.\n */\n.tcw-bracket-bar {\n position: absolute;\n bottom: calc(30px + var(--tcw-space-5));\n inset-inline: 0;\n margin-inline: auto;\n box-sizing: border-box;\n width: max-content;\n max-width: calc(100% - 2 * var(--tcw-space-4));\n z-index: 45;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n padding-block: var(--tcw-space-3);\n padding-inline: var(--tcw-space-5) var(--tcw-space-3);\n background: var(--tcw-bg-elevated);\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-bracket-bar[data-side='buy'] { --tcw-side: var(--tcw-green); }\n.tcw-bracket-bar[data-side='sell'] { --tcw-side: var(--tcw-red); }\n/* The name gives way first: in German or Russian it would push Place off a phone. */\n.tcw-bracket-label {\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-side, var(--tcw-text));\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n/* The replay bar has the chart's foot while it shows: the bracket's goes to the top. */\n.tcw-root[data-tcw-replay] .tcw-bracket-bar {\n top: var(--tcw-space-4);\n bottom: auto;\n}\n.tcw-bracket-hint {\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.tcw-bracket-cancel,\n.tcw-bracket-confirm {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-control-h);\n padding-inline: var(--tcw-space-5);\n border-radius: var(--tcw-control-radius);\n font: inherit;\n font-size: var(--tcw-font-size);\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-bracket-cancel {\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n background: transparent;\n color: var(--tcw-text);\n}\n.tcw-bracket-cancel:hover { background: var(--tcw-hover-bg); }\n/* The ground's own colour reads on the side's: dark on the dark theme's light greens, paper on the light theme's deep ones. */\n.tcw-bracket-confirm {\n border: none;\n background: var(--tcw-side, var(--tcw-accent));\n color: var(--tcw-bg);\n font-weight: var(--tcw-weight-strong);\n}\n.tcw-bracket-confirm:hover { background: color-mix(in srgb, var(--tcw-side, var(--tcw-accent)) 86%, var(--tcw-text)); }\n.tcw-bracket-cancel:focus-visible,\n.tcw-bracket-confirm:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n@media (max-width: 640px) {\n .tcw-bracket-bar {\n inset-inline: var(--tcw-space-4);\n width: auto;\n max-width: none;\n }\n .tcw-bracket-hint { display: none; }\n .tcw-bracket-label { margin-inline-end: auto; }\n .tcw-bracket-cancel,\n .tcw-bracket-confirm { height: 34px; }\n}\n\n@media (forced-colors: active) {\n .tcw-bracket-bar { border: 1px solid CanvasText; }\n .tcw-bracket-confirm { border: 1px solid ButtonText; }\n .tcw-bracket-cancel:focus-visible,\n .tcw-bracket-confirm:focus-visible { outline: 2px solid Highlight; }\n}\n\n/* === Drawing style + templates popover === */\n\n.tcw-style-panel {\n position: absolute;\n bottom: 12px;\n inset-inline-start: var(--tcw-panel-left);\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-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n}\n.tcw-style-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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-control-radius);\n color: var(--tcw-text-dim);\n cursor: pointer;\n font-size: var(--tcw-font-size-xs);\n}\n.tcw-style-width span { width: 16px; background: currentColor; border-radius: var(--tcw-radius-xs); }\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\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: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent-ink);\n background: var(--tcw-accent);\n border: none;\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-xs); 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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n background: transparent;\n border: none;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n text-align: start;\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: end;\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-dim);\n}\n\n/* === Indicator settings dialog === */\n\n/* Narrow on a desktop; on a phone a sheet across the screen like every dialog. */\n@media (min-width: 641px) {\n .tcw-modal-narrow {\n max-width: 360px;\n }\n}\n.tcw-indi-input {\n width: 110px;\n height: 30px;\n padding: 0 8px;\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\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-select {\n width: 150px;\n padding-right: 4px;\n cursor: pointer;\n}\n/* A level: its value and a remove button. */\n.tcw-indi-level {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n.tcw-indi-remove {\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-indi-remove:hover {\n color: var(--tcw-red);\n background: var(--tcw-hover-bg);\n}\n.tcw-indi-remove:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n.tcw-indi-add {\n margin-top: 8px;\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: var(--tcw-panel-top);\n inset-inline-end: 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-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\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: var(--tcw-weight-strong);\n font-size: var(--tcw-font-size);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-xs);\n font-weight: calc(var(--tcw-weight-strong) + 100);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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: var(--tcw-font-size-sm);\n color: var(--tcw-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n/* A compare: its colour and symbol, then how it is compared, taking the room left before its button. */\n.tcw-tree-compare {\n justify-content: flex-start;\n}\n.tcw-tree-compare .tcw-tree-name {\n flex: 0 1 auto;\n}\n.tcw-tree-compare .tcw-tree-del {\n flex: none;\n margin-inline-start: auto;\n}\n.tcw-tree-way {\n flex: 1 1 0;\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-size: var(--tcw-font-size-xs);\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: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n background: transparent;\n color: var(--tcw-text-muted);\n border-radius: var(--tcw-control-radius);\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/* A drawing row's grip: dragged, it moves the drawing up or down the order. */\n.tcw-tree-btn.tcw-tree-grip {\n flex: none;\n cursor: grab;\n touch-action: none;\n}\n.tcw-tree-row:not(:hover) .tcw-tree-grip:not(:focus-visible) {\n opacity: 0.45;\n}\n/* The row a dragged drawing would take the place of. */\n.tcw-tree-row.tcw-tree-drop {\n box-shadow: inset 0 0 0 1px var(--tcw-accent);\n}\n/* A drawing's name selects it on the chart. */\n.tcw-tree-name.tcw-tree-pick {\n flex: 1 1 auto;\n cursor: pointer;\n}\n.tcw-tree-btn.tcw-tree-del:hover {\n background: var(--tcw-red-soft);\n color: var(--tcw-red);\n}\n.tcw-tree-group .tcw-tree-name {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-weight: var(--tcw-weight-strong);\n}\n.tcw-tree-group .tcw-tree-name svg {\n flex: none;\n color: var(--tcw-text-muted);\n}\n.tcw-tree-member {\n margin-left: 14px;\n padding-left: 10px;\n border-inline-start: 1px solid var(--tcw-border-strong);\n border-radius: 0 var(--tcw-radius-sm) var(--tcw-radius-sm) 0;\n}\n.tcw-tree-rename {\n flex: 1;\n min-width: 0;\n padding: 3px 6px;\n border: 1px solid var(--tcw-accent-line);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-tree-rename:focus {\n outline: none;\n box-shadow: 0 0 0 2px var(--tcw-accent-soft);\n}\n.tcw-tree-empty {\n padding: 8px;\n font-size: var(--tcw-font-size-sm);\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 max-height: 30dvh;\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 /* Except the loader's slow glow (opacity only): without it a long wait\n looks frozen. */\n .tcw-root .tcw-loading-candle,\n .tcw-root .tcw-loading-track > span {\n animation-duration: 2.4s !important;\n animation-iteration-count: infinite !important;\n animation-delay: var(--tcw-delay, 0ms) !important;\n }\n}\n\n/* --- Drawing settings dialog --- */\n.tcw-drawing-text {\n min-height: 56px;\n resize: vertical;\n font-family: inherit;\n}\n/* The text a drawing writes takes the dialog's width, under its name. */\n.tcw-text-row {\n flex-direction: column;\n align-items: stretch;\n gap: var(--tcw-space-3);\n}\n.tcw-text-row .tcw-drawing-text { box-sizing: border-box; width: 100%; }\n.tcw-levels-editor { display: grid; gap: var(--tcw-space-3); }\n/* Two columns of levels on a desktop, as a Fibonacci tool has a dozen. */\n.tcw-levels-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--tcw-space-3) var(--tcw-space-6);\n max-height: 260px;\n overflow-y: auto;\n padding-inline-end: var(--tcw-space-1);\n}\n@media (max-width: 640px) {\n .tcw-levels-grid { grid-template-columns: minmax(0, 1fr); }\n}\n.tcw-level-row {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto auto;\n align-items: center;\n gap: var(--tcw-space-3);\n}\n.tcw-level-row .tcw-indi-input { box-sizing: border-box; width: 100%; min-width: 0; }\n.tcw-level-row input[type='checkbox'] { accent-color: var(--tcw-accent); }\n.tcw-level-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: 0;\n border-radius: var(--tcw-radius-sm, 4px);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-level-remove:hover { color: var(--tcw-text); background: var(--tcw-bg-elevated); }\n.tcw-level-remove:focus-visible { outline: 2px solid var(--tcw-accent); outline-offset: 1px; }\n.tcw-level-add { justify-self: start; }\n\n/* --- Context menu (right-click on a drawing) --- */\n.tcw-context-menu {\n position: absolute;\n z-index: 70;\n min-width: 200px;\n /* Taller than the room (many templates, say), it scrolls. */\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: var(--tcw-menu-pad);\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n /* Frosted with the other menus (`ui.blur` above 0): the chart under it blurred, not sharp behind its words. */\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n}\n.tcw-context-item {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n width: 100%;\n min-height: var(--tcw-menu-item-h);\n padding: var(--tcw-space-1) var(--tcw-space-4);\n border: 0;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size);\n text-align: start;\n cursor: pointer;\n}\n.tcw-context-item svg, .tcw-context-icon { flex: none; width: 14px; height: 14px; color: var(--tcw-text-muted); }\n.tcw-context-item:hover, .tcw-context-item:focus-visible { background: var(--tcw-hover-bg); outline: none; }\n.tcw-context-item:focus-visible { box-shadow: inset 0 0 0 1px var(--tcw-accent); }\n.tcw-context-danger, .tcw-context-danger svg { color: var(--tcw-red); }\n.tcw-context-sep { height: 1px; margin: var(--tcw-space-2) var(--tcw-space-4); background: var(--tcw-divider); }\n.tcw-context-label { flex: 1; min-width: 0; }\n/* A shortcut, a count, and the mark of a submenu, at the row's end. */\n.tcw-context-key, .tcw-context-count {\n flex: none;\n margin-inline-start: var(--tcw-space-5);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text-muted);\n}\n.tcw-context-item svg.tcw-context-more { width: 12px; height: 12px; }\n/* Right to left, a submenu opens to the left: its marks point there. */\n[dir='rtl'] .tcw-context-more, [dir='rtl'] .tcw-context-back > svg { transform: scaleX(-1); }\n/* No keyboard under a finger: the keys stay named to a screen reader only. */\n@media (hover: none) { .tcw-context-key { display: none; } }\n.tcw-context-item[aria-expanded='true'] { background: var(--tcw-hover-bg); }\n/* The choice made among radios: a dot where a switch has its tick. */\n.tcw-context-dot { display: grid; place-items: center; }\n.tcw-context-dot::after { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--tcw-text); }\n/* An entry that can be removed: its x on the row in hand, always on a touch screen. */\n.tcw-context-row { display: flex; align-items: center; border-radius: var(--tcw-menu-item-radius); }\n.tcw-context-row .tcw-context-item { flex: 1; min-width: 0; }\n.tcw-context-row:hover { background: var(--tcw-hover-bg); }\n.tcw-context-row:hover .tcw-context-item { background: transparent; }\n.tcw-context-remove {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n margin-inline-end: var(--tcw-space-1);\n border: 0;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-context-row:hover .tcw-context-remove, .tcw-context-row:focus-within .tcw-context-remove { opacity: 1; }\n.tcw-context-remove:hover { color: var(--tcw-red); background: var(--tcw-hover-bg); }\n@media (hover: none) { .tcw-context-remove { opacity: 1; } }\n/* --- Toolbar over a selected drawing --- */\n.tcw-sel-toolbar {\n position: absolute;\n z-index: 65;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-divider);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n font-family: var(--tcw-font);\n white-space: nowrap;\n animation: tcw-sel-in var(--tcw-dur-fast) var(--tcw-ease-out);\n}\n@keyframes tcw-sel-in { from { opacity: 0; transform: translateY(3px); } }\n.tcw-sel-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n min-width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n padding: 0 6px;\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-sel-btn svg { flex: none; }\n.tcw-sel-btn:hover, .tcw-sel-btn[aria-expanded=\"true\"] { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-sel-btn:focus-visible, .tcw-sel-swatch:focus-visible, .tcw-sel-option:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--tcw-accent); }\n.tcw-sel-btn.tcw-sel-on { color: var(--tcw-accent); background: var(--tcw-accent-soft); }\n.tcw-sel-danger:hover { color: var(--tcw-red); background: var(--tcw-red-soft); }\n.tcw-sel-color {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tcw-text) 25%, transparent);\n}\n/* The fill picker: a square, where the line colour is a dot. */\n.tcw-sel-fill { border-radius: 3px; }\n/* The text colour picker: a letter over a bar in the text's colour. */\n.tcw-sel-text {\n font-weight: var(--tcw-weight-strong);\n font-size: var(--tcw-font-size-sm);\n line-height: 1;\n padding-bottom: 1px;\n border-bottom: 3px solid var(--c, currentColor);\n}\n.tcw-sel-width {\n display: inline-block;\n width: 16px;\n height: var(--w, 1px);\n max-height: 6px;\n border-radius: 1px;\n background: currentColor;\n}\n.tcw-sel-sep { flex: none; width: 1px; height: 18px; margin: 0 3px; background: var(--tcw-divider); }\n.tcw-sel-pop {\n position: absolute;\n z-index: 66;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 120px;\n padding: 4px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-divider);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n font-family: var(--tcw-font);\n}\n.tcw-sel-pop--color {\n display: grid;\n grid-template-columns: repeat(4, 24px);\n gap: 6px;\n min-width: 0;\n padding: 8px;\n}\n.tcw-sel-swatch {\n width: 24px;\n height: 24px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tcw-text) 20%, transparent);\n cursor: pointer;\n transition: transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-sel-swatch:hover { transform: scale(1.1); }\n.tcw-sel-swatch.tcw-sel-on { box-shadow: 0 0 0 2px var(--tcw-bg-elevated), 0 0 0 4px var(--tcw-accent); }\n.tcw-sel-option {\n display: flex;\n align-items: center;\n gap: 10px;\n min-height: var(--tcw-menu-item-h);\n padding: 4px 10px;\n border: 0;\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n text-align: start;\n cursor: pointer;\n}\n.tcw-sel-option:hover { background: var(--tcw-bg-surface); }\n.tcw-sel-option.tcw-sel-on { color: var(--tcw-accent); }\n@media (prefers-reduced-motion: reduce) {\n .tcw-sel-toolbar { animation: none; }\n .tcw-sel-swatch { transition: none; }\n}\n\n/* --- The account: a panel under the chart; its head the tabs, the totals, a new order and its close. --- */\n.tcw-account-dock {\n flex: none;\n}\n.tcw-account {\n display: flex;\n flex-direction: column;\n /* 233, on the widget's φ ladder. */\n height: 233px;\n border-top: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n}\n.tcw-account-head {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-height: calc(var(--tcw-space-6) + var(--tcw-space-5));\n padding-inline: var(--tcw-space-4) var(--tcw-space-3);\n border-bottom: 1px solid var(--tcw-divider);\n}\n.tcw-account-tabs {\n display: flex;\n gap: var(--tcw-space-1);\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.tcw-account-tab {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-tab-h);\n padding: var(--tcw-tab-pad);\n border: 0;\n border-radius: var(--tcw-tab-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n cursor: pointer;\n}\n.tcw-account-tab:hover { color: var(--tcw-text); background: var(--tcw-tab-hover); }\n.tcw-account-tab[aria-selected='true'] {\n color: var(--tcw-tab-on-fg);\n background: var(--tcw-tab-on-bg);\n font-weight: var(--tcw-weight-strong);\n box-shadow: inset 0 calc(-1 * var(--tcw-tab-line)) 0 var(--tcw-accent);\n}\n/* A tab's count: a figure in a soft pill. */\n.tcw-account-count {\n min-width: 1.6em;\n padding-inline: var(--tcw-space-2);\n border-radius: 999px;\n background: var(--tcw-hover-bg);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n text-align: center;\n}\n/* The open and realised P&L, on every tab, in the mono figures. Short of room, they keep their start: the open P&L's words stay whole. */\n.tcw-account-totals {\n display: flex;\n flex: 1;\n justify-content: flex-end;\n justify-content: safe flex-end;\n gap: var(--tcw-space-5);\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.tcw-account-new {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: var(--tcw-space-3);\n height: var(--tcw-control-h);\n padding-inline: var(--tcw-space-4);\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n cursor: pointer;\n}\n.tcw-account-new:hover { background: var(--tcw-hover-bg); }\n.tcw-account-tab:focus-visible,\n.tcw-account-new:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n.tcw-account-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\n/* The rows: headings in the label case, figures set right in the mono type. */\n.tcw-account-table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-account-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n height: var(--tcw-control-h);\n padding-inline: var(--tcw-space-4);\n border-bottom: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-align: start;\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n white-space: nowrap;\n}\n.tcw-account-table td {\n height: calc(var(--tcw-control-h) + var(--tcw-space-2));\n padding-inline: var(--tcw-space-4);\n border-bottom: 1px solid var(--tcw-divider);\n color: var(--tcw-text);\n white-space: nowrap;\n}\n.tcw-account-table :is(th, td).tcw-num {\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n text-align: end;\n}\n.tcw-account-table tbody tr:hover td { background: var(--tcw-hover-bg); }\n.tcw-account-side { font-weight: var(--tcw-weight-strong); }\n.tcw-account-buy, .tcw-account-up { color: var(--tcw-green); }\n.tcw-account-sell, .tcw-account-down { color: var(--tcw-red); }\n.tcw-account-actions { display: flex; justify-content: flex-end; gap: var(--tcw-space-1); }\n.tcw-account-empty {\n margin: 0;\n padding: var(--tcw-space-6);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n text-align: center;\n}\n\n/*\n * A narrow widget (a phone, a narrow column): the totals go under the tabs,\n * and each row is a card of named figures. The headings stay for a screen\n * reader, unseen: the cells name themselves on screen. The panel is a step\n * of phi taller (377) for two cards and more, at most 45% of a phone's screen.\n */\n.tcw-root[data-tcw-narrow] .tcw-account {\n height: 377px;\n max-height: 45vh;\n max-height: 45dvh;\n}\n.tcw-root[data-tcw-narrow] .tcw-account-head { flex-wrap: wrap; padding-block: var(--tcw-space-2); }\n/* The tabs give way (they scroll): New order and the close keep the first line. */\n.tcw-root[data-tcw-narrow] .tcw-account-tabs { flex: 1 1 0; }\n.tcw-root[data-tcw-narrow] .tcw-account-totals { order: 3; flex-basis: 100%; justify-content: flex-start; padding-inline: var(--tcw-space-3); }\n.tcw-root[data-tcw-narrow] .tcw-account-table thead {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table,\n.tcw-root[data-tcw-narrow] .tcw-account-table tbody { display: block; }\n.tcw-root[data-tcw-narrow] .tcw-account-table tbody tr {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: var(--tcw-space-2) var(--tcw-space-5);\n padding: var(--tcw-space-4);\n border-bottom: 1px solid var(--tcw-divider);\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table td {\n display: flex;\n justify-content: space-between;\n gap: var(--tcw-space-3);\n height: auto;\n padding: 0;\n border: 0;\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table td::before {\n content: attr(data-label);\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font);\n font-size: var(--tcw-font-size-xs);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n.tcw-root[data-tcw-narrow] .tcw-account-table td:first-child,\n.tcw-root[data-tcw-narrow] .tcw-account-table td[data-label=''] { grid-column: 1 / -1; }\n.tcw-root[data-tcw-narrow] .tcw-account-table td[data-label='']::before { content: none; }\n.tcw-root[data-tcw-narrow] .tcw-account-table td[data-label=''] .tcw-account-actions { width: 100%; }\n.tcw-root[data-tcw-narrow] .tcw-account-table .tcw-tree-btn { width: 34px; height: 34px; }\n\n@media (forced-colors: active) {\n .tcw-account-tab[aria-selected='true'] { outline: 2px solid Highlight; }\n .tcw-account-tab:focus-visible,\n .tcw-account-new:focus-visible { outline: 2px solid Highlight; }\n}\n\n/* --- Named layouts --- */\n.tcw-layouts-btn { max-width: 190px; }\n.tcw-layouts-label {\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n.tcw-layouts-dirty {\n width: 6px;\n height: 6px;\n flex: none;\n border-radius: 50%;\n background: var(--tcw-accent);\n}\n.tcw-name-field { display: flex; flex-direction: column; gap: 6px; font-size: var(--tcw-font-size-sm); color: var(--tcw-text-dim); }\n.tcw-name-field .tcw-indi-input { width: 100%; height: 34px; font-size: var(--tcw-font-size); }\n\n/* --- Chart grid --- */\n.tcw-grid { background: var(--tcw-bg); }\n.tcw-grid-bar {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: calc(var(--tcw-control-h) + 8px);\n padding: 0 8px;\n border-bottom: 1px solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n overflow-x: auto;\n scrollbar-width: none;\n}\n.tcw-grid-bar::-webkit-scrollbar { display: none; }\n.tcw-grid-group { display: flex; align-items: center; gap: 2px; flex: none; }\n.tcw-grid-label {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-right: 4px;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n letter-spacing: var(--tcw-label-tracking);\n text-transform: var(--tcw-label-case);\n color: var(--tcw-text-muted);\n}\n.tcw-grid-sync[aria-pressed=\"true\"] { color: var(--tcw-accent); }\n.tcw-grid-cells {\n flex: 1;\n min-height: 0;\n display: grid;\n gap: 1px;\n background: var(--tcw-border);\n}\n.tcw-grid-cell {\n position: relative;\n min-width: 0;\n min-height: 0;\n background: var(--tcw-bg);\n}\n.tcw-grid-cell-active::after {\n content: '';\n position: absolute;\n inset: 0;\n border: 1px solid var(--tcw-accent);\n pointer-events: none;\n z-index: 5;\n}\n\n/* --- Host toolbar buttons --- */\n.tcw-toolbar-host { display: inline-flex; align-items: center; gap: 2px; }\n.tcw-toolbar-host:empty { display: none; }\n.tcw-host-btn { display: inline-flex; align-items: center; gap: 4px; }\n\n/* --- Host sidebar buttons, status bar items, and the layer over the chart --- */\n.tcw-sidebar-host { display: flex; flex-direction: column; align-items: center; }\n.tcw-sidebar-host:empty { display: none; }\n/* Your items keep their width (the range presets fold for them), and on the left a gap\n before the right group, whose auto margin closes up when the bar is full. */\n.tcw-status-host { display: flex; align-items: center; gap: 10px; flex: none; }\n.tcw-statusbar > .tcw-status-host { margin-inline-end: var(--tcw-space-5); }\n.tcw-status-host:empty { display: none; }\n.tcw-status-host-item { white-space: nowrap; }\n.tcw-status-host-btn {\n margin: -4px -6px;\n padding: 4px 6px;\n font: inherit;\n color: inherit;\n background: transparent;\n border: none;\n border-radius: var(--tcw-control-radius);\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-status-host-btn:hover { color: var(--tcw-text); background: var(--tcw-hover-bg); }\n.tcw-status-host-btn:focus-visible { outline: 2px solid var(--tcw-accent); outline-offset: -2px; }\n/* Over the plot and under the widget's own overlays; the pointer reaches the chart unless an element of yours takes it. */\n.tcw-host-layer { position: absolute; inset: 0; z-index: 2; pointer-events: none; }\n\n/* --- Pane buttons (move, fold, maximise) --- */\n.tcw-pane-controls {\n position: absolute;\n z-index: 4;\n display: flex;\n gap: 1px;\n transform: translateX(-100%);\n padding: 1px;\n border-radius: var(--tcw-radius-sm);\n background: color-mix(in srgb, var(--tcw-bg) 80%, transparent);\n opacity: 0.55;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-pane-controls:hover,\n.tcw-pane-controls:focus-within { opacity: 1; }\n.tcw-pane-btn {\n display: inline-grid;\n place-items: center;\n width: 18px;\n height: 16px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-pane-btn:hover { color: var(--tcw-text); background: var(--tcw-hover-bg); }\n.tcw-pane-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--tcw-accent-soft); }\n\n/* --- Typed interval --- */\n.tcw-interval-input {\n position: absolute;\n z-index: 20;\n left: 50%;\n top: 40%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px 12px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-radius-lg, 10px);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n}\n.tcw-interval-field {\n width: 150px;\n height: 36px;\n padding: 0 10px;\n font: inherit;\n font-size: var(--tcw-font-size-xl);\n font-weight: var(--tcw-weight-strong);\n font-variant-numeric: tabular-nums;\n color: var(--tcw-text);\n background: var(--tcw-bg-surface);\n border: 1px solid var(--tcw-accent);\n border-radius: var(--tcw-input-radius);\n outline: none;\n}\n.tcw-interval-field[aria-invalid] { border-color: var(--tcw-red); }\n.tcw-interval-hint { font-size: var(--tcw-font-size-xs); color: var(--tcw-text-muted); max-width: 170px; }\n\n/* --- Alerts: lines, moves, bar close, expiry --- */\n.tcw-alerts-source { grid-column: auto; }\n.tcw-alerts-row-fields {\n grid-column: 1 / -1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n}\n.tcw-alerts-row-fields[hidden] { display: none; }\n.tcw-alerts-row-fields > input[hidden] { display: none; }\n.tcw-alerts-row-fields:has(> input[hidden]) { grid-template-columns: 1fr; }\n.tcw-alerts-options { align-items: center; }\n.tcw-alerts-form .tcw-alerts-check {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text-dim);\n}\n.tcw-alerts-form .tcw-alerts-check input { width: auto; height: auto; }\n.tcw-alerts-form input[aria-invalid=\"true\"] { border-color: var(--tcw-red); }\n.tcw-alerts-row-meta { margin-top: 2px; font-size: var(--tcw-font-size-xs); color: var(--tcw-text-muted); }\n.tcw-alerts-expired { opacity: 0.6; }\n\n/* --- Signal marker note --- */\n.tcw-marker-tip {\n position: absolute;\n z-index: 12;\n pointer-events: none;\n padding: 6px 8px;\n border: 1px solid var(--tcw-border);\n border-radius: var(--tcw-tooltip-radius);\n background: var(--tcw-tooltip-bg);\n color: var(--tcw-tooltip-fg);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.45;\n font-variant-numeric: tabular-nums;\n box-shadow: var(--tcw-menu-shadow);\n max-width: 240px;\n}\n.tcw-marker-tip strong { display: block; font-size: var(--tcw-font-size-sm); }\n\n/* === Navigation over the chart ===\n * Centred on the plot's bottom edge, shown while a mouse is over the chart. */\n.tcw-nav {\n position: absolute;\n z-index: 15;\n display: flex;\n gap: 2px;\n padding: 3px;\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: calc(var(--tcw-control-radius) + 3px);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n opacity: 0;\n pointer-events: none;\n transform: translate(-50%, calc(-100% - 12px));\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-nav.tcw-nav-shown {\n opacity: 1;\n pointer-events: auto;\n}\n.tcw-nav-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n border: 0;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n touch-action: none;\n}\n.tcw-nav-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n.tcw-nav-btn:active {\n background: var(--tcw-active-bg);\n}\n.tcw-nav-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n.tcw-nav-btn svg {\n width: var(--tcw-icon);\n height: var(--tcw-icon);\n}\n@media (hover: none) {\n .tcw-nav { display: none; }\n}\n\n/* === Symbol info ===\n * Top left, beside the drawing tools: the panels on the right stay clear. */\n.tcw-syminfo {\n position: absolute;\n top: var(--tcw-panel-top);\n inset-inline-start: var(--tcw-panel-left);\n z-index: 38;\n width: 288px;\n max-height: calc(100% - var(--tcw-panel-top) - 12px);\n display: flex;\n flex-direction: column;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-panel-radius);\n box-shadow: var(--tcw-menu-shadow);\n overflow: hidden;\n animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;\n}\n.tcw-syminfo-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 9px 12px;\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n border-bottom: 1px solid var(--tcw-border);\n}\n.tcw-syminfo-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n.tcw-syminfo-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }\n.tcw-syminfo-body,\n.tcw-syminfo-news {\n padding: 12px 14px;\n overflow-y: auto;\n}\n.tcw-syminfo-body {\n display: grid;\n gap: 10px;\n}\n.tcw-syminfo-symbol {\n font-size: var(--tcw-font-size-lg);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n}\n.tcw-syminfo-desc {\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text-dim);\n}\n.tcw-syminfo-meta {\n margin-top: 2px;\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n.tcw-syminfo-quote {\n display: flex;\n align-items: baseline;\n gap: 10px;\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n.tcw-syminfo-price {\n font-size: var(--tcw-font-size-display);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text);\n}\n.tcw-syminfo-change { font-size: var(--tcw-font-size-sm); }\n.tcw-syminfo-change.tcw-up { color: var(--tcw-green); }\n.tcw-syminfo-change.tcw-down { color: var(--tcw-red); }\n.tcw-syminfo-status {\n display: flex;\n align-items: center;\n gap: 7px;\n font-size: var(--tcw-font-size-sm);\n color: var(--tcw-text-dim);\n}\n.tcw-syminfo-status::before,\n.tcw-status-market::before {\n content: '';\n flex: none;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--tcw-text-muted);\n}\n.tcw-syminfo-status[data-state='open']::before,\n.tcw-syminfo-status[data-state='always']::before,\n.tcw-status-market[data-state='open']::before {\n background: var(--tcw-green);\n}\n.tcw-syminfo-stats {\n display: grid;\n gap: 4px;\n margin: 0;\n padding-top: 10px;\n border-top: 1px solid var(--tcw-divider);\n}\n.tcw-syminfo-stat {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-syminfo-stat dt { color: var(--tcw-text-muted); }\n.tcw-syminfo-stat dd {\n margin: 0;\n color: var(--tcw-text);\n text-align: end;\n font-variant-numeric: tabular-nums;\n overflow-wrap: anywhere;\n}\n.tcw-syminfo-news {\n border-top: 1px solid var(--tcw-divider);\n}\n.tcw-syminfo-news-title {\n margin-bottom: 8px;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text-muted);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n.tcw-syminfo-news-list {\n display: grid;\n gap: 10px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.tcw-syminfo-news-item {\n font-size: var(--tcw-font-size-sm);\n line-height: 1.4;\n color: var(--tcw-text);\n}\n.tcw-syminfo-news-item a {\n color: var(--tcw-text);\n text-decoration: none;\n}\n.tcw-syminfo-news-item a:hover { color: var(--tcw-accent); text-decoration: underline; }\n.tcw-syminfo-news-item a:focus-visible { outline: none; box-shadow: var(--tcw-ring); border-radius: var(--tcw-radius-xs); }\n.tcw-syminfo-news-meta,\n.tcw-syminfo-news-note {\n margin-top: 2px;\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n\n/* Numbers keep their sign on the left, and mixed text its own order, in a right-to-left widget too. */\n.tcw-watchlist-price,\n.tcw-watchlist-change,\n.tcw-syminfo-price,\n.tcw-syminfo-change {\n unicode-bidi: isolate;\n direction: ltr;\n}\n.tcw-syminfo-desc,\n.tcw-syminfo-meta,\n.tcw-syminfo-status,\n.tcw-syminfo-stat dd,\n.tcw-syminfo-news-meta {\n unicode-bidi: plaintext;\n}\n\n/* The market's status in the status bar. */\n.tcw-status-market {\n display: flex;\n align-items: center;\n gap: 7px;\n color: var(--tcw-text-muted);\n}\n\n@media (max-width: 640px) {\n .tcw-syminfo {\n top: auto;\n bottom: 0;\n left: 0;\n right: 0;\n width: 100vw;\n max-height: 70%;\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 0 0;\n }\n}\n\n/* === The look: how chosen controls show, floating bars, segmented intervals ===\n * Each switch sets variables on its own root, which its parts read: a grid's\n * look never reaches into a chart that has one of its own. */\n\n/* A chosen button (`ui.active`): a tinted fill (default), a solid pill, or an underline.\n * Dialog tabs are chips, or underlined in the underline look. Panels sit below the\n * toolbar and beside the drawing tools. */\n.tcw-root {\n --tcw-on-bg: var(--tcw-accent-soft);\n --tcw-on-fg: var(--tcw-accent);\n --tcw-on-ring: none;\n --tcw-on-icon-bg: var(--tcw-accent-soft);\n --tcw-on-icon-fg: var(--tcw-accent);\n --tcw-on-icon-ring: none;\n --tcw-tabs-pad-block: var(--tcw-space-4);\n --tcw-tab-h: var(--tcw-control-h);\n --tcw-tab-pad: 0 var(--tcw-space-5);\n --tcw-tab-line: 0px;\n --tcw-tab-radius: var(--tcw-control-radius);\n --tcw-tab-hover: var(--tcw-hover-bg);\n --tcw-tab-on-bg: var(--tcw-on-bg);\n --tcw-tab-on-fg: var(--tcw-on-fg);\n /* A menu's rows sit inside its padding with corners that follow its own: the menu's\n * corner less the padding between, so the two curves run parallel (Print: 5 - 3 = 2). */\n --tcw-menu-pad: var(--tcw-space-2);\n --tcw-menu-item-radius: max(0px, calc(var(--tcw-menu-radius) - var(--tcw-menu-pad)));\n --tcw-panel-top: calc(var(--tcw-toolbar-h) + var(--tcw-space-3));\n --tcw-panel-left: calc(var(--tcw-sidebar-w) + var(--tcw-space-5));\n}\n.tcw-root[data-tcw-active='solid'] {\n --tcw-on-bg: var(--tcw-text);\n --tcw-on-fg: var(--tcw-bg);\n --tcw-on-icon-bg: var(--tcw-text);\n --tcw-on-icon-fg: var(--tcw-bg);\n}\n/* Print picks a tool in ink blue on a tint: a solid square would outweigh the chart beside it. */\n.tcw-root[data-tcw-ui='print'][data-tcw-active='solid'] {\n --tcw-on-icon-bg: var(--tcw-accent-soft);\n --tcw-on-icon-fg: var(--tcw-accent);\n}\n.tcw-root[data-tcw-active='underline'] {\n --tcw-on-bg: var(--tcw-active-bg);\n --tcw-on-fg: var(--tcw-text);\n --tcw-on-ring: inset 0 -2px 0 var(--tcw-accent);\n --tcw-on-icon-bg: var(--tcw-active-bg);\n --tcw-on-icon-fg: var(--tcw-accent);\n --tcw-on-icon-ring: inset 2px 0 0 var(--tcw-accent);\n --tcw-tabs-pad-block: 0px;\n --tcw-tab-h: auto;\n --tcw-tab-pad: 11px 14px;\n --tcw-tab-line: 2px;\n --tcw-tab-radius: 0px;\n --tcw-tab-hover: transparent;\n --tcw-tab-on-bg: transparent;\n --tcw-tab-on-fg: var(--tcw-accent);\n}\n.tcw-root[data-tcw-toolbar='floating'] {\n --tcw-panel-top: calc(var(--tcw-toolbar-h) + 2 * var(--tcw-border-w) + 14px);\n}\n.tcw-root[data-tcw-sidebar='floating'] {\n --tcw-panel-left: calc(var(--tcw-sidebar-w) + 2 * var(--tcw-border-w) + 22px);\n}\n\n/* The toolbar as an island (`ui.toolbar: 'floating'`). */\n.tcw-root[data-tcw-toolbar='floating'] > .tcw-toolbar {\n margin: 8px 10px 0;\n padding-inline: calc(min(var(--tcw-toolbar-radius), var(--tcw-toolbar-h) / 2) / 2 + 8px);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-toolbar-radius);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n}\n\n/* The drawing tools as an island (`ui.sidebar: 'floating'`). */\n.tcw-root[data-tcw-sidebar='floating'] > .tcw-body > .tcw-sidebar {\n align-self: flex-start;\n max-height: calc(100% - 20px);\n margin: 10px 6px 10px 10px;\n padding-block: calc(min(var(--tcw-sidebar-radius), var(--tcw-sidebar-w) / 2) / 2 + 6px);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-sidebar-radius);\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-menu-shadow);\n}\n\n/* Frosted menus (`ui.blur` above 0): the chart shows through, blurred. */\n@supports (background: color-mix(in srgb, red 50%, transparent)) {\n .tcw-dropdown,\n .tcw-flyout,\n .tcw-context-menu {\n background: color-mix(in srgb, var(--tcw-bg-elevated) var(--tcw-surface-opacity), transparent);\n }\n}\n\n/* The interval buttons in one track (`ui.intervals: 'segmented'`). */\n.tcw-root[data-tcw-intervals='segmented'] > .tcw-toolbar > .tcw-tf-group {\n gap: 2px;\n margin: 0 4px;\n padding: 3px;\n border-radius: calc(var(--tcw-control-radius) + 3px);\n background: var(--tcw-hover-bg);\n}\n.tcw-root[data-tcw-intervals='segmented'] > .tcw-toolbar > .tcw-tf-group .tcw-btn {\n height: calc(var(--tcw-control-h) - 6px);\n padding: 0 9px;\n}\n\n/* Phones: the variants keep comfortable tap targets and room for the bar. */\n@media (max-width: 768px) {\n .tcw-root[data-tcw-intervals='segmented'] > .tcw-toolbar > .tcw-tf-group .tcw-btn {\n height: max(34px, calc(var(--tcw-control-h) - 6px));\n padding: 0 10px;\n }\n .tcw-root[data-tcw-toolbar='floating'] > .tcw-toolbar {\n margin: 6px 6px 0;\n padding-inline: 4px;\n }\n .tcw-root[data-tcw-sidebar='floating'] > .tcw-body > .tcw-sidebar {\n margin: 6px 4px 6px 6px;\n }\n}\n\n/* --- Phones and tablets --- */\n\n/* Taps without the grey flash or the double-tap zoom's wait. The chart area\n sets its own touch-action for its gestures. */\n.tcw-root {\n -webkit-tap-highlight-color: transparent;\n touch-action: manipulation;\n}\n\n/* iOS zooms the page into an input under 16 px when it takes focus. */\n@media (pointer: coarse) {\n .tcw-root input:not([type='color']):not([type='range']):not([type='checkbox']):not([type='radio']),\n .tcw-root select,\n .tcw-root textarea {\n font-size: max(16px, 1em);\n }\n}\n\n/* Sheets and lists scroll on their own, without dragging the page behind them. */\n.tcw-modal {\n overscroll-behavior: contain;\n}\n\n/* === The bars' newer parts ===\n * Interval sections and the chart type's icon, the Trade menu's button, undo\n * and redo off while idle, the tool menus' shortcuts and stars, the status\n * bar's clock and scale switches, and the grip of the selection toolbar. */\n\n/* The interval menu: each unit under its heading, a hairline between them. */\n.tcw-tf-section + .tcw-tf-section {\n margin-top: var(--tcw-space-2);\n padding-top: var(--tcw-space-1);\n border-top: 1px solid var(--tcw-divider);\n}\n\n/* The chart type: its icon alone, square. */\n.tcw-dropdown-trigger[data-role='charttype'] {\n justify-content: center;\n width: var(--tcw-control-h);\n padding: 0;\n}\n\n/* Undo and redo with nothing to do: there, quiet, not pressable. */\n.tcw-btn-icon:disabled {\n opacity: 0.35;\n cursor: default;\n background: transparent;\n color: var(--tcw-text-muted);\n}\n\n/* A tool menu's row: the tool, its shortcut, and a star beside it. */\n.tcw-flyout-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n}\n.tcw-flyout-row > .tcw-flyout-item {\n flex: 1;\n min-width: 0;\n}\n.tcw-flyout-name {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.tcw-flyout-key {\n flex: none;\n margin-inline-start: var(--tcw-space-5);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n color: var(--tcw-text-muted);\n}\n.tcw-flyout-pin {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n/* Shown on the row in hand; always for a pinned tool, filled in ink blue; always on a touch screen. */\n.tcw-flyout-row:hover .tcw-flyout-pin,\n.tcw-flyout-row:focus-within .tcw-flyout-pin,\n.tcw-flyout-pin[aria-pressed='true'],\n.tcw-root[data-tcw-narrow] .tcw-flyout-pin {\n opacity: 1;\n}\n@media (hover: none) {\n .tcw-flyout-pin {\n opacity: 1;\n }\n}\n.tcw-flyout-pin:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n.tcw-flyout-pin[aria-pressed='true'] {\n color: var(--tcw-accent);\n}\n.tcw-flyout-pin[aria-pressed='true'] svg path {\n fill: currentColor;\n}\n\n/* The clock: the time in figures, the zone beside it; it opens the zones. */\n.tcw-status-clock,\n.tcw-status-scale-btn {\n height: var(--tcw-control-h-sm);\n padding: 0 var(--tcw-space-3);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n cursor: pointer;\n transition: color var(--tcw-dur-fast) var(--tcw-ease), background var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-status-clock {\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n.tcw-status-clock:hover,\n.tcw-status-scale-btn:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n.tcw-status-clock:focus-visible,\n.tcw-status-scale-btn:focus-visible {\n outline: 2px solid var(--tcw-accent);\n outline-offset: -2px;\n}\n\n/* The scale switches: %, log, auto, in ink blue while on. */\n.tcw-status-scale {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n padding-inline-start: var(--tcw-space-3);\n border-inline-start: var(--tcw-sep-w) solid var(--tcw-border);\n}\n.tcw-status-scale-btn[aria-pressed='true'] {\n color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n/* A narrow widget keeps the range presets and the clock: the scale switches (also in the\n settings and the scale's menu) give them the room, and the connection's word is left to\n screen readers beside its dot. */\n.tcw-root[data-tcw-narrow] .tcw-status-scale {\n display: none;\n}\n/* The market's status in a word (\"Closed\"), when even with everything folded under \"more\"\n the bar has no room: the full words are left to screen readers and the tooltip. */\n.tcw-status-market-short {\n display: none;\n}\n.tcw-statusbar--short-market .tcw-status-market-short {\n display: inline;\n}\n.tcw-root[data-tcw-narrow] .tcw-status-indicator > span:not(.tcw-status-dot),\n.tcw-statusbar--short-market .tcw-status-market-text {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* The selection toolbar's grip: dots to take it by. */\n.tcw-sel-grip {\n flex: none;\n width: var(--tcw-space-4);\n height: var(--tcw-control-h-sm);\n margin-inline: var(--tcw-space-1) var(--tcw-space-2);\n background-image: radial-gradient(circle, var(--tcw-text-muted) 1px, transparent 1.4px);\n background-size: 4px 4px;\n background-position: center;\n opacity: 0.7;\n cursor: grab;\n touch-action: none;\n}\n.tcw-sel-grip:active {\n cursor: grabbing;\n}\n\n/* --- A narrow widget (a phone, or a narrow column): data-tcw-narrow ---\n Set from the widget's own width, below 641px. The toolbar keeps the\n chart's own controls (symbol, interval, type, indicators) and puts the\n rest under \"more\"; the drawing tools wait behind a button over the chart;\n a grid shows one chart at a time, picked by its tab. */\n\n.tcw-toolbar-more,\n.tcw-sidebar-fab,\n.tcw-tf-current,\n.tcw-grid-tabs {\n display: none;\n}\n\n/* The toolbar fits itself too (on a tablet, a window half a screen wide):\n the right-hand buttons that don't fit fold under \"more\" (`--collapsed`\n shows it), a host's left-hand ones last, and `--icons` drops the menus'\n labels and the interval buttons. Narrow folds them all. */\n.tcw-toolbar [data-tcw-folded],\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-toolbar-overflow {\n display: none;\n}\n.tcw-toolbar--collapsed > .tcw-toolbar-more,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar > .tcw-toolbar-more {\n display: inline-flex;\n margin-inline-start: auto;\n}\n.tcw-toolbar--icons.tcw-toolbar--tf-menu > .tcw-tf-group,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar.tcw-toolbar--tf-menu > .tcw-tf-group {\n display: none;\n}\n.tcw-toolbar--icons .tcw-tf-more,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-tf-more {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 10px;\n}\n.tcw-toolbar--icons .tcw-tf-current,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-tf-current {\n display: inline;\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-accent);\n}\n.tcw-toolbar--icons .tcw-trigger-label,\n.tcw-root[data-tcw-narrow] > .tcw-toolbar .tcw-trigger-label {\n display: none;\n}\n\n/* The drawing tools lie over the chart when opened, from its edge. */\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n /* Under the toolbar (20), whose menus open over it. */\n z-index: 18;\n box-shadow: var(--tcw-menu-shadow);\n transform: translateX(-100%);\n visibility: hidden;\n transition: transform var(--tcw-dur-normal) var(--tcw-ease-out), visibility 0s linear var(--tcw-dur-normal);\n}\n.tcw-root[data-tcw-narrow][dir='rtl'] > .tcw-body > .tcw-sidebar {\n transform: translateX(100%);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar.tcw-sidebar-open {\n transform: none;\n visibility: visible;\n transition: transform var(--tcw-dur-normal) var(--tcw-ease-out), visibility 0s;\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-flyout {\n z-index: 19;\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n /* Over the plot, in from its left edge (the widget sets where it starts): the\n price axis stays on the chart's right in either direction, so a\n right-to-left widget keeps the button on the left too, off the axis. */\n left: calc(var(--tcw-fab-plot-left, 0px) + 10px);\n /* Clear of the time axis. */\n bottom: 44px;\n z-index: 17;\n width: 44px;\n height: 44px;\n padding: 0;\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: 999px;\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text);\n box-shadow: var(--tcw-menu-shadow);\n cursor: pointer;\n transition: background var(--tcw-dur-fast), color var(--tcw-dur-fast), border-color var(--tcw-dur-fast);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab.tcw-active {\n background: var(--tcw-accent);\n border-color: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n.tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar-fab[aria-expanded='true'] {\n visibility: hidden;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar,\n .tcw-root[data-tcw-narrow] > .tcw-body > .tcw-sidebar.tcw-sidebar-open {\n transition: none;\n }\n}\n\n/* A narrow grid: one chart at a time, a tab for each. */\n.tcw-grid[data-tcw-narrow] > .tcw-grid-bar > .tcw-grid-tabs {\n display: flex;\n}\n.tcw-grid-tab {\n white-space: nowrap;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells {\n display: flex;\n flex-direction: column;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells > .tcw-grid-cell {\n flex: 1;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells > .tcw-grid-cell:not(.tcw-grid-cell-current) {\n display: none;\n}\n.tcw-grid-has-tabs[data-tcw-narrow] > .tcw-grid-cells > .tcw-grid-cell-active::after {\n display: none;\n}\n\n/* Phones: menus open as sheets from the bottom, in reach of a thumb and\n never off screen (a menu's own place may be off the side of a phone). */\n@media (max-width: 640px) {\n .tcw-dropdown,\n .tcw-context-menu {\n position: fixed !important;\n /* Above the on-screen keyboard (the indicators' search). */\n inset: auto 0 var(--tcw-keyboard-inset, 0px) 0 !important;\n margin: 0 !important;\n width: auto;\n max-width: none;\n max-height: 70vh !important;\n max-height: 70dvh !important;\n overflow-y: auto;\n overscroll-behavior: contain;\n z-index: 80;\n padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px));\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 0 0;\n border-bottom: none;\n }\n .tcw-dropdown-item,\n .tcw-context-item {\n min-height: 44px;\n }\n}\n", Zt = "/* === Base controls: fields, selects, checks, sliders, calendar, scrollbars ===\n *\n * One look for every form control in the widget, from tokens. Fields are\n * quiet until used: a faint fill and hairline, a firmer line on hover, and\n * on focus the line turns accent (no ring). Selects and date fields open\n * the widget's own list and calendar (formControls.ts).\n */\n\n.tcw-root {\n color-scheme: dark;\n\n --tcw-field-bg: rgba(230, 227, 220, 0.04);\n --tcw-field-bg-hover: rgba(230, 227, 220, 0.06);\n --tcw-field-bg-focus: rgba(230, 227, 220, 0.03);\n --tcw-field-line: rgba(230, 227, 220, 0.12);\n --tcw-field-line-hover: rgba(230, 227, 220, 0.22);\n --tcw-field-line-focus: var(--tcw-accent-line);\n --tcw-field-placeholder: var(--tcw-text-muted);\n --tcw-check-line: rgba(230, 227, 220, 0.3);\n --tcw-scroll-thumb: rgba(230, 227, 220, 0.14);\n --tcw-scroll-thumb-hover: rgba(230, 227, 220, 0.26);\n /* Glyphs drawn in a field's background (a background image takes no currentColor). */\n --tcw-field-chevron: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.75l3 3 3-3' fill='none' stroke='%23918f8a' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n --tcw-field-calendar: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg fill='none' stroke='%23918f8a' stroke-width='1.3' stroke-linecap='round'%3E%3Crect x='2.5' y='3.5' width='11' height='10' rx='2'/%3E%3Cpath d='M2.5 6.5h11M5.5 2v3M10.5 2v3'/%3E%3C/g%3E%3C/svg%3E\");\n --tcw-check-mark: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.25l2.6 2.6L12 5.5' fill='none' stroke='%23131416' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n}\n\n.tcw-root[data-tcw-theme='light'] {\n color-scheme: light;\n\n /* Fields are white boxes on the paper, ruled in ink, as on a printed form. */\n --tcw-field-bg: #ffffff;\n --tcw-field-bg-hover: #ffffff;\n --tcw-field-bg-focus: #ffffff;\n --tcw-field-line: rgba(27, 29, 33, 0.16);\n --tcw-field-line-hover: rgba(27, 29, 33, 0.3);\n --tcw-check-line: rgba(27, 29, 33, 0.34);\n --tcw-scroll-thumb: rgba(27, 29, 33, 0.16);\n --tcw-scroll-thumb-hover: rgba(27, 29, 33, 0.3);\n --tcw-field-chevron: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.75l3 3 3-3' fill='none' stroke='%236a6e75' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n --tcw-field-calendar: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg fill='none' stroke='%236a6e75' stroke-width='1.3' stroke-linecap='round'%3E%3Crect x='2.5' y='3.5' width='11' height='10' rx='2'/%3E%3Cpath d='M2.5 6.5h11M5.5 2v3M10.5 2v3'/%3E%3C/g%3E%3C/svg%3E\");\n --tcw-check-mark: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.25l2.6 2.6L12 5.5' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n}\n\n/* --- Text, number, date and time fields, and selects --- */\n\n/* Fields speak the widget's type, not the browser's (a part's own font still wins).\n * The browser's control font resets the OpenType features, so --tcw-font-features\n * set on .tcw-root reaches every button and field only through this. */\n:where(.tcw-root) :where(input, select, textarea, button) {\n font-family: inherit;\n font-weight: inherit;\n letter-spacing: inherit;\n font-feature-settings: inherit;\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-settings-select,\n .tcw-settings-number,\n .tcw-goto-input,\n .tcw-watchlist-input,\n .tcw-indi-input,\n .tcw-style-name,\n .tcw-drawing-text,\n .tcw-replay-speed,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-alerts-form select\n) {\n border: 1px solid var(--tcw-field-line);\n border-radius: var(--tcw-input-radius);\n background-color: var(--tcw-field-bg);\n color: var(--tcw-text);\n outline: none;\n box-shadow: none;\n transition:\n border-color var(--tcw-dur-fast) var(--tcw-ease),\n background-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-settings-select,\n .tcw-settings-number,\n .tcw-goto-input,\n .tcw-watchlist-input,\n .tcw-indi-input,\n .tcw-style-name,\n .tcw-drawing-text,\n .tcw-replay-speed,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-alerts-form select\n):hover:not(:disabled, :focus) {\n border-color: var(--tcw-field-line-hover);\n background-color: var(--tcw-field-bg-hover);\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-settings-select,\n .tcw-settings-number,\n .tcw-goto-input,\n .tcw-watchlist-input,\n .tcw-indi-input,\n .tcw-style-name,\n .tcw-drawing-text,\n .tcw-replay-speed,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-alerts-form select\n):is(:focus, :focus-visible, [aria-expanded='true']) {\n border-color: var(--tcw-field-line-focus);\n background-color: var(--tcw-field-bg-focus);\n outline: none;\n box-shadow: none;\n}\n\n.tcw-root :is(\n .tcw-tf-custom-input,\n .tcw-indi-input,\n .tcw-watchlist-input,\n .tcw-goto-input,\n .tcw-alerts-form input:not([type='checkbox']),\n .tcw-settings-number\n):is([aria-invalid='true']):is(*, :hover, :focus) {\n /* As specific as the hover rule (its list holds the same :not) and later, so a wrong value stays red\n under the pointer and in focus. */\n border-color: var(--tcw-red);\n box-shadow: none;\n}\n\n.tcw-root :is(input, textarea)::placeholder {\n color: var(--tcw-field-placeholder);\n opacity: 1;\n}\n\n.tcw-root :is(input, select, textarea):disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Selects: the browser's arrow gives way to a fine chevron. */\n.tcw-root select:not([multiple]):not([size]) {\n appearance: none;\n -webkit-appearance: none;\n background-image: var(--tcw-field-chevron);\n background-repeat: no-repeat;\n background-size: 12px 12px;\n background-position: right 8px center;\n padding-inline-end: 26px;\n text-overflow: ellipsis;\n cursor: pointer;\n}\n\n.tcw-root[dir='rtl'] select:not([multiple]):not([size]),\n.tcw-root [dir='rtl'] select:not([multiple]):not([size]) {\n background-position: left 8px center;\n}\n\n/* A select laid out left to right inside a right-to-left widget (the chart's\n * own area is LTR, the replay's figures too) keeps its chevron on the right,\n * where its padding is. */\n.tcw-root[dir='rtl'] [dir='ltr'] select:not([multiple]):not([size]),\n.tcw-root[dir='rtl'] select[dir='ltr']:not([multiple]):not([size]) {\n background-position: right 8px center;\n}\n\n/* Number fields: the steppers show only on a field in use. */\n.tcw-root input[type='number']::-webkit-inner-spin-button,\n.tcw-root input[type='number']::-webkit-outer-spin-button {\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root input[type='number']:is(:hover, :focus)::-webkit-inner-spin-button {\n opacity: 0.55;\n}\n\n/* Date and time: the widget's calendar icon where the browser's own can be hidden. */\n@supports selector(::-webkit-calendar-picker-indicator) {\n .tcw-root input[type='date'] {\n background-image: var(--tcw-field-calendar);\n background-repeat: no-repeat;\n background-size: 15px 15px;\n background-position: right 8px center;\n padding-inline-end: 30px;\n cursor: text;\n }\n\n .tcw-root[dir='rtl'] input[type='date'],\n .tcw-root [dir='rtl'] input[type='date'] {\n background-position: left 8px center;\n }\n}\n\n.tcw-root input:is([type='date'], [type='time'])::-webkit-calendar-picker-indicator {\n display: none;\n}\n\n.tcw-root input:is([type='date'], [type='time'])::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n}\n\n/* --- Checkboxes and radios --- */\n\n.tcw-root input:is([type='checkbox'], [type='radio']) {\n appearance: none;\n -webkit-appearance: none;\n flex-shrink: 0;\n width: 16px;\n height: 16px;\n margin: 0;\n border: 1.5px solid var(--tcw-check-line);\n border-radius: var(--tcw-radius-sm);\n background: transparent center / 14px 14px no-repeat;\n cursor: pointer;\n vertical-align: middle;\n transition:\n border-color var(--tcw-dur-fast) var(--tcw-ease),\n background-color var(--tcw-dur-fast) var(--tcw-ease),\n box-shadow var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root input[type='radio'] {\n border-radius: 50%;\n}\n\n.tcw-root input:is([type='checkbox'], [type='radio']):hover:not(:disabled) {\n border-color: var(--tcw-text-dim);\n}\n\n.tcw-root input[type='checkbox']:checked {\n border-color: var(--tcw-accent);\n background-color: var(--tcw-accent);\n background-image: var(--tcw-check-mark);\n}\n\n.tcw-root input[type='radio']:checked {\n border-color: var(--tcw-accent);\n background-image: radial-gradient(circle, var(--tcw-accent) 0 3.5px, transparent 4px);\n}\n\n.tcw-root input:is([type='checkbox'], [type='radio']):focus {\n outline: none;\n}\n\n.tcw-root input:is([type='checkbox'], [type='radio']):focus-visible {\n box-shadow: 0 0 0 3px var(--tcw-accent-soft);\n}\n\n/* --- Sliders --- */\n\n.tcw-root input[type='range'] {\n appearance: none;\n -webkit-appearance: none;\n height: 4px;\n border-radius: 999px;\n background: var(--tcw-field-line-hover);\n outline: none;\n cursor: pointer;\n}\n\n.tcw-root input[type='range']::-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 1px 3px rgba(0, 0, 0, 0.35);\n transition: transform var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-root input[type='range']::-moz-range-thumb {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--tcw-accent);\n border: 2px solid var(--tcw-bg-elevated);\n}\n\n.tcw-root input[type='range']:hover::-webkit-slider-thumb {\n transform: scale(1.12);\n}\n\n.tcw-root input[type='range']:focus-visible::-webkit-slider-thumb {\n box-shadow: 0 0 0 4px var(--tcw-accent-soft);\n}\n\n/* --- The select list --- */\n\n.tcw-select-menu {\n z-index: 120;\n padding: var(--tcw-menu-pad);\n max-width: min(360px, calc(100vw - 16px));\n font-size: var(--tcw-font-size);\n}\n\n.tcw-select-group {\n padding: var(--tcw-space-4) var(--tcw-space-4) var(--tcw-space-2);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text-muted);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-select-option {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n min-height: var(--tcw-menu-item-h);\n padding-block: 0;\n padding-inline: var(--tcw-space-3) var(--tcw-space-5);\n border-radius: var(--tcw-menu-item-radius);\n color: var(--tcw-text-dim);\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n}\n\n.tcw-select-option-text {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-select-check {\n flex-shrink: 0;\n width: 14px;\n height: 14px;\n}\n\n.tcw-select-option.tcw-active {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-select-option[aria-selected='true'] {\n color: var(--tcw-text);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-select-option[aria-selected='true'] .tcw-select-check {\n background: var(--tcw-accent);\n -webkit-mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.25l3 3L12.5 5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center / contain no-repeat;\n mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.25l3 3L12.5 5' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center / contain no-repeat;\n}\n\n.tcw-select-option[aria-disabled='true'] {\n opacity: 0.4;\n cursor: default;\n background: none;\n}\n\n/* --- The calendar --- */\n\n.tcw-calendar {\n z-index: 120;\n width: 268px;\n padding: 10px;\n background: var(--tcw-bg-elevated);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-menu-radius);\n box-shadow: var(--tcw-menu-shadow);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n backdrop-filter: blur(var(--tcw-blur));\n -webkit-backdrop-filter: blur(var(--tcw-blur));\n animation: tcw-pop-in var(--tcw-dur-normal) var(--tcw-ease-out);\n}\n\n.tcw-calendar-head {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-bottom: 8px;\n}\n\n.tcw-calendar-title {\n flex: 1;\n text-align: center;\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n letter-spacing: -0.01em;\n}\n\n.tcw-calendar-nav {\n display: inline-grid;\n place-items: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-radius-sm);\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}\n\n.tcw-calendar-nav svg {\n width: 16px;\n height: 16px;\n fill: none;\n stroke: currentColor;\n stroke-width: 1.6;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.tcw-calendar[dir='rtl'] .tcw-calendar-nav svg,\n[dir='rtl'] .tcw-calendar-nav svg {\n transform: scaleX(-1);\n}\n\n.tcw-calendar-nav:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-calendar-weekdays,\n.tcw-calendar-grid {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n}\n\n.tcw-calendar-weekdays {\n margin-bottom: 4px;\n padding: 3px 0;\n border-radius: var(--tcw-radius-sm);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-calendar-weekday {\n text-align: center;\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n color: var(--tcw-text-muted);\n line-height: 20px;\n}\n\n.tcw-calendar-grid {\n row-gap: 2px;\n}\n\n.tcw-calendar-week {\n display: contents;\n}\n\n.tcw-calendar-day {\n position: relative;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-calendar-day:hover:not(:disabled) {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-calendar-day.tcw-outside {\n color: var(--tcw-text-muted);\n opacity: 0.55;\n}\n\n/* Today: accent figures over a short line. */\n.tcw-calendar-day.tcw-today {\n color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-calendar-day.tcw-today::after {\n content: '';\n position: absolute;\n left: 50%;\n bottom: 5px;\n width: 12px;\n height: 2px;\n margin-left: -6px;\n border-radius: 1px;\n background: currentColor;\n}\n\n.tcw-calendar-day[aria-selected='true'] {\n background: var(--tcw-accent);\n color: var(--tcw-accent-ink);\n font-weight: var(--tcw-weight-strong);\n opacity: 1;\n}\n\n.tcw-calendar-day:disabled {\n opacity: 0.28;\n cursor: not-allowed;\n}\n\n.tcw-calendar-day:focus {\n outline: none;\n}\n\n.tcw-calendar-day:focus-visible {\n box-shadow: inset 0 0 0 1.5px var(--tcw-accent);\n}\n\n.tcw-calendar-foot {\n display: flex;\n justify-content: flex-end;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-calendar-today {\n height: 26px;\n padding: 0 10px;\n border: none;\n border-radius: var(--tcw-radius-sm);\n background: transparent;\n color: var(--tcw-accent);\n font: inherit;\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n}\n\n.tcw-calendar-today:hover {\n background: var(--tcw-accent-soft);\n}\n\n.tcw-calendar-today:focus-visible,\n.tcw-calendar-nav:focus-visible {\n outline: none;\n box-shadow: inset 0 0 0 1.5px var(--tcw-accent);\n}\n\n/* --- Scrollbars: thin and rounded, a thumb on no track. Low specificity:\n a part that hides its bar keeps it hidden. --- */\n\n:where(.tcw-root) ::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n\n:where(.tcw-root) ::-webkit-scrollbar-track,\n:where(.tcw-root) ::-webkit-scrollbar-corner {\n background: transparent;\n}\n\n:where(.tcw-root) ::-webkit-scrollbar-thumb {\n background: var(--tcw-scroll-thumb);\n background-clip: padding-box;\n border: 3px solid transparent;\n border-radius: 999px;\n}\n\n:where(.tcw-root) ::-webkit-scrollbar-thumb:hover {\n background: var(--tcw-scroll-thumb-hover);\n background-clip: padding-box;\n border: 2.5px solid transparent;\n}\n\n/* Engines without the pseudo-elements take the standard properties. */\n@supports not selector(::-webkit-scrollbar) {\n :where(.tcw-root, .tcw-root *) {\n scrollbar-width: thin;\n scrollbar-color: var(--tcw-scroll-thumb) transparent;\n }\n}\n\n/* --- Switches: flat, no glow --- */\n\n.tcw-root .tcw-toggle.tcw-on {\n box-shadow: none;\n}\n\n.tcw-root .tcw-toggle::after {\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);\n}\n\n.tcw-root .tcw-toggle:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px var(--tcw-accent-soft);\n}\n\n/* One choice of a few in a row (a radio group): the chosen one as the look shows a chosen button. */\n.tcw-segmented {\n display: inline-flex;\n flex-wrap: wrap;\n max-width: 100%;\n gap: 2px;\n padding: 2px;\n border-radius: calc(var(--tcw-control-radius) + 2px);\n background: var(--tcw-hover-bg);\n}\n.tcw-segment {\n height: calc(var(--tcw-control-h) - 4px);\n padding-inline: var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-segment:hover { color: var(--tcw-text); }\n.tcw-segment[aria-checked='true'] {\n background: var(--tcw-on-bg);\n color: var(--tcw-on-fg);\n font-weight: var(--tcw-weight-strong);\n box-shadow: var(--tcw-on-ring);\n}\n.tcw-segment:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A number between a − and a +: one field, the figure right-aligned in the chart's mono type. */\n.tcw-stepper {\n box-sizing: border-box;\n display: inline-flex;\n align-items: stretch;\n height: var(--tcw-control-h);\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-bg);\n overflow: hidden;\n}\n.tcw-stepper:focus-within { box-shadow: var(--tcw-ring); }\n.tcw-stepper .tcw-indi-input {\n width: 110px;\n height: auto;\n padding-inline: var(--tcw-space-3);\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n text-align: end;\n -moz-appearance: textfield;\n appearance: textfield;\n}\n.tcw-stepper .tcw-indi-input::-webkit-inner-spin-button,\n.tcw-stepper .tcw-indi-input::-webkit-outer-spin-button { margin: 0; -webkit-appearance: none; }\n.tcw-stepper .tcw-indi-input:focus { outline: none; box-shadow: none; }\n.tcw-stepper-btn {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: var(--tcw-control-h);\n border: none;\n background: transparent;\n color: var(--tcw-text-dim);\n cursor: pointer;\n}\n.tcw-stepper-btn:hover { background: var(--tcw-hover-bg); color: var(--tcw-text); }\n.tcw-stepper-btn:focus-visible { outline: none; background: var(--tcw-hover-bg); color: var(--tcw-text); }\n\n/* Forced colours drop the box-shadow rings: an outline marks focus and the chosen choice. */\n@media (forced-colors: active) {\n .tcw-segment[aria-checked='true'] { outline: 2px solid Highlight; }\n .tcw-segment:focus-visible,\n .tcw-stepper-btn:focus-visible { outline: 2px solid Highlight; outline-offset: -2px; }\n .tcw-stepper:focus-within { outline: 2px solid Highlight; }\n}\n", Qt = "/* === The indicators dialog === */\n\n/* 610 wide, a Fibonacci number: the groups take 233 and the list 377 beside them (377 : 233 = phi).\n A fixed height, so the dialog keeps still while a search shortens the list. */\n.tcw-modal.tcw-ip {\n width: 610px;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n.tcw-ip-search,\n.tcw-ss-search {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n height: var(--tcw-control-h);\n margin: var(--tcw-space-4) var(--tcw-space-6);\n padding: 0 var(--tcw-space-4);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-input-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text-muted);\n transition: border-color var(--tcw-dur-fast) var(--tcw-ease), box-shadow var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ip-search:focus-within,\n.tcw-ss-search:focus-within {\n border-color: var(--tcw-accent);\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-ip-search svg,\n.tcw-ss-search svg {\n flex: none;\n}\n\n.tcw-ip-search input,\n.tcw-ss-search input {\n flex: 1;\n min-width: 0;\n height: 100%;\n border: none;\n outline: none;\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size);\n}\n\n.tcw-ip-search input::placeholder,\n.tcw-ss-search input::placeholder {\n color: var(--tcw-text-muted);\n}\n\n.tcw-ip-body {\n display: grid;\n grid-template-columns: 233px minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-ip-nav,\n.tcw-set-nav {\n display: flex;\n flex-direction: column;\n gap: 1px;\n padding: var(--tcw-space-4) var(--tcw-space-3);\n /* Logical sides: in Arabic, Hebrew or Persian the tabs sit on the right. */\n border-inline-end: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n overflow-y: auto;\n border-end-start-radius: var(--tcw-dialog-radius);\n}\n\n.tcw-ip-tab,\n.tcw-set-tab {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size);\n text-align: start;\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ip-tab svg,\n.tcw-set-tab svg {\n flex: none;\n}\n\n/* The kinds start below a gap: favourites and templates are yours, the rest the library's. */\n.tcw-ip-tab[data-view='all'] {\n margin-top: var(--tcw-space-4);\n}\n\n.tcw-ip-tab:hover,\n.tcw-set-tab:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-ip-tab.tcw-active,\n.tcw-set-tab.tcw-active {\n background: var(--tcw-on-bg);\n color: var(--tcw-on-fg);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-ip-nav--searching .tcw-ip-tab.tcw-active {\n background: transparent;\n color: var(--tcw-text-dim);\n font-weight: var(--tcw-weight);\n}\n\n.tcw-ip-list {\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0 var(--tcw-space-4) var(--tcw-space-5);\n}\n\n/* Each kind's name stays at the top while its indicators scroll under it. */\n.tcw-ip-heading {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: var(--tcw-space-5) var(--tcw-space-4) var(--tcw-space-2);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-ip-list > :first-child:not(.tcw-ip-heading) {\n margin-top: var(--tcw-space-4);\n}\n\n.tcw-ip-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-1);\n border-radius: var(--tcw-menu-item-radius);\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ip-row:hover {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ip-add {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: 1;\n min-width: 0;\n height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n font-size: var(--tcw-font-size);\n text-align: start;\n cursor: pointer;\n}\n\n.tcw-ip-add:focus-visible,\n.tcw-ip-aside:focus-visible,\n.tcw-ip-tab:focus-visible,\n.tcw-set-tab:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-ip-add svg {\n flex: none;\n color: var(--tcw-text-muted);\n}\n\n.tcw-ip-name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-ip-short {\n flex: none;\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n}\n\n/* Where it draws, quietly at the row's end. */\n.tcw-ip-kind {\n flex: none;\n margin-inline-start: auto;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n/* How many are on the chart: ink on its wash, the figures in a column. */\n.tcw-ip-count {\n flex: none;\n display: inline-grid;\n place-items: center;\n min-width: var(--tcw-space-6);\n height: var(--tcw-space-6);\n padding: 0 var(--tcw-space-2);\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-accent-soft);\n color: var(--tcw-accent);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.tcw-ip-aside {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n/* Shown on the row in hand; always for a starred one, filled in ink; always on a touch screen. */\n.tcw-ip-row:hover .tcw-ip-aside,\n.tcw-ip-row:focus-within .tcw-ip-aside,\n.tcw-ip-star[aria-pressed='true'] {\n opacity: 1;\n}\n\n@media (hover: none) {\n .tcw-ip-aside {\n opacity: 1;\n }\n}\n\n.tcw-ip-aside:hover {\n color: var(--tcw-text);\n background: var(--tcw-hover-bg);\n}\n\n.tcw-ip-star[aria-pressed='true'] {\n color: var(--tcw-accent);\n}\n\n.tcw-ip-star[aria-pressed='true'] svg path {\n fill: currentColor;\n}\n\n.tcw-ip-remove:hover {\n color: var(--tcw-red);\n}\n\n.tcw-ip-save {\n flex: none;\n width: 100%;\n color: var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-ip-save svg {\n color: currentColor;\n}\n\n.tcw-ip-save:hover {\n background: var(--tcw-accent-soft);\n}\n\n.tcw-ip-empty {\n max-width: 34ch;\n padding: var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.5;\n text-wrap: pretty;\n}\n\n/* Heard by a screen reader, not seen. */\n.tcw-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n\n/* A phone: the dialog is the widget's sheet, as tall as a sheet goes, and the groups a row of chips. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-ip {\n /* Above the on-screen keyboard: the sheet's top stays on the screen. */\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-ip-search,\n .tcw-ss-search {\n margin-inline: var(--tcw-space-4);\n }\n\n .tcw-ip-body {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .tcw-ip-nav,\n .tcw-set-nav {\n flex-direction: row;\n gap: var(--tcw-space-2);\n padding: var(--tcw-space-3) var(--tcw-space-4);\n border-inline-end: none;\n border-bottom: 1px solid var(--tcw-divider);\n border-radius: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n }\n\n .tcw-ip-tab[data-view='all'] {\n margin-top: 0;\n margin-inline-start: var(--tcw-space-4);\n }\n\n .tcw-ip-tab,\n .tcw-set-tab {\n /* A finger's size, as the dialogs' other tabs on a phone. */\n min-height: 40px;\n border: var(--tcw-border-w) solid var(--tcw-border);\n }\n\n\n .tcw-ip-list {\n padding-inline: var(--tcw-space-3);\n }\n}\n\n/* === The indicator settings, and a drawing's === */\n\n/* One half step of phi under the indicators dialog: 610 / sqrt(phi) = 480. */\n@media (min-width: 641px) {\n .tcw-modal.tcw-modal-narrow.tcw-indi,\n .tcw-modal.tcw-modal-narrow.tcw-drawing-settings {\n width: 480px;\n max-width: 92vw;\n }\n}\n\n/* A line, or a kind of interval: ticked where it shows, its name, then what sets it. */\n.tcw-indi-plot-name {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-width: 0;\n cursor: pointer;\n}\n\n.tcw-indi-plot-name .tcw-settings-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Unticked, its name steps back. */\n.tcw-indi-plot-name:has(input:not(:checked)) .tcw-settings-label {\n color: var(--tcw-text-muted);\n}\n\n.tcw-indi-plot-controls,\n.tcw-indi-range {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-3);\n flex: none;\n}\n\n/* A box ticked beside other controls in a row (bold, italics, a text box's background). */\n.tcw-inline-check {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-2);\n cursor: pointer;\n white-space: nowrap;\n}\n\n.tcw-indi-plot-controls .tcw-indi-select {\n width: 104px;\n}\n\n.tcw-indi-range {\n color: var(--tcw-text-muted);\n}\n\n.tcw-indi-range .tcw-indi-input {\n width: 68px;\n text-align: end;\n}\n\n.tcw-indi-range .tcw-indi-input:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Defaults on the left; Cancel and Ok on the right, one height for all three. */\n.tcw-indi .tcw-modal-footer,\n.tcw-set .tcw-modal-footer,\n.tcw-drawing-settings .tcw-modal-footer {\n gap: var(--tcw-space-4);\n}\n\n.tcw-footer-end {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n}\n\n.tcw-indi .tcw-modal-footer button,\n.tcw-set .tcw-modal-footer button,\n.tcw-drawing-settings .tcw-modal-footer button {\n height: var(--tcw-menu-item-h);\n padding-block: 0;\n}\n\n.tcw-footer-menu,\n.tcw-footer-cancel {\n display: inline-flex;\n align-items: center;\n gap: var(--tcw-space-2);\n padding-inline: var(--tcw-space-5);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease), border-color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-footer-cancel {\n border-color: var(--tcw-border-strong);\n color: var(--tcw-text);\n}\n\n.tcw-footer-menu:hover,\n.tcw-footer-menu[aria-expanded='true'],\n.tcw-footer-cancel:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-footer-menu:focus-visible,\n.tcw-footer-cancel:focus-visible,\n.tcw-indi .tcw-done-btn:focus-visible,\n.tcw-set .tcw-done-btn:focus-visible,\n.tcw-drawing-settings .tcw-done-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A drawing's switches: the box, then its name, a list without rules between. */\n.tcw-check-row {\n justify-content: flex-start;\n gap: var(--tcw-space-4);\n padding-block: var(--tcw-space-3);\n cursor: pointer;\n}\n\n.tcw-settings-row + .tcw-check-row,\n.tcw-check-row + .tcw-settings-row {\n border-top: 0;\n}\n\n/* A point: its name, then its price, date and time in columns; on a phone the price over the date and time. */\n.tcw-draw-point {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr);\n gap: var(--tcw-space-4);\n}\n\n.tcw-draw-point > .tcw-settings-label {\n white-space: nowrap;\n}\n\n.tcw-draw-point .tcw-indi-plot-controls {\n display: contents;\n}\n\n.tcw-draw-point input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n}\n\n.tcw-draw-point input[type='number'] {\n text-align: end;\n}\n\n@media (max-width: 640px) {\n .tcw-draw-point {\n grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);\n }\n\n .tcw-draw-point > .tcw-settings-label {\n grid-row: span 2;\n }\n\n .tcw-draw-point input[type='number'] {\n grid-column: span 2;\n }\n}\n\n.tcw-drawing-settings .tcw-indi-plot-controls input[type='number']:not(.tcw-draw-point *) {\n width: 68px;\n text-align: end;\n}\n\n/* The unit after a number (the fill's opacity in %). */\n.tcw-unit {\n margin-inline-start: calc(-1 * var(--tcw-space-2));\n color: var(--tcw-text-muted);\n}\n\n/* === The chart settings === */\n\n/* 776 x 610: half a step of phi wider than the indicators dialog (610 x sqrt(phi) = 776), as tall as it,\n so the dialog is a sqrt(phi) rectangle. The tabs take 233 down the side, as the indicator groups do. */\n.tcw-modal.tcw-set {\n width: 776px;\n max-width: 94vw;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n.tcw-set-body {\n display: grid;\n grid-template-columns: 233px minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n}\n\n.tcw-set-panel {\n min-width: 0;\n}\n\n/* A phone: the widget's sheet across the screen, the tabs a row of chips over the settings. After the rules above, which it overrides. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-set {\n width: 100vw;\n max-width: 100vw;\n /* Above the on-screen keyboard: the sheet's top stays on the screen. */\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-set-body {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n}\n\n/* === The symbol search, and the same dialog comparing === */\n\n/* As wide and as still as the indicators dialog: 610, a fixed height while a search shortens the list. */\n.tcw-modal.tcw-ss {\n width: 610px;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n/* Comparing: how the next symbol goes on the chart, under the search. */\n.tcw-ss-way {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n flex: none;\n margin: 0 var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n\n.tcw-ss-way > span {\n flex: none;\n}\n\n.tcw-root .tcw-ss-way-select {\n flex: 1;\n min-width: 0;\n height: var(--tcw-control-h);\n padding-block: 0;\n}\n\n/* The heads' height, which the rows scroll in below. */\n.tcw-modal.tcw-ss {\n --tcw-ss-head-h: var(--tcw-control-h);\n}\n\n/* Over the list: the kinds the rows come in, and their exchanges once there are two. The exchanges sit\n on the tabs' first line when the tabs wrap, not between their lines. */\n.tcw-ss-filters {\n display: flex;\n align-items: flex-start;\n gap: var(--tcw-space-4);\n flex: none;\n margin: 0 var(--tcw-space-6) var(--tcw-space-4);\n}\n\n/* The kinds as tabs (All, stock, crypto…), showing the one picked as the look shows a choice. */\n.tcw-ss-kinds {\n display: flex;\n flex-wrap: wrap;\n flex: 1;\n min-width: 0;\n gap: var(--tcw-space-2);\n}\n\n/* Where they scroll in one line, the tabs fade out at an end with more past it, so a tab cut there\n reads as more to scroll to. A mask: only its alpha counts, so what shows is drawn in the text's\n colour, which is opaque, and what fades goes to transparent. */\n.tcw-ss-kinds[data-more] {\n --tcw-ss-shown: currentColor;\n --tcw-ss-fade-start: var(--tcw-ss-shown);\n --tcw-ss-fade-end: var(--tcw-ss-shown);\n -webkit-mask-image: linear-gradient(to right, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n mask-image: linear-gradient(to right, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n}\n\n[dir='rtl'] .tcw-ss-kinds[data-more] {\n -webkit-mask-image: linear-gradient(to left, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n mask-image: linear-gradient(to left, var(--tcw-ss-fade-start), var(--tcw-ss-shown) var(--tcw-space-6), var(--tcw-ss-shown) calc(100% - var(--tcw-space-6)), var(--tcw-ss-fade-end));\n}\n\n.tcw-ss-kinds[data-more~='start'] {\n --tcw-ss-fade-start: transparent;\n}\n\n.tcw-ss-kinds[data-more~='end'] {\n --tcw-ss-fade-end: transparent;\n}\n\n.tcw-ss-type {\n flex: none;\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-5);\n border: none;\n border-radius: var(--tcw-tab-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n/* A feed's words as it wrote them (\"Cổ phiếu\" stays so), only the first letter raised. */\n.tcw-ss-type::first-letter {\n text-transform: uppercase;\n}\n\n.tcw-ss-type:hover {\n background: var(--tcw-tab-hover);\n color: var(--tcw-text);\n}\n\n.tcw-ss-type[aria-pressed='true'] {\n background: var(--tcw-tab-on-bg);\n color: var(--tcw-tab-on-fg);\n box-shadow: inset 0 calc(-1 * var(--tcw-tab-line)) 0 var(--tcw-accent);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-ss-type:focus-visible,\n.tcw-ss-remove:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* The exchanges at the end of the row, as wide as the longest up to 144. */\n.tcw-root .tcw-ss-exchange-filter {\n flex: none;\n width: auto;\n max-width: 144px;\n height: var(--tcw-control-h);\n margin-inline-start: auto;\n padding-block: 0;\n font-size: var(--tcw-font-size-sm);\n}\n\n/* What scrolls is one grid, and the heads, the list and each row are its subgrids, so a column is\n as wide in every row: the badge, the symbol up to 144 (89 x phi), the name the rest, the kind and\n the exchange up to 89 each, the check. An empty cell keeps its column. */\n.tcw-ss-results {\n display: grid;\n grid-template-columns: max-content fit-content(144px) minmax(0, 1fr) fit-content(89px) fit-content(89px) auto;\n align-content: start;\n column-gap: var(--tcw-space-4);\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n /* A row the arrows reach scrolls in below the heads, not under them. */\n scroll-padding-block-start: calc(var(--tcw-ss-head-h) + var(--tcw-space-2));\n padding: 0 var(--tcw-space-4) var(--tcw-space-5);\n}\n\n/* Comparing, under a heading of its own as well. */\n.tcw-ss--compare .tcw-ss-results {\n scroll-padding-block-start: calc(var(--tcw-ss-head-h) + var(--tcw-space-5) + var(--tcw-space-2) + var(--tcw-font-size-xs) * 1.5);\n}\n\n.tcw-ss-results > * {\n grid-column: 1 / -1;\n}\n\n.tcw-ss-columns,\n.tcw-ss-list,\n.tcw-ss-added,\n.tcw-ss-row,\n.tcw-ss-added-row {\n display: grid;\n grid-column: 1 / -1;\n /* Where subgrids aren't drawn: fixed columns, the rest sized row by row. */\n grid-template-columns: var(--tcw-control-h-sm) 89px minmax(0, 1fr) auto auto auto;\n grid-template-columns: subgrid;\n align-items: center;\n column-gap: inherit;\n}\n\n/* The heads stay at the top while the rows scroll under them. */\n.tcw-ss-columns {\n position: sticky;\n top: 0;\n z-index: 2;\n height: var(--tcw-ss-head-h);\n margin-bottom: var(--tcw-space-2);\n padding: 0 var(--tcw-space-4);\n background: var(--tcw-bg-elevated);\n box-shadow: 0 1px 0 var(--tcw-divider);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n white-space: nowrap;\n}\n\n.tcw-ss-head {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-ss-head:nth-child(1) { grid-column: 1; }\n.tcw-ss-head:nth-child(2) { grid-column: 2; }\n.tcw-ss-head:nth-child(3) { grid-column: 3; }\n.tcw-ss-head:nth-child(4) { grid-column: 4; justify-self: end; }\n.tcw-ss-head:nth-child(5) { grid-column: 5; justify-self: end; }\n\n.tcw-ss-row {\n min-height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border-radius: var(--tcw-menu-item-radius);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-ss-row.tcw-selected {\n background: var(--tcw-hover-bg);\n}\n\n/* The logo, or the ticker's first letter on a tint of its kind's colour, cornered as the look's tags. */\n.tcw-ss-badge {\n --tcw-ss-kind: var(--tcw-text-dim);\n grid-column: 1;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h-sm);\n height: var(--tcw-control-h-sm);\n overflow: hidden;\n border-radius: var(--tcw-tag-radius);\n background: color-mix(in srgb, var(--tcw-ss-kind) 16%, transparent);\n color: var(--tcw-ss-kind);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n line-height: 1;\n}\n\n.tcw-ss-badge[data-kind='1'] { --tcw-ss-kind: var(--tcw-kind-1); }\n.tcw-ss-badge[data-kind='2'] { --tcw-ss-kind: var(--tcw-kind-2); }\n.tcw-ss-badge[data-kind='3'] { --tcw-ss-kind: var(--tcw-kind-3); }\n.tcw-ss-badge[data-kind='4'] { --tcw-ss-kind: var(--tcw-kind-4); }\n.tcw-ss-badge[data-kind='5'] { --tcw-ss-kind: var(--tcw-kind-5); }\n\nimg.tcw-ss-badge {\n background: transparent;\n object-fit: cover;\n}\n\n/* The figures of a ticker, in the mono face, left to right in any widget, at the start of its column;\n the chart's own in ink. */\n.tcw-ss-symbol {\n grid-column: 2;\n display: flex;\n justify-self: start;\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text);\n font-family: var(--tcw-font-mono);\n font-weight: var(--tcw-weight-strong);\n white-space: nowrap;\n}\n\n/* A venue before the ticker (\"BINANCE:\"), dim, is what a narrow column shortens; the ticker never\n shrinks (a share of a pixel would end it in an ellipsis), and is cut only when it alone is wider.\n A gap keeps the venue's ellipsis off the ticker (\"HYPERLIQ… GOLD\"). */\n.tcw-ss-venue {\n flex: 0 1 auto;\n min-width: 0;\n margin-inline-end: var(--tcw-space-1);\n overflow: hidden;\n color: var(--tcw-text-muted);\n font-weight: var(--tcw-weight);\n text-overflow: ellipsis;\n}\n\n.tcw-ss-ticker {\n flex: none;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tcw-ss-row.tcw-current .tcw-ss-symbol {\n color: var(--tcw-accent);\n}\n\n.tcw-ss-symbol mark {\n background: transparent;\n color: var(--tcw-accent);\n}\n\n.tcw-ss-desc-cell {\n grid-column: 3;\n min-width: 0;\n}\n\n/* As wide as its words, at the start of the column, whichever way they run. */\n.tcw-ss-desc {\n display: block;\n width: fit-content;\n max-width: 100%;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-size: var(--tcw-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* The kind as the feed wrote it, and the exchange, each at the end of its column. */\n.tcw-ss-kind,\n.tcw-ss-exchange {\n justify-self: end;\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n font-size: var(--tcw-font-size-xs);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-ss-kind {\n grid-column: 4;\n color: var(--tcw-text-muted);\n}\n\n.tcw-ss-exchange {\n grid-column: 5;\n color: var(--tcw-text-dim);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n/* The chart's symbol, or one on it already: a check in the last column. */\n.tcw-ss-check {\n grid-column: 6;\n display: inline-grid;\n place-items: center;\n color: var(--tcw-accent);\n}\n\n.tcw-ss-heading[hidden] {\n display: none;\n}\n\n/* \"On the chart\" and \"Symbols\", under the heads while their rows scroll. */\n.tcw-ss-heading {\n position: sticky;\n top: var(--tcw-ss-head-h);\n z-index: 1;\n padding: var(--tcw-space-5) var(--tcw-space-4) var(--tcw-space-2);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-ss-added-row {\n min-height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border-radius: var(--tcw-menu-item-radius);\n}\n\n.tcw-ss-added-row:hover {\n background: var(--tcw-hover-bg);\n}\n\n/* How it is compared, across the name, kind and exchange; the line's colour, where it has one of its own, where the badges are. */\n.tcw-ss-way-cell {\n grid-column: 3 / 6;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-width: 0;\n}\n\n.tcw-ss-swatch {\n grid-column: 1;\n justify-self: center;\n width: var(--tcw-space-4);\n height: var(--tcw-space-4);\n border-radius: var(--tcw-radius-sm);\n}\n\n.tcw-ss-way-label {\n min-width: 0;\n overflow: hidden;\n color: var(--tcw-text-dim);\n font-size: var(--tcw-font-size-sm);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-ss-remove {\n grid-column: 6;\n display: inline-grid;\n place-items: center;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n\n.tcw-ss-remove:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-red);\n}\n\n.tcw-ss-empty {\n max-width: 44ch;\n padding: var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.5;\n text-wrap: pretty;\n}\n\n/* Under a list cut short: how many more match, for typing to narrow. */\n.tcw-ss-more {\n padding: var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.5;\n}\n\n/* The way the dialog opens too: a letter typed on the chart. */\n.tcw-ss-foot {\n flex: none;\n padding: var(--tcw-space-5) var(--tcw-space-6);\n border-top: 1px solid var(--tcw-divider);\n border-radius: 0 0 var(--tcw-dialog-radius) var(--tcw-dialog-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n text-align: center;\n}\n\n/* === Go to === */\n\n/* 377: the step of phi under the search dialogs. */\n@media (min-width: 641px) {\n .tcw-modal.tcw-goto {\n width: 377px;\n }\n}\n\n.tcw-goto-form {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n\n.tcw-goto-fields {\n display: grid;\n gap: var(--tcw-space-5);\n padding: var(--tcw-space-6) var(--tcw-space-6) var(--tcw-space-4);\n}\n\n/* The date takes the room; the time 144 beside it; a range's end named above its two. */\n.tcw-goto-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 144px;\n gap: var(--tcw-space-3) var(--tcw-space-4);\n align-items: center;\n}\n\n.tcw-goto-label {\n grid-column: 1 / -1;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-root .tcw-goto-input {\n width: 100%;\n min-width: 0;\n height: var(--tcw-control-h);\n box-sizing: border-box;\n padding: 0 var(--tcw-space-4);\n font-size: var(--tcw-font-size);\n font-variant-numeric: tabular-nums;\n}\n\n/* No time on daily bars: the date across the row. */\n.tcw-goto-input[type='date']:last-child {\n grid-column: 1 / -1;\n}\n\n/* The month under the fields, part of the dialog: no card of its own. */\n.tcw-calendar.tcw-goto-calendar {\n position: static;\n width: auto;\n padding: var(--tcw-space-4) var(--tcw-space-6) var(--tcw-space-5);\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n backdrop-filter: none;\n -webkit-backdrop-filter: none;\n animation: none;\n}\n\n.tcw-goto-calendar .tcw-calendar-day {\n height: 34px;\n}\n\n.tcw-goto .tcw-modal-footer {\n justify-content: flex-end;\n gap: var(--tcw-space-4);\n}\n\n.tcw-goto .tcw-modal-footer button {\n height: var(--tcw-menu-item-h);\n padding-block: 0;\n}\n\n.tcw-goto .tcw-done-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A phone: both are the widget's sheet; the search as tall as a sheet goes, its symbols up to 89\n wide. The kind's column goes (the badge's colour still tells it), the tabs scroll in one line, and\n a row is a finger's height. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-ss {\n /* Above the on-screen keyboard: the sheet's top stays on the screen. */\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-ss-way,\n .tcw-ss-filters {\n margin-inline: var(--tcw-space-4);\n }\n\n .tcw-ss-kinds {\n flex-wrap: nowrap;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .tcw-ss-kinds::-webkit-scrollbar {\n display: none;\n }\n\n .tcw-root .tcw-ss-exchange-filter {\n max-width: 110px;\n }\n\n /* The ticker is the row's key: its column as wide as the widest ticker, up to 144 or 38.2% of the\n row, and the name gives way first. The exchange's up to 55, each cut in its own row. */\n .tcw-ss-results {\n grid-template-columns: max-content fit-content(min(144px, 38.2%)) minmax(0, 1fr) fit-content(55px) auto;\n }\n\n /* A venue counts for nothing in that width (its own is 0): it shows, dim and shortened, in what\n its ticker leaves, if that is 2em, a letter and an ellipsis as on the toolbar. With less, it\n wraps to a second line the cell clips, never a sliver (\"H.GOLD\"). The ticker comes first in the\n line, laid from the end, so it is the one that stays, at the column's start when alone. */\n .tcw-ss-symbol {\n justify-self: stretch;\n flex-direction: row-reverse;\n flex-wrap: wrap;\n justify-content: flex-end;\n align-content: flex-start;\n height: 1lh;\n }\n\n .tcw-ss-ticker {\n order: -1;\n }\n\n .tcw-ss-venue {\n flex: 1 1 2em;\n width: 0;\n }\n\n /* The head over the exchanges reads whole, over the gap before it if it must. */\n .tcw-ss-head:nth-child(5) {\n overflow: visible;\n }\n\n .tcw-ss-columns,\n .tcw-ss-list,\n .tcw-ss-added,\n .tcw-ss-row,\n .tcw-ss-added-row {\n grid-template-columns: var(--tcw-control-h-sm) 89px minmax(0, 1fr) auto auto;\n grid-template-columns: subgrid;\n }\n\n .tcw-ss-kind,\n .tcw-ss-head:nth-child(4) {\n display: none;\n }\n\n .tcw-ss-exchange,\n .tcw-ss-head:nth-child(5) {\n grid-column: 4;\n }\n\n .tcw-ss-check,\n .tcw-ss-remove {\n grid-column: 5;\n }\n\n .tcw-ss-way-cell {\n grid-column: 3 / 5;\n }\n\n .tcw-ss-row,\n .tcw-ss-added-row {\n min-height: 44px;\n }\n}\n\n/* Without a keyboard there are no letters to type on the chart. */\n@media (hover: none) and (pointer: coarse) {\n .tcw-ss-foot {\n display: none;\n }\n}\n\n/* === The shortcut sheet === */\n\n/* As wide and as still as the indicators dialog: 610, a fixed height while a search shortens the list. */\n.tcw-modal.tcw-hotkey-sheet {\n width: 610px;\n height: min(610px, 86vh);\n height: min(610px, 86dvh);\n max-height: none;\n}\n\n.tcw-hotkey-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 0 var(--tcw-space-6) var(--tcw-space-5);\n border-top: 1px solid var(--tcw-divider);\n}\n\n/* Two columns as tall as their groups, inside the box that scrolls: on the box itself, of a fixed\n height, the groups past its foot went into columns to the side, out of reach. */\n.tcw-hotkey-columns {\n columns: 2;\n column-gap: var(--tcw-space-7);\n}\n\n/* A group keeps together in its column, its name above its rows. */\n.tcw-hotkey-group {\n break-inside: avoid;\n padding-top: var(--tcw-space-5);\n}\n\n.tcw-hotkey-heading {\n padding-bottom: var(--tcw-space-3);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n/* What it does on the left, its keys on the right, the keys in a column of their own. */\n.tcw-hotkey-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--tcw-space-4);\n min-height: calc(var(--tcw-space-6) + var(--tcw-space-3));\n padding: var(--tcw-space-2) 0;\n}\n\n.tcw-hotkey-label {\n min-width: 0;\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n line-height: 1.4;\n}\n\n.tcw-hotkey-keys {\n display: inline-flex;\n align-items: baseline;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--tcw-space-2);\n flex: none;\n max-width: 55%;\n}\n\n/* A key: its name in the mono face on a key's face. */\n.tcw-hotkey-key,\n.tcw-cp-key {\n display: inline-block;\n min-width: calc(var(--tcw-space-6) - var(--tcw-space-2));\n padding: 0 var(--tcw-space-3);\n border: var(--tcw-border-w) solid var(--tcw-border);\n border-bottom-width: 2px;\n border-radius: var(--tcw-tag-radius);\n background: var(--tcw-bg);\n color: var(--tcw-text-dim);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n line-height: 1.6;\n text-align: center;\n white-space: nowrap;\n}\n\n/* A gesture is not a key: its words, quieter. */\n.tcw-hotkey-gesture {\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n white-space: nowrap;\n}\n\n.tcw-hotkey-sep {\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n}\n\n.tcw-hotkey-empty {\n padding: var(--tcw-space-6) 0;\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n\n/* How to open it again, at its foot. */\n.tcw-hotkey-foot {\n flex: none;\n padding: var(--tcw-space-5) var(--tcw-space-6);\n border-top: 1px solid var(--tcw-divider);\n border-radius: 0 0 var(--tcw-dialog-radius) var(--tcw-dialog-radius);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n}\n\n/* === The command palette === */\n\n/* 610 wide, a third of the way down: a launcher, not a form; its search is the dialogs' search row. */\n.tcw-modal.tcw-cp {\n top: 19.1%;\n transform: translate(-50%, 0);\n width: 610px;\n max-height: min(610px, 76.4vh);\n max-height: min(610px, 76.4dvh);\n animation: none;\n}\n\n.tcw-cp .tcw-cp-search {\n margin-top: var(--tcw-space-5);\n}\n\n.tcw-cp-results {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n /* A row the arrows reach scrolls in below its group's heading, not under it. */\n scroll-padding-block-start: calc(var(--tcw-space-5) + var(--tcw-space-2) + var(--tcw-font-size-xs) * 1.5);\n padding: 0 var(--tcw-space-4) var(--tcw-space-4);\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-cp-heading {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: var(--tcw-space-5) var(--tcw-space-4) var(--tcw-space-2);\n background: var(--tcw-bg-elevated);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n\n.tcw-cp-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-4);\n min-height: var(--tcw-menu-item-h);\n padding: 0 var(--tcw-space-4);\n border-radius: var(--tcw-menu-item-radius);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size);\n cursor: pointer;\n}\n\n.tcw-cp-row.tcw-selected {\n background: var(--tcw-hover-bg);\n}\n\n.tcw-cp-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* What is on now: its name in ink, a check at the end. */\n.tcw-cp-row.tcw-on .tcw-cp-label {\n color: var(--tcw-accent);\n}\n\n.tcw-cp-check {\n display: inline-grid;\n place-items: center;\n flex: none;\n color: var(--tcw-accent);\n}\n\n.tcw-cp-empty {\n padding: var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n\n/* === Layouts === */\n\n/* 480, as the settings of an indicator: a list of names and when they were saved. On a phone, the sheet's width. */\n.tcw-modal.tcw-layouts-dialog {\n max-height: min(610px, 86vh);\n max-height: min(610px, 86dvh);\n}\n@media (min-width: 641px) {\n .tcw-modal.tcw-layouts-dialog { width: 480px; }\n}\n\n.tcw-layouts-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: var(--tcw-space-3) var(--tcw-space-4) var(--tcw-space-5);\n border-top: 1px solid var(--tcw-divider);\n}\n\n.tcw-layouts-list {\n display: flex;\n flex-direction: column;\n gap: var(--tcw-space-1);\n}\n\n.tcw-layouts-row {\n display: flex;\n align-items: center;\n gap: var(--tcw-space-2);\n padding-inline-end: var(--tcw-space-3);\n border-radius: var(--tcw-menu-item-radius);\n}\n\n.tcw-layouts-row:hover,\n.tcw-layouts-row:focus-within {\n background: var(--tcw-hover-bg);\n}\n\n/* A column for the check of the one open, so every name starts at the same place. */\n.tcw-layouts-open {\n display: grid;\n grid-template-columns: var(--tcw-space-5) minmax(0, 1fr);\n column-gap: var(--tcw-space-3);\n align-items: center;\n flex: 1;\n min-width: 0;\n padding: var(--tcw-space-3) var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-menu-item-radius);\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n.tcw-layouts-open:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n.tcw-layouts-name,\n.tcw-layouts-meta {\n grid-column: 2;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-layouts-name {\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-layouts-meta {\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.tcw-layouts-check {\n display: inline-grid;\n place-items: center;\n grid-column: 1;\n grid-row: 1 / span 2;\n color: var(--tcw-accent);\n}\n\n.tcw-layouts-open[aria-current='true'] .tcw-layouts-name {\n color: var(--tcw-accent);\n}\n\n/* Rename and delete show on the row in hand; always on a touch screen. */\n.tcw-layouts-row .tcw-account-actions {\n display: flex;\n gap: var(--tcw-space-1);\n opacity: 0;\n transition: opacity var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-layouts-row:is(:hover, :focus-within) .tcw-account-actions,\n.tcw-layouts-row .tcw-account-actions:has(.tcw-layouts-confirm) {\n opacity: 1;\n}\n\n@media (hover: none) {\n .tcw-layouts-row .tcw-account-actions {\n opacity: 1;\n }\n}\n\n.tcw-layouts-confirm {\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-4);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-red);\n /* The accent fill's ink reads on the red too: dark on the dark theme's, white on the light's. */\n color: var(--tcw-accent-ink);\n font: inherit;\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n}\n\n.tcw-layouts-confirm:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* A phone: the sheets as tall as they go, the shortcuts in one column. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-hotkey-sheet {\n height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-hotkey-body {\n padding-inline: var(--tcw-space-4);\n }\n\n .tcw-hotkey-columns {\n columns: 1;\n }\n\n /* Their own heights outrank the sheet's: give them back its height, less the keyboard, and the palette its slide up. */\n .tcw-modal.tcw-cp,\n .tcw-modal.tcw-layouts-dialog {\n max-height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n max-height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n\n .tcw-modal.tcw-cp {\n top: auto;\n transform: none;\n animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);\n }\n\n .tcw-cp .tcw-cp-search {\n margin-top: var(--tcw-space-3);\n }\n\n :is(.tcw-hotkey-search, .tcw-cp-search, .tcw-layouts-search-row) {\n margin-inline: var(--tcw-space-4);\n }\n\n .tcw-cp-row {\n min-height: 44px;\n }\n}\n\n/* === The order ticket === */\n\n/* 480, as a drawing's settings: the side, the order, its stop and target, then the receipt. On a phone, the sheet's width. */\n.tcw-modal.tcw-order-ticket {\n max-height: min(610px, 92vh);\n max-height: min(610px, 92dvh);\n}\n@media (min-width: 641px) {\n .tcw-modal.tcw-order-ticket { width: 480px; }\n}\n.tcw-order-ticket[data-side='buy'] { --tcw-side: var(--tcw-green); }\n.tcw-order-ticket[data-side='sell'] { --tcw-side: var(--tcw-red); }\n\n.tcw-ticket-heading {\n display: flex;\n align-items: baseline;\n gap: var(--tcw-space-4);\n min-width: 0;\n}\n.tcw-ticket-symbol {\n overflow: hidden;\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.tcw-ticket-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n/* Buy and Sell: the chosen one filled with its colour, the ground's own colour on it. */\n.tcw-ticket-side {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--tcw-space-3);\n margin-bottom: var(--tcw-space-4);\n}\n.tcw-ticket-side-btn {\n height: 34px;\n border: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-dim);\n font: inherit;\n font-size: var(--tcw-font-size-lg);\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n.tcw-ticket-side-btn:hover { color: var(--tcw-text); }\n.tcw-ticket-buy[aria-pressed='true'] { border-color: var(--tcw-green); background: var(--tcw-green); color: var(--tcw-bg); }\n.tcw-ticket-sell[aria-pressed='true'] { border-color: var(--tcw-red); background: var(--tcw-red); color: var(--tcw-bg); }\n.tcw-ticket-side-btn:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n\n/* A row's control goes under its name when they don't fit side by side (a long choice at 320 px). */\n.tcw-ticket-row {\n flex-wrap: wrap;\n gap: var(--tcw-space-3) var(--tcw-space-5);\n}\n.tcw-ticket-market {\n color: var(--tcw-text-dim);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n/* A stop or a target: its switch, its name with how far it is under it, then its price. */\n.tcw-ticket-optional {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--tcw-space-4);\n}\n.tcw-ticket-optional-name {\n display: flex;\n flex-direction: column;\n gap: var(--tcw-space-1);\n min-width: 0;\n}\n.tcw-ticket-away {\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n overflow-wrap: anywhere;\n /* Left to right inside, but at the name's start in either direction (the column's, not its own). */\n align-self: flex-start;\n}\n\n/* The receipt: under a torn-paper rule, each sum a label and a figure in the mono type. */\n.tcw-ticket-summary:not(:empty) {\n display: grid;\n gap: var(--tcw-space-2);\n margin: 0 var(--tcw-space-6) var(--tcw-space-4);\n padding-top: var(--tcw-space-4);\n border-top: var(--tcw-border-w) dashed var(--tcw-border-strong);\n}\n.tcw-ticket-summary-row {\n display: flex;\n justify-content: space-between;\n gap: var(--tcw-space-5);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-ticket-figure {\n color: var(--tcw-text);\n font-family: var(--tcw-font-mono);\n font-variant-numeric: tabular-nums;\n}\n.tcw-ticket-figure.tcw-ticket-up { color: var(--tcw-green); }\n.tcw-ticket-figure.tcw-ticket-down { color: var(--tcw-red); }\n\n.tcw-ticket-problems {\n padding: 0 var(--tcw-space-6) var(--tcw-space-4);\n color: var(--tcw-red);\n font-size: var(--tcw-font-size-sm);\n}\n.tcw-ticket-problems p { margin: var(--tcw-space-1) 0; }\n\n/* Cancel and Place alone, at the end, as tall as each other. */\n.tcw-order-ticket .tcw-modal-footer { justify-content: flex-end; }\n.tcw-order-ticket .tcw-modal-footer button { height: var(--tcw-menu-item-h); padding-block: 0; }\n.tcw-ticket-place {\n height: var(--tcw-menu-item-h);\n padding-inline: var(--tcw-space-6);\n border: none;\n border-radius: var(--tcw-control-radius);\n background: var(--tcw-side, var(--tcw-accent));\n color: var(--tcw-bg);\n font: inherit;\n font-size: var(--tcw-font-size);\n font-weight: var(--tcw-weight-strong);\n cursor: pointer;\n}\n.tcw-ticket-place:hover:not(:disabled) { background: color-mix(in srgb, var(--tcw-side, var(--tcw-accent)) 86%, var(--tcw-text)); }\n.tcw-ticket-place:disabled { opacity: 0.45; cursor: not-allowed; }\n.tcw-ticket-place:focus-visible { outline: none; box-shadow: var(--tcw-ring); }\n\n/* A phone: the ticket is a sheet above the keyboard, its controls a finger's size. */\n@media (max-width: 640px) {\n .tcw-modal.tcw-order-ticket {\n max-height: calc(92vh - var(--tcw-keyboard-inset, 0px));\n max-height: calc(92dvh - var(--tcw-keyboard-inset, 0px));\n }\n .tcw-stepper .tcw-indi-input { width: 96px; }\n .tcw-stepper-btn, .tcw-segment { min-width: 34px; }\n .tcw-segment { height: 34px; }\n .tcw-stepper { height: 38px; }\n}\n\n/* Forced colours drop the box-shadow rings: an outline marks focus and the chosen side. */\n@media (forced-colors: active) {\n .tcw-ticket-side-btn[aria-pressed='true'] { outline: 2px solid Highlight; }\n .tcw-ticket-place { border: 1px solid ButtonText; }\n .tcw-ticket-side-btn:focus-visible,\n .tcw-ticket-place:focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }\n}\n", $t = "/* === The dock: the panels by the chart, and their rail === */\n\n/* In the body's row after the chart: the panel of the page open beside the chart, the rail at the outer edge\n (both mirror in a right-to-left widget). */\n.tcw-dock {\n position: relative;\n display: flex;\n flex: none;\n min-height: 0;\n}\n\n/* The rail: as wide as the drawing tools on the other side, its buttons as theirs. */\n.tcw-dock-rail {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--tcw-space-2);\n width: var(--tcw-sidebar-w);\n padding: var(--tcw-space-3) 0;\n border-inline-start: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n}\n\n.tcw-dock-btn {\n display: inline-grid;\n place-items: center;\n flex: none;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n transition: background var(--tcw-dur-fast) var(--tcw-ease), color var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-dock-btn svg {\n width: var(--tcw-icon);\n height: var(--tcw-icon);\n}\n\n.tcw-dock-btn:hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n/* The page open: in ink on its wash, as a tool in use on the other side. */\n.tcw-dock-btn[aria-pressed='true'] {\n background: var(--tcw-on-icon-bg, var(--tcw-accent-soft));\n color: var(--tcw-on-icon-fg, var(--tcw-accent));\n}\n\n.tcw-dock-btn:focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* The edge in focus shows as its line, in ink: a ring round a strip this thin reads as two lines. */\n.tcw-dock-resize:focus-visible {\n outline: none;\n}\n\n@media (forced-colors: active) {\n .tcw-dock-resize:is(:hover, :active, :focus-visible)::after {\n background: Highlight;\n }\n}\n\n/* The panel: 296 wide to start (377 / sqrt(phi)), from 233 to 377. */\n.tcw-dock-panel {\n position: relative;\n display: flex;\n flex-direction: column;\n width: var(--tcw-dock-w, 296px);\n min-height: 0;\n border-inline-start: var(--tcw-border-w) solid var(--tcw-border);\n background: var(--tcw-bg-surface);\n}\n\n/* Its edge by the chart: a strip to drag, a line in ink while in hand. */\n.tcw-dock-resize {\n position: absolute;\n inset-block: 0;\n inset-inline-start: calc(var(--tcw-space-3) * -1);\n z-index: 3;\n width: calc(var(--tcw-space-3) * 2);\n cursor: col-resize;\n touch-action: none;\n}\n\n.tcw-dock-resize::after {\n content: '';\n position: absolute;\n inset-block: 0;\n inset-inline-start: calc(var(--tcw-space-3) - 1px);\n width: 2px;\n background: transparent;\n transition: background var(--tcw-dur-fast) var(--tcw-ease);\n}\n\n.tcw-dock-resize:hover::after,\n.tcw-dock-resize:active::after,\n.tcw-dock-resize:focus-visible::after {\n background: var(--tcw-accent);\n}\n\n/* A page's header: 34 tall (21 + 13), or a control's height where that is more, and the rule under\n it. Its height and the page's scroll padding are both these, so they never part. */\n.tcw-dock-page {\n --tcw-dock-head-h: max(calc(var(--tcw-space-6) + var(--tcw-space-5)), var(--tcw-control-h));\n --tcw-dock-head-rule: 1px;\n}\n\n/* A page fills the panel and scrolls under its header; the floating panels it was lose their card. */\n.tcw-dock-panel > .tcw-dock-page {\n position: static;\n inset: auto;\n display: flex;\n flex-direction: column;\n flex: 1;\n width: auto;\n max-width: none;\n max-height: none;\n min-height: 0;\n margin: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n /* A row the keyboard moves to scrolls in below the header and its rule, not under them. */\n scroll-padding-block-start: calc(var(--tcw-dock-head-h) + var(--tcw-dock-head-rule));\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n animation: none;\n}\n\n/* One header for every page: its title, its own buttons, and the close at the end. */\n.tcw-dock-page > :is(.tcw-watchlist-header, .tcw-alerts-header, .tcw-tree-header, .tcw-datawin-header, .tcw-syminfo-header, .tcw-ladder-header) {\n position: sticky;\n top: 0;\n z-index: 2;\n display: flex;\n align-items: center;\n gap: var(--tcw-space-2);\n flex: none;\n min-height: var(--tcw-dock-head-h);\n margin: 0;\n padding-block: 0;\n padding-inline: var(--tcw-space-5) var(--tcw-space-3);\n border-bottom: var(--tcw-dock-head-rule) solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n}\n\n.tcw-dock-page > :is(.tcw-alerts-header, .tcw-tree-header, .tcw-datawin-header, .tcw-syminfo-header) > span:first-child {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tcw-dock-page :is(.tcw-watchlist-add, .tcw-watchlist-close, .tcw-alerts-close, .tcw-tree-close, .tcw-datawin-close, .tcw-syminfo-close, .tcw-ladder-close) {\n display: inline-grid;\n place-items: center;\n flex: none;\n width: var(--tcw-control-h);\n height: var(--tcw-control-h);\n padding: 0;\n border: none;\n border-radius: var(--tcw-control-radius);\n background: transparent;\n color: var(--tcw-text-muted);\n cursor: pointer;\n}\n\n.tcw-dock-page :is(.tcw-watchlist-add, .tcw-watchlist-close, .tcw-alerts-close, .tcw-tree-close, .tcw-datawin-close, .tcw-syminfo-close, .tcw-ladder-close):hover {\n background: var(--tcw-hover-bg);\n color: var(--tcw-text);\n}\n\n.tcw-dock-page :is(.tcw-watchlist-add, .tcw-watchlist-close, .tcw-alerts-close, .tcw-tree-close, .tcw-datawin-close, .tcw-syminfo-close, .tcw-ladder-close):focus-visible {\n outline: none;\n box-shadow: var(--tcw-ring);\n}\n\n/* What scrolled in a box of its own on a floating panel scrolls with the page here (a phone's caps too). */\n.tcw-dock-page :is(.tcw-alerts-list, .tcw-datawin-body, .tcw-watchlist-list, .tcw-tree-list) {\n max-height: none;\n overflow-y: visible;\n}\n\n.tcw-dock-page .tcw-watchlist-list {\n flex: 1;\n}\n\n/* The watchlist was a bar of its own: its width and shadow are the panel's now. It scrolls as a page\n (no overflow of its own here: this rule, as specific as the page's and later, would win). */\n.tcw-dock-panel > .tcw-watchlist {\n width: auto;\n border-inline-start: none;\n box-shadow: none;\n}\n\n/* The symbol info's own padding sits under the header. */\n.tcw-dock-page.tcw-syminfo > .tcw-syminfo-body {\n padding: var(--tcw-space-5);\n}\n\n/* Narrow (a phone, a narrow column): no rail; the panel rises from the bottom over the chart, 61.8% tall. */\n.tcw-root[data-tcw-narrow] .tcw-dock-rail,\n.tcw-root[data-tcw-narrow] .tcw-dock-resize {\n display: none;\n}\n\n.tcw-root[data-tcw-narrow] .tcw-dock {\n position: static;\n}\n\n/* Above the chart's lines and tags, under its toasts; above the on-screen keyboard. */\n.tcw-root[data-tcw-narrow] .tcw-dock-panel {\n position: absolute;\n inset-inline: 0;\n bottom: var(--tcw-keyboard-inset, 0px);\n z-index: 38;\n width: auto;\n height: 61.8%;\n max-height: calc(100% - var(--tcw-keyboard-inset, 0px));\n border-inline-start: none;\n border-top: var(--tcw-border-w) solid var(--tcw-border-strong);\n border-radius: var(--tcw-dialog-radius) var(--tcw-dialog-radius) 0 0;\n background: var(--tcw-bg-elevated);\n box-shadow: var(--tcw-dialog-shadow);\n padding-bottom: env(safe-area-inset-bottom, 0px);\n}\n\n.tcw-root[data-tcw-narrow] .tcw-dock-page > :is(.tcw-watchlist-header, .tcw-alerts-header, .tcw-tree-header, .tcw-datawin-header, .tcw-syminfo-header, .tcw-ladder-header) {\n background: var(--tcw-bg-elevated);\n}\n\n/* The small buttons in a panel's rows: the browser's padding left their icons 8 px wide in a 20 px button. */\n:is(.tcw-tree-btn, .tcw-tree-add, .tcw-alerts-del, .tcw-watchlist-remove) {\n padding: 0;\n}\n\n:is(.tcw-tree-btn, .tcw-tree-add, .tcw-alerts-del, .tcw-watchlist-remove) svg {\n flex: none;\n}\n\n/* A page's title as the others': the watchlist's is its list's name, a menu. */\n.tcw-dock-page .tcw-watchlist-name {\n height: var(--tcw-control-h);\n padding: 0 var(--tcw-space-3);\n margin-inline-start: calc(var(--tcw-space-3) * -1);\n color: var(--tcw-text);\n font-size: var(--tcw-font-size-sm);\n font-weight: var(--tcw-weight-strong);\n text-transform: none;\n letter-spacing: normal;\n flex: 0 1 auto;\n}\n\n/* Its caret beside the name, the add and close buttons at the end. */\n.tcw-dock-page .tcw-watchlist-name::after {\n margin-inline-start: var(--tcw-space-3);\n}\n\n.tcw-dock-page .tcw-watchlist-add {\n margin-inline-start: auto;\n}\n\n/* === The depth ladder, a page of the dock === */\n\n.tcw-ladder-title {\n flex: 1;\n min-width: 0;\n margin: 0;\n overflow: hidden;\n font: inherit;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n/*\n * Bid, price, ask: under the header, in the label case. The heading and each\n * row are grids of their own, so their columns are fixed shares: a row's\n * content (a mark of your orders) never moves its column off the others'.\n */\n.tcw-ladder-cols,\n.tcw-ladder-row {\n --tcw-ladder-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr);\n}\n.tcw-ladder-cols {\n position: sticky;\n top: calc(var(--tcw-space-6) + var(--tcw-space-5));\n z-index: 1;\n display: grid;\n grid-template-columns: var(--tcw-ladder-columns);\n align-items: center;\n height: var(--tcw-space-6);\n padding-inline: var(--tcw-space-3);\n border-bottom: 1px solid var(--tcw-divider);\n background: var(--tcw-bg-surface);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n text-transform: var(--tcw-label-case);\n letter-spacing: var(--tcw-label-tracking);\n}\n.tcw-ladder-cols span:first-child { text-align: end; padding-inline-end: var(--tcw-space-4); }\n.tcw-ladder-cols span:nth-child(2) { text-align: center; }\n.tcw-ladder-cols span:last-child { padding-inline-start: var(--tcw-space-4); }\n\n.tcw-ladder-body { flex: 1; padding-inline: var(--tcw-space-3); }\n\n/* A row 21 tall: the bid's size, the price, the ask's size, in the mono figures. */\n.tcw-ladder-row {\n display: grid;\n grid-template-columns: var(--tcw-ladder-columns);\n height: var(--tcw-space-6);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-sm);\n font-variant-numeric: tabular-nums;\n}\n/* A side's size over a bar grown from the price outward, as long as its share of the largest. */\n.tcw-ladder-cell {\n position: relative;\n isolation: isolate;\n display: flex;\n align-items: center;\n min-width: 0;\n padding-inline: var(--tcw-space-4);\n border: none;\n background: transparent;\n color: var(--tcw-text);\n font: inherit;\n cursor: pointer;\n}\n.tcw-ladder-cell::before {\n content: '';\n position: absolute;\n inset-block: 2px;\n z-index: -1;\n width: var(--w, 0%);\n border-radius: 1px;\n}\n.tcw-ladder-bid { justify-content: flex-end; }\n.tcw-ladder-bid::before { inset-inline-end: 0; background: var(--tcw-green-soft); }\n.tcw-ladder-ask { justify-content: flex-start; }\n.tcw-ladder-ask::before { inset-inline-start: 0; background: var(--tcw-red-soft); }\n.tcw-ladder-cell:not(:disabled):hover { background: var(--tcw-hover-bg); }\n.tcw-ladder-cell:disabled { cursor: default; }\n.tcw-ladder-cell:focus-visible { outline: none; box-shadow: inset var(--tcw-ring); }\n.tcw-ladder-price {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--tcw-space-2);\n min-width: 0;\n overflow: hidden;\n padding-inline: var(--tcw-space-3);\n border-inline: 1px solid var(--tcw-divider);\n white-space: nowrap;\n}\n.tcw-ladder-price.tcw-ask { color: var(--tcw-red); }\n.tcw-ladder-price.tcw-bid { color: var(--tcw-green); }\n/* Your orders at a price: their quantity, stamped in the side's colour. */\n.tcw-ladder-own {\n flex: none;\n padding-inline: var(--tcw-space-2);\n border-radius: 2px;\n color: var(--tcw-bg);\n font-size: var(--tcw-font-size-xs);\n font-weight: var(--tcw-weight-strong);\n}\n.tcw-ladder-own[data-side='buy'] { background: var(--tcw-green); }\n.tcw-ladder-own[data-side='sell'] { background: var(--tcw-red); }\n/* The spread, between the asks and the bids, on a torn-paper rule. */\n.tcw-ladder-spread {\n display: flex;\n align-items: center;\n justify-content: center;\n height: var(--tcw-space-6);\n border-block: 1px dashed var(--tcw-border-strong);\n color: var(--tcw-text-muted);\n font-family: var(--tcw-font-mono);\n font-size: var(--tcw-font-size-xs);\n font-variant-numeric: tabular-nums;\n}\n.tcw-ladder-empty {\n padding: var(--tcw-space-6);\n color: var(--tcw-text-muted);\n font-size: var(--tcw-font-size-sm);\n text-align: center;\n}\n\n/* Narrow (a finger, not a pointer): rows a control tall, 26 not 21. */\n.tcw-root[data-tcw-narrow] .tcw-ladder-row {\n height: var(--tcw-control-h);\n}\n\n/* Forced colours drop the bars' and the marks' fills: the bars show in the system's highlight, the marks framed. */\n@media (forced-colors: active) {\n .tcw-ladder-cell::before { forced-color-adjust: none; background: Highlight; opacity: 0.3; }\n .tcw-ladder-cell:focus-visible { outline: 2px solid Highlight; outline-offset: -2px; }\n .tcw-ladder-own { border: 1px solid CanvasText; }\n}\n", en = /* @__PURE__ */ "toolbar,sidebar,statusBar,dock,alerts,objectTree,symbolInfo,symbolSearch,settings,indicatorSettings,drawingSettings,dataWindow,commandPalette,hotkeySheet,goToDate,replay,screenshot,copyImage,shareView,autoFib,themeToggle,fullscreen,accountPanel,orderTicket,bracketOrders,depthLadder,layouts,indicatorTemplates,compare,indicatorLegend,navigation,customTimeframes,intervalTyping,symbolTyping,dragDropImport,hotkeys,toasts,toolbar.symbol,toolbar.symbolInfo,toolbar.timeframes,toolbar.timeframeMenu,toolbar.chartType,toolbar.indicators,toolbar.layouts,toolbar.replay,toolbar.bracketOrders,toolbar.depthLadder,toolbar.accountPanel,toolbar.objectTree,toolbar.alerts,toolbar.screenshot,toolbar.settings,toolbar.themeToggle,toolbar.fullscreen,toolbar.compare,toolbar.undo,toolbar.redo,toolbar.trade,sidebar.cursor,sidebar.favorites,sidebar.lines,sidebar.fibonacci,sidebar.patterns,sidebar.forecasting,sidebar.annotation,sidebar.style,sidebar.magnet,sidebar.eraser,sidebar.zoomArea,sidebar.stayInDrawing,sidebar.undo,sidebar.redo,sidebar.clear,sidebar.lockAll,sidebar.hideAll,dock.watchlist,dock.alerts,dock.objectTree,dock.dataWindow,dock.symbolInfo,dock.depthLadder,statusBar.range,statusBar.goToDate,statusBar.market,statusBar.connection,statusBar.symbol,statusBar.clock,statusBar.scale,statusBar.rangeTimeframe,indicatorLegend.values,indicatorLegend.visibility,indicatorLegend.settings,indicatorLegend.remove,indicatorLegend.more,pane.move,pane.collapse,pane.maximize,navigation.zoom,navigation.scroll,navigation.reset,menu.chart,menu.chart.alert,menu.chart.order,menu.chart.orderTicket,menu.chart.horizontalLine,menu.chart.resetView,menu.chart.drawings,menu.chart.exportData,menu.chart.settings,menu.chart.scale,menu.chart.goToDate,menu.chart.paneScale,menu.priceAxisAdd,menu.chart.indicators,menu.chart.timezone,menu.drawing,menu.drawing.settings,menu.drawing.alert,menu.drawing.order,menu.drawing.group,menu.drawing.lock,menu.drawing.hide,menu.drawing.duplicate,menu.drawing.delete,selectionToolbar,hotkeys.commandPalette,hotkeys.symbolSearch,hotkeys.save,hotkeys.tools,hotkeys.invertScale,hotkeys.goToDate,hotkeys.help,hotkeys.resetView".split(","), tn = new Set(en), nn = {
|
|
1229
1229
|
toolbar: ["toolbar"],
|
|
1230
1230
|
drawingTools: [
|
|
1231
1231
|
"sidebar",
|
|
@@ -1251,7 +1251,7 @@ var Jt = [...new Set([
|
|
|
1251
1251
|
navigation: ["navigation"],
|
|
1252
1252
|
dragDropImport: ["dragDropImport"],
|
|
1253
1253
|
customTimeframes: ["customTimeframes"]
|
|
1254
|
-
},
|
|
1254
|
+
}, rn = {
|
|
1255
1255
|
alert: ["alerts", "menu.chart.alert"],
|
|
1256
1256
|
buyLimit: ["menu.chart.order"],
|
|
1257
1257
|
buyStop: ["menu.chart.order"],
|
|
@@ -1287,7 +1287,7 @@ var Jt = [...new Set([
|
|
|
1287
1287
|
paneLog: ["menu.chart.paneScale"],
|
|
1288
1288
|
paneInvert: ["menu.chart.paneScale"],
|
|
1289
1289
|
panePercent: ["menu.chart.paneScale"]
|
|
1290
|
-
},
|
|
1290
|
+
}, an = {
|
|
1291
1291
|
settings: ["drawingSettings", "menu.drawing.settings"],
|
|
1292
1292
|
alert: ["alerts", "menu.drawing.alert"],
|
|
1293
1293
|
front: ["menu.drawing.order"],
|
|
@@ -1301,7 +1301,7 @@ var Jt = [...new Set([
|
|
|
1301
1301
|
hide: ["menu.drawing.hide"],
|
|
1302
1302
|
duplicate: ["menu.drawing.duplicate"],
|
|
1303
1303
|
delete: ["menu.drawing.delete"]
|
|
1304
|
-
},
|
|
1304
|
+
}, on = {
|
|
1305
1305
|
symbolSearch: "symbolSearch",
|
|
1306
1306
|
compare: "compare",
|
|
1307
1307
|
goToDate: "goToDate",
|
|
@@ -1318,24 +1318,24 @@ var Jt = [...new Set([
|
|
|
1318
1318
|
dataWindow: "dataWindow",
|
|
1319
1319
|
symbolInfo: "symbolInfo"
|
|
1320
1320
|
};
|
|
1321
|
-
function
|
|
1321
|
+
function sn(e) {
|
|
1322
1322
|
if (typeof e != "object" || !e || Array.isArray(e)) return {};
|
|
1323
1323
|
let t = {}, n = [];
|
|
1324
|
-
for (let [r, i] of Object.entries(e))
|
|
1324
|
+
for (let [r, i] of Object.entries(e)) tn.has(r) && typeof i == "boolean" ? t[r] = i : n.push(r);
|
|
1325
1325
|
return n.length > 0 && console.warn(`[ChartWidget] Unknown or non-boolean feature switches left out: ${n.join(", ")}.`), t;
|
|
1326
1326
|
}
|
|
1327
|
-
function
|
|
1328
|
-
let t = Object.fromEntries(
|
|
1329
|
-
for (let [n, r] of Object.entries(
|
|
1327
|
+
function cn(e) {
|
|
1328
|
+
let t = Object.fromEntries(en.map((e) => [e, !0]));
|
|
1329
|
+
for (let [n, r] of Object.entries(nn)) if (e[n] === !1) for (let e of r) t[e] = !1;
|
|
1330
1330
|
return {
|
|
1331
1331
|
...t,
|
|
1332
|
-
...
|
|
1332
|
+
...sn(e.features)
|
|
1333
1333
|
};
|
|
1334
1334
|
}
|
|
1335
|
-
function
|
|
1336
|
-
return
|
|
1335
|
+
function ln(e) {
|
|
1336
|
+
return en.filter((t) => !e[t]).join(" ");
|
|
1337
1337
|
}
|
|
1338
|
-
var
|
|
1338
|
+
var un = "tcw-divider-off", dn = [
|
|
1339
1339
|
{
|
|
1340
1340
|
names: [
|
|
1341
1341
|
"navigation.zoom",
|
|
@@ -1362,39 +1362,39 @@ var ln = "tcw-divider-off", un = [
|
|
|
1362
1362
|
selector: ".tcw-ind-legend-actions"
|
|
1363
1363
|
}
|
|
1364
1364
|
];
|
|
1365
|
-
function
|
|
1365
|
+
function fn() {
|
|
1366
1366
|
return [
|
|
1367
|
-
|
|
1368
|
-
...
|
|
1369
|
-
`.${
|
|
1367
|
+
...en.map((e) => `.tcw-root[data-tcw-off~="${e}"] [data-tcw-part~="${e}"]{display:none!important}`),
|
|
1368
|
+
...dn.map(({ names: e, selector: t }) => `.tcw-root${e.map((e) => `[data-tcw-off~="${e}"]`).join("")} ${t}{display:none!important}`),
|
|
1369
|
+
`.${un}{display:none!important}`
|
|
1370
1370
|
].join("\n");
|
|
1371
1371
|
}
|
|
1372
1372
|
function O(e, ...t) {
|
|
1373
1373
|
e.dataset.tcwPart = t.join(" ");
|
|
1374
1374
|
}
|
|
1375
|
-
function
|
|
1375
|
+
function pn(...e) {
|
|
1376
1376
|
return `data-tcw-part="${e.join(" ")}"`;
|
|
1377
1377
|
}
|
|
1378
|
-
function
|
|
1379
|
-
return Object.prototype.hasOwnProperty.call(
|
|
1378
|
+
function mn(e) {
|
|
1379
|
+
return Object.prototype.hasOwnProperty.call(on, e) ? on[e] : void 0;
|
|
1380
1380
|
}
|
|
1381
|
-
function
|
|
1381
|
+
function hn(e, t, n) {
|
|
1382
1382
|
let r = [...e.children], i = (e) => e.classList.contains(t);
|
|
1383
|
-
for (let e of r) i(e) && e.classList.remove(
|
|
1383
|
+
for (let e of r) i(e) && e.classList.remove(un);
|
|
1384
1384
|
let a = (e) => !e.hidden && getComputedStyle(e).display !== "none", o = (e) => a(e) && (e instanceof HTMLButtonElement || e.childElementCount > 0 || e.textContent !== ""), s = !1, c = null;
|
|
1385
|
-
for (let e of r) if (n !== void 0 && e.classList.contains(n)) c?.classList.add(
|
|
1385
|
+
for (let e of r) if (n !== void 0 && e.classList.contains(n)) c?.classList.add(un), c = null, s = !1;
|
|
1386
1386
|
else if (i(e)) {
|
|
1387
1387
|
if (!a(e)) continue;
|
|
1388
|
-
s ? (c = e, s = !1) : e.classList.add(
|
|
1388
|
+
s ? (c = e, s = !1) : e.classList.add(un);
|
|
1389
1389
|
} else o(e) && (s = !0, c = null);
|
|
1390
|
-
c?.classList.add(
|
|
1390
|
+
c?.classList.add(un);
|
|
1391
1391
|
}
|
|
1392
|
-
function
|
|
1392
|
+
function gn(e, t, n) {
|
|
1393
1393
|
let r = e.flatMap((e) => {
|
|
1394
1394
|
if (e === "separator") return [e];
|
|
1395
1395
|
if (!(t[e.id] ?? []).every((e) => n[e])) return [];
|
|
1396
1396
|
if (!e.submenu) return [e];
|
|
1397
|
-
let r =
|
|
1397
|
+
let r = gn(e.submenu, t, n);
|
|
1398
1398
|
return r.length > 0 ? [{
|
|
1399
1399
|
...e,
|
|
1400
1400
|
submenu: r
|
|
@@ -1408,33 +1408,33 @@ function hn(e, t, n) {
|
|
|
1408
1408
|
}
|
|
1409
1409
|
//#endregion
|
|
1410
1410
|
//#region src/widget/WidgetStyles.ts
|
|
1411
|
-
var
|
|
1412
|
-
function
|
|
1413
|
-
if (
|
|
1411
|
+
var _n = 0, vn = "tcw-styles";
|
|
1412
|
+
function yn() {
|
|
1413
|
+
if (_n++, _n > 1 || document.getElementById(vn)) return;
|
|
1414
1414
|
let e = document.createElement("style");
|
|
1415
|
-
e.id =
|
|
1416
|
-
${Xt}
|
|
1415
|
+
e.id = vn, e.textContent = `${Xt}
|
|
1417
1416
|
${Zt}
|
|
1418
1417
|
${Qt}
|
|
1419
|
-
${
|
|
1418
|
+
${$t}
|
|
1419
|
+
${fn()}`, document.head.insertBefore(e, document.head.firstChild);
|
|
1420
1420
|
}
|
|
1421
|
-
function
|
|
1422
|
-
if (
|
|
1423
|
-
let e = document.getElementById(
|
|
1421
|
+
function bn() {
|
|
1422
|
+
if (_n--, _n > 0) return;
|
|
1423
|
+
let e = document.getElementById(vn);
|
|
1424
1424
|
e && e.remove();
|
|
1425
1425
|
}
|
|
1426
1426
|
//#endregion
|
|
1427
1427
|
//#region src/widget/icons.ts
|
|
1428
|
-
var
|
|
1428
|
+
var xn = (e, t) => Object.prototype.hasOwnProperty.call(e, t) ? e[t] : void 0;
|
|
1429
1429
|
function k(e, t = 14) {
|
|
1430
|
-
let n =
|
|
1430
|
+
let n = xn(oe, e);
|
|
1431
1431
|
return n ? ue(n, t) : "";
|
|
1432
1432
|
}
|
|
1433
|
-
function
|
|
1434
|
-
return ue(
|
|
1433
|
+
function Sn(e, t = 16) {
|
|
1434
|
+
return ue(xn(te, e) ?? oe.penLine, t);
|
|
1435
1435
|
}
|
|
1436
|
-
function
|
|
1437
|
-
return ue(
|
|
1436
|
+
function Cn(e, t = 14) {
|
|
1437
|
+
return ue(xn(v, e) ?? oe.barChart, t);
|
|
1438
1438
|
}
|
|
1439
1439
|
//#endregion
|
|
1440
1440
|
//#region src/widget/escapeHtml.ts
|
|
@@ -1449,7 +1449,7 @@ function A(e) {
|
|
|
1449
1449
|
}
|
|
1450
1450
|
//#endregion
|
|
1451
1451
|
//#region src/widget/WidgetDropdown.ts
|
|
1452
|
-
var
|
|
1452
|
+
var wn = class {
|
|
1453
1453
|
trigger;
|
|
1454
1454
|
panel;
|
|
1455
1455
|
_isOpen = !1;
|
|
@@ -1497,17 +1497,17 @@ var Cn = class {
|
|
|
1497
1497
|
this.close(), this.trigger.removeEventListener("click", this.onTriggerClick), this.panel.remove();
|
|
1498
1498
|
}
|
|
1499
1499
|
place() {
|
|
1500
|
-
|
|
1500
|
+
pt(this.panel, this.trigger, this.align);
|
|
1501
1501
|
}
|
|
1502
|
-
},
|
|
1503
|
-
function
|
|
1502
|
+
}, Tn = 4, En = 2, Dn = 150, On = "[role=menuitem], [role=menuitemcheckbox], [role=menuitemradio]", kn = "(max-width: 640px)", An = "tcw:back", jn = /* @__PURE__ */ new Set();
|
|
1503
|
+
function Mn(e, t, n, r = e, i = !1) {
|
|
1504
1504
|
let a = i ? r - t >= 0 ? r - t : e : e + t > n ? r - t : e;
|
|
1505
1505
|
return Math.max(0, Math.min(a, n - t));
|
|
1506
1506
|
}
|
|
1507
|
-
function
|
|
1507
|
+
function Nn(e) {
|
|
1508
1508
|
return e.radio ? "menuitemradio" : e.checked === void 0 ? "menuitem" : "menuitemcheckbox";
|
|
1509
1509
|
}
|
|
1510
|
-
function
|
|
1510
|
+
function Pn(e) {
|
|
1511
1511
|
let t = "<span class=\"tcw-context-icon\"></span>";
|
|
1512
1512
|
return e.radio ? e.checked ? "<span class=\"tcw-context-icon tcw-context-dot\"></span>" : t : e.checked ? k("check", 14) : e.icon && k(e.icon, 14) || t;
|
|
1513
1513
|
}
|
|
@@ -1541,12 +1541,12 @@ var j = class e {
|
|
|
1541
1541
|
before: s
|
|
1542
1542
|
}, r, i, a, !0);
|
|
1543
1543
|
}
|
|
1544
|
-
openUnder(e, t, n, r = "start", i =
|
|
1544
|
+
openUnder(e, t, n, r = "start", i = En) {
|
|
1545
1545
|
let a = t.getBoundingClientRect(), o = this.host.getBoundingClientRect(), s = r === "end" !== this.rtl();
|
|
1546
1546
|
this.open(e, a.left - o.left, a.bottom - o.top + i, n, t, void 0, a.right - o.left, s);
|
|
1547
1547
|
}
|
|
1548
1548
|
openBeside(e, t, n) {
|
|
1549
|
-
let r = t.getBoundingClientRect(), i = this.host.getBoundingClientRect(), a = r.right - i.left +
|
|
1549
|
+
let r = t.getBoundingClientRect(), i = this.host.getBoundingClientRect(), a = r.right - i.left + En, o = r.left - i.left - En;
|
|
1550
1550
|
this.show(e, {
|
|
1551
1551
|
x: a,
|
|
1552
1552
|
y: r.top - i.top,
|
|
@@ -1556,16 +1556,16 @@ var j = class e {
|
|
|
1556
1556
|
}, n, t, void 0, !0), this.returnFocus = t;
|
|
1557
1557
|
}
|
|
1558
1558
|
static closeAnchoredTo(e) {
|
|
1559
|
-
let t = [...
|
|
1559
|
+
let t = [...jn].filter((t) => t.anchor === e);
|
|
1560
1560
|
for (let e of t) e.close();
|
|
1561
1561
|
return t.length > 0;
|
|
1562
1562
|
}
|
|
1563
1563
|
static focusedAnchor() {
|
|
1564
|
-
return [...
|
|
1564
|
+
return [...jn].find((e) => e.anchor !== null && e.hasFocus())?.anchor ?? null;
|
|
1565
1565
|
}
|
|
1566
1566
|
close() {
|
|
1567
1567
|
if (this.clearHover(), this.child?.close(), this.el.hidden) return;
|
|
1568
|
-
|
|
1568
|
+
jn.delete(this);
|
|
1569
1569
|
let e = !this.parent || this.el.contains(document.activeElement);
|
|
1570
1570
|
this.el.hidden = !0, this.onPick = null, this.onRemove = null, this.anchor?.setAttribute("aria-expanded", "false"), this.anchor = null, document.removeEventListener("pointerdown", this.onDocPointer, !0), document.removeEventListener("wheel", this.onWheel, { capture: !0 }), window.removeEventListener("resize", this.onAway), window.removeEventListener("blur", this.onAway), e && this.returnFocus?.isConnected && this.returnFocus.focus({ preventScroll: !0 }), this.returnFocus = null;
|
|
1571
1571
|
}
|
|
@@ -1579,9 +1579,9 @@ var j = class e {
|
|
|
1579
1579
|
this.close(), this.child?.destroy(), this.el.remove();
|
|
1580
1580
|
}
|
|
1581
1581
|
show(e, t, n, r, i, a) {
|
|
1582
|
-
this.clearHover(), this.child?.close(), this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null, this.onPick = n, this.onRemove = i ?? null, this.anchor = r ?? null, this.anchor?.setAttribute("aria-expanded", "true"), this.el.replaceChildren(...e.map((e) => this.entry(e))), this.el.hidden = !1,
|
|
1583
|
-
let o = this.host.getBoundingClientRect(), s = Math.min(this.host.clientWidth, window.innerWidth - o.left) -
|
|
1584
|
-
this.el.style.maxHeight = `${Math.max(0, c - this.frameHeight())}px`, this.el.style.left = `${
|
|
1582
|
+
this.clearHover(), this.child?.close(), this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null, this.onPick = n, this.onRemove = i ?? null, this.anchor = r ?? null, this.anchor?.setAttribute("aria-expanded", "true"), this.el.replaceChildren(...e.map((e) => this.entry(e))), this.el.hidden = !1, jn.add(this);
|
|
1583
|
+
let o = this.host.getBoundingClientRect(), s = Math.min(this.host.clientWidth, window.innerWidth - o.left) - Tn, c = Math.min(this.host.clientHeight, window.innerHeight - o.top) - Tn;
|
|
1584
|
+
this.el.style.maxHeight = `${Math.max(0, c - this.frameHeight())}px`, this.el.style.left = `${Mn(t.x, this.el.offsetWidth, s, t.xBack, t.before)}px`, this.el.style.top = `${Mn(t.y, this.el.offsetHeight, c, t.yBack)}px`, document.addEventListener("pointerdown", this.onDocPointer, !0), document.addEventListener("wheel", this.onWheel, {
|
|
1585
1585
|
capture: !0,
|
|
1586
1586
|
passive: !0
|
|
1587
1587
|
}), window.addEventListener("resize", this.onAway), window.addEventListener("blur", this.onAway);
|
|
@@ -1610,7 +1610,7 @@ var j = class e {
|
|
|
1610
1610
|
return e.className = "tcw-context-sep", e.setAttribute("role", "separator"), e;
|
|
1611
1611
|
}
|
|
1612
1612
|
let t = document.createElement("button");
|
|
1613
|
-
t.type = "button", t.className = `tcw-context-item${e.danger ? " tcw-context-danger" : ""}`, t.setAttribute("role",
|
|
1613
|
+
t.type = "button", t.className = `tcw-context-item${e.danger ? " tcw-context-danger" : ""}`, t.setAttribute("role", Nn(e)), (e.radio || e.checked !== void 0) && t.setAttribute("aria-checked", String(e.checked ?? !1)), t.tabIndex = -1, t.dataset.id = e.id, t.innerHTML = Pn(e);
|
|
1614
1614
|
let n = document.createElement("span");
|
|
1615
1615
|
n.className = "tcw-context-label", n.textContent = e.label, t.appendChild(n), this.appendEnd(t, e);
|
|
1616
1616
|
let r = e.submenu;
|
|
@@ -1653,9 +1653,9 @@ var j = class e {
|
|
|
1653
1653
|
xBack: o.left - a.left,
|
|
1654
1654
|
yBack: o.bottom - a.top,
|
|
1655
1655
|
before: this.rtl()
|
|
1656
|
-
}, c = window.matchMedia?.(
|
|
1656
|
+
}, c = window.matchMedia?.(kn).matches ?? !1, l = c ? [
|
|
1657
1657
|
{
|
|
1658
|
-
id:
|
|
1658
|
+
id: An,
|
|
1659
1659
|
label: t,
|
|
1660
1660
|
icon: "chevronLeft"
|
|
1661
1661
|
},
|
|
@@ -1663,9 +1663,9 @@ var j = class e {
|
|
|
1663
1663
|
...n
|
|
1664
1664
|
] : n;
|
|
1665
1665
|
i.show(l, s, (e) => {
|
|
1666
|
-
e !==
|
|
1666
|
+
e !== An && this.pick(e);
|
|
1667
1667
|
}, e, (e) => this.onRemove?.(e), r);
|
|
1668
|
-
let u = c ? i.el.querySelector(`[data-id="${
|
|
1668
|
+
let u = c ? i.el.querySelector(`[data-id="${An}"]`) : null;
|
|
1669
1669
|
u?.classList.add("tcw-context-back"), u && this.backLabel && u.setAttribute("aria-label", `${this.backLabel}: ${t}`), i.returnFocus = e;
|
|
1670
1670
|
}
|
|
1671
1671
|
makeChild() {
|
|
@@ -1678,7 +1678,7 @@ var j = class e {
|
|
|
1678
1678
|
let r = this.child?.isOpen() ? this.child.anchor : null;
|
|
1679
1679
|
(n ? r === e : r === null) || (this.hoverItem = e, this.hoverTimer = setTimeout(() => {
|
|
1680
1680
|
this.hoverTimer = null, this.hoverItem = null, n ? this.openSubmenu(e, t, n, !1) : this.child?.close();
|
|
1681
|
-
},
|
|
1681
|
+
}, Dn));
|
|
1682
1682
|
}
|
|
1683
1683
|
clearHover() {
|
|
1684
1684
|
this.hoverItem = null, this.hoverTimer !== null && (clearTimeout(this.hoverTimer), this.hoverTimer = null);
|
|
@@ -1702,7 +1702,7 @@ var j = class e {
|
|
|
1702
1702
|
this.close(), t?.(e);
|
|
1703
1703
|
}
|
|
1704
1704
|
items() {
|
|
1705
|
-
return [...this.el.querySelectorAll(
|
|
1705
|
+
return [...this.el.querySelectorAll(On)];
|
|
1706
1706
|
}
|
|
1707
1707
|
onKeyDown(e) {
|
|
1708
1708
|
let t = this.items(), n = t.indexOf(document.activeElement), [r, i] = this.rtl() ? ["ArrowLeft", "ArrowRight"] : ["ArrowRight", "ArrowLeft"], a = -1;
|
|
@@ -1728,7 +1728,7 @@ var j = class e {
|
|
|
1728
1728
|
} else return;
|
|
1729
1729
|
e.preventDefault(), this.child?.close(), t[a]?.focus({ preventScroll: !0 });
|
|
1730
1730
|
}
|
|
1731
|
-
},
|
|
1731
|
+
}, Fn = [
|
|
1732
1732
|
"en-US",
|
|
1733
1733
|
"en-GB",
|
|
1734
1734
|
"en-IN",
|
|
@@ -1746,15 +1746,15 @@ var j = class e {
|
|
|
1746
1746
|
"zh-TW",
|
|
1747
1747
|
"ja-JP",
|
|
1748
1748
|
"ko-KR"
|
|
1749
|
-
],
|
|
1750
|
-
function
|
|
1751
|
-
return (e && !
|
|
1749
|
+
], In = 65234;
|
|
1750
|
+
function Ln(e) {
|
|
1751
|
+
return (e && !Fn.includes(e) ? [e, ...Fn] : Fn).map((e) => {
|
|
1752
1752
|
let t;
|
|
1753
1753
|
try {
|
|
1754
1754
|
t = new Intl.NumberFormat(e, {
|
|
1755
1755
|
minimumFractionDigits: 2,
|
|
1756
1756
|
maximumFractionDigits: 2
|
|
1757
|
-
}).format(
|
|
1757
|
+
}).format(In);
|
|
1758
1758
|
} catch {
|
|
1759
1759
|
t = "";
|
|
1760
1760
|
}
|
|
@@ -1764,7 +1764,7 @@ function In(e) {
|
|
|
1764
1764
|
};
|
|
1765
1765
|
});
|
|
1766
1766
|
}
|
|
1767
|
-
var
|
|
1767
|
+
var Rn = {
|
|
1768
1768
|
Lines: "toolGroup.lines",
|
|
1769
1769
|
"Horizontal/Vertical": "toolGroup.horizontalVertical",
|
|
1770
1770
|
Channels: "toolGroup.channels",
|
|
@@ -1779,14 +1779,14 @@ var Ln = {
|
|
|
1779
1779
|
Cycles: "toolGroup.cycles",
|
|
1780
1780
|
"Elliott Waves": "toolGroup.elliott"
|
|
1781
1781
|
};
|
|
1782
|
-
function
|
|
1782
|
+
function zn(e, t) {
|
|
1783
1783
|
let n = `chartType.${e.value}`, r = t(n);
|
|
1784
1784
|
return r === n ? e.label : r;
|
|
1785
1785
|
}
|
|
1786
|
-
function
|
|
1786
|
+
function Bn(e, t) {
|
|
1787
1787
|
return e.map((e) => ({
|
|
1788
1788
|
...e,
|
|
1789
|
-
label:
|
|
1789
|
+
label: Rn[e.label] ? t(Rn[e.label]) : e.label,
|
|
1790
1790
|
tools: e.tools.map((e) => {
|
|
1791
1791
|
let n = `tool.${e.value}`, r = t(n);
|
|
1792
1792
|
return {
|
|
@@ -1798,7 +1798,7 @@ function zn(e, t) {
|
|
|
1798
1798
|
}
|
|
1799
1799
|
//#endregion
|
|
1800
1800
|
//#region src/widget/widgetTimeframes.ts
|
|
1801
|
-
var
|
|
1801
|
+
var Vn = [
|
|
1802
1802
|
"1m",
|
|
1803
1803
|
"3m",
|
|
1804
1804
|
"5m",
|
|
@@ -1810,33 +1810,33 @@ var Bn = [
|
|
|
1810
1810
|
"1d",
|
|
1811
1811
|
"1w",
|
|
1812
1812
|
"1M"
|
|
1813
|
-
],
|
|
1813
|
+
], Hn = [
|
|
1814
1814
|
"1m",
|
|
1815
1815
|
"5m",
|
|
1816
1816
|
"15m",
|
|
1817
1817
|
"1h",
|
|
1818
1818
|
"4h",
|
|
1819
1819
|
"1d"
|
|
1820
|
-
],
|
|
1821
|
-
function
|
|
1820
|
+
], Un = 6;
|
|
1821
|
+
function Wn(e) {
|
|
1822
1822
|
let t = e.slice(-1);
|
|
1823
1823
|
return t === "h" || t === "d" || t === "w" ? e.slice(0, -1) + t.toUpperCase() : e;
|
|
1824
1824
|
}
|
|
1825
|
-
var
|
|
1825
|
+
var Gn = (e) => Number.isFinite(C(e)) || Oe(e) !== null, Kn = (e, t) => {
|
|
1826
1826
|
let n = Oe(e), r = Oe(t);
|
|
1827
1827
|
return n !== null || r !== null ? n === null ? 1 : r === null ? -1 : n - r : C(e) - C(t);
|
|
1828
1828
|
};
|
|
1829
|
-
function
|
|
1830
|
-
let n = t?.length ? t : null, r = e?.length ? e : n ??
|
|
1831
|
-
return [...new Set(r)].filter((e) =>
|
|
1829
|
+
function qn(e, t) {
|
|
1830
|
+
let n = t?.length ? t : null, r = e?.length ? e : n ?? Vn;
|
|
1831
|
+
return [...new Set(r)].filter((e) => Gn(e) && (!n || n.includes(e))).sort(Kn);
|
|
1832
1832
|
}
|
|
1833
|
-
function
|
|
1833
|
+
function Jn(e, t, n = !1) {
|
|
1834
1834
|
if (t?.length) return e.filter((e) => t.includes(e));
|
|
1835
1835
|
if (n) return [...e];
|
|
1836
|
-
let r = e.filter((e) =>
|
|
1837
|
-
return r.length > 0 ? r : e.slice(0,
|
|
1836
|
+
let r = e.filter((e) => Hn.includes(e));
|
|
1837
|
+
return r.length > 0 ? r : e.slice(0, Un);
|
|
1838
1838
|
}
|
|
1839
|
-
var
|
|
1839
|
+
var Yn = 9999, Xn = {
|
|
1840
1840
|
"": "m",
|
|
1841
1841
|
s: "s",
|
|
1842
1842
|
S: "s",
|
|
@@ -1848,30 +1848,30 @@ var Jn = 9999, Yn = {
|
|
|
1848
1848
|
w: "w",
|
|
1849
1849
|
W: "w",
|
|
1850
1850
|
M: "M"
|
|
1851
|
-
},
|
|
1851
|
+
}, Zn = {
|
|
1852
1852
|
s: ["m", 60],
|
|
1853
1853
|
m: ["h", 60],
|
|
1854
1854
|
h: ["d", 24]
|
|
1855
1855
|
};
|
|
1856
|
-
function
|
|
1856
|
+
function Qn(e) {
|
|
1857
1857
|
let t = /^(\d+)([a-zA-Z]?)$/.exec(e.trim());
|
|
1858
1858
|
if (!t) return null;
|
|
1859
1859
|
if (t[2] === "T" || t[2] === "t") {
|
|
1860
1860
|
let e = `${Number(t[1])}T`;
|
|
1861
|
-
return Number(t[1]) <=
|
|
1861
|
+
return Number(t[1]) <= Yn && Oe(e) !== null ? e : null;
|
|
1862
1862
|
}
|
|
1863
|
-
let n = Number(t[1]), r =
|
|
1863
|
+
let n = Number(t[1]), r = Xn[t[2]];
|
|
1864
1864
|
if (!r || !Number.isSafeInteger(n) || n < 1) return null;
|
|
1865
|
-
for (let e =
|
|
1866
|
-
if (n >
|
|
1865
|
+
for (let e = Zn[r]; e && n % e[1] === 0; e = Zn[r]) n /= e[1], r = e[0];
|
|
1866
|
+
if (n > Yn) return null;
|
|
1867
1867
|
let i = `${n}${r}`;
|
|
1868
1868
|
return fe(i) ? i : null;
|
|
1869
1869
|
}
|
|
1870
|
-
function
|
|
1871
|
-
let r = n?.length ? n : null, i = t.filter((e) =>
|
|
1872
|
-
return [...new Set([...e, ...i])].sort(
|
|
1870
|
+
function $n(e, t, n) {
|
|
1871
|
+
let r = n?.length ? n : null, i = t.filter((e) => Gn(e) && (!r || r.includes(e)));
|
|
1872
|
+
return [...new Set([...e, ...i])].sort(Kn);
|
|
1873
1873
|
}
|
|
1874
|
-
var
|
|
1874
|
+
var er = [
|
|
1875
1875
|
"T",
|
|
1876
1876
|
"s",
|
|
1877
1877
|
"m",
|
|
@@ -1880,42 +1880,42 @@ var $n = [
|
|
|
1880
1880
|
"w",
|
|
1881
1881
|
"M"
|
|
1882
1882
|
];
|
|
1883
|
-
function
|
|
1883
|
+
function tr(e) {
|
|
1884
1884
|
let t = (e) => {
|
|
1885
1885
|
let t = e.slice(-1);
|
|
1886
|
-
return
|
|
1886
|
+
return er.includes(t) ? t : "m";
|
|
1887
1887
|
};
|
|
1888
|
-
return
|
|
1888
|
+
return er.map((n) => ({
|
|
1889
1889
|
unit: n,
|
|
1890
1890
|
timeframes: e.filter((e) => t(e.value) === n)
|
|
1891
1891
|
})).filter((e) => e.timeframes.length > 0);
|
|
1892
1892
|
}
|
|
1893
|
-
var
|
|
1894
|
-
function
|
|
1893
|
+
var nr = 864e5, rr = 5 / 7;
|
|
1894
|
+
function ir(e) {
|
|
1895
1895
|
let t = C(e.current), n = C(e.chosen);
|
|
1896
1896
|
if (!Number.isFinite(t) || !Number.isFinite(n) || !(e.width > 0) || !(e.spanMs > 0)) return e.current;
|
|
1897
1897
|
let r = (n) => {
|
|
1898
1898
|
if (n === t) return e.barsInSpan;
|
|
1899
|
-
if (n <
|
|
1899
|
+
if (n < nr) return e.barsInSpan * t / n;
|
|
1900
1900
|
let r = e.spanMs / n;
|
|
1901
|
-
return n ===
|
|
1901
|
+
return n === nr ? r * (e.dayShare ?? rr) : r;
|
|
1902
1902
|
}, i = [...new Set([...e.available, e.current])].filter((e) => {
|
|
1903
1903
|
let t = C(e);
|
|
1904
1904
|
return Number.isFinite(t) && t >= n;
|
|
1905
|
-
}).sort(
|
|
1905
|
+
}).sort(Kn);
|
|
1906
1906
|
for (let t of i) if (r(C(t)) * 2 <= e.width) return t;
|
|
1907
1907
|
return i[i.length - 1] ?? e.current;
|
|
1908
1908
|
}
|
|
1909
1909
|
//#endregion
|
|
1910
1910
|
//#region src/widget/WidgetTradeMenu.ts
|
|
1911
|
-
var
|
|
1911
|
+
var ar = {
|
|
1912
1912
|
ticket: "receipt",
|
|
1913
1913
|
long: "trendingUp",
|
|
1914
1914
|
short: "trendingDown",
|
|
1915
1915
|
ladder: "ladder",
|
|
1916
1916
|
account: "layers"
|
|
1917
|
-
},
|
|
1918
|
-
function
|
|
1917
|
+
}, or = ["ladder", "account"];
|
|
1918
|
+
function sr(e, t) {
|
|
1919
1919
|
let n = [];
|
|
1920
1920
|
e.onOrderTicket && n.push({
|
|
1921
1921
|
id: "ticket",
|
|
@@ -1946,12 +1946,12 @@ function or(e, t) {
|
|
|
1946
1946
|
run: e.onToggleAccount
|
|
1947
1947
|
}), n;
|
|
1948
1948
|
}
|
|
1949
|
-
var
|
|
1949
|
+
var cr = class e {
|
|
1950
1950
|
button;
|
|
1951
1951
|
menu = null;
|
|
1952
1952
|
open = /* @__PURE__ */ new Set();
|
|
1953
1953
|
static create(t, n, r, i) {
|
|
1954
|
-
let a =
|
|
1954
|
+
let a = sr(t, n);
|
|
1955
1955
|
return a.length > 0 ? new e(a, n, r, i) : null;
|
|
1956
1956
|
}
|
|
1957
1957
|
constructor(e, t, n, r) {
|
|
@@ -1963,7 +1963,7 @@ var sr = class e {
|
|
|
1963
1963
|
this.button.hidden = this.items.every((e) => this.isOff(e.parts));
|
|
1964
1964
|
}
|
|
1965
1965
|
setOpen(e, t) {
|
|
1966
|
-
let n =
|
|
1966
|
+
let n = or.find((t) => t === e);
|
|
1967
1967
|
n && (t ? this.open.add(n) : this.open.delete(n));
|
|
1968
1968
|
}
|
|
1969
1969
|
destroy() {
|
|
@@ -1980,11 +1980,11 @@ var sr = class e {
|
|
|
1980
1980
|
}
|
|
1981
1981
|
let t = this.items.filter((e) => !this.isOff(e.parts));
|
|
1982
1982
|
if (t.length === 0) return;
|
|
1983
|
-
let n = t.filter((e) => !
|
|
1983
|
+
let n = t.filter((e) => !or.includes(e.id)), r = t.filter((e) => or.includes(e.id)), i = [
|
|
1984
1984
|
...n.map((e) => ({
|
|
1985
1985
|
id: e.id,
|
|
1986
1986
|
label: e.label,
|
|
1987
|
-
icon:
|
|
1987
|
+
icon: ar[e.id]
|
|
1988
1988
|
})),
|
|
1989
1989
|
...n.length > 0 && r.length > 0 ? ["separator"] : [],
|
|
1990
1990
|
...r.map((e) => ({
|
|
@@ -1997,22 +1997,22 @@ var sr = class e {
|
|
|
1997
1997
|
t.find((t) => t.id === e)?.run();
|
|
1998
1998
|
});
|
|
1999
1999
|
}
|
|
2000
|
-
},
|
|
2000
|
+
}, lr = 2048, ur = 65536, dr = /^data:image\/(png|jpeg|gif|webp|avif|svg\+xml)[;,]/i, fr = new Set([
|
|
2001
2001
|
"https:",
|
|
2002
2002
|
"http:",
|
|
2003
2003
|
"blob:"
|
|
2004
|
-
]),
|
|
2004
|
+
]), pr = new Set([
|
|
2005
2005
|
"description",
|
|
2006
2006
|
"exchange",
|
|
2007
2007
|
"type",
|
|
2008
2008
|
"logo"
|
|
2009
2009
|
]);
|
|
2010
|
-
function
|
|
2010
|
+
function mr(e) {
|
|
2011
2011
|
if (typeof e != "string") return null;
|
|
2012
2012
|
let t = e.trim();
|
|
2013
2013
|
return t && t.length <= 64 ? t : null;
|
|
2014
2014
|
}
|
|
2015
|
-
function
|
|
2015
|
+
function hr(e) {
|
|
2016
2016
|
let t = [], n = /* @__PURE__ */ new Map();
|
|
2017
2017
|
if (!Array.isArray(e)) return {
|
|
2018
2018
|
names: t,
|
|
@@ -2020,30 +2020,30 @@ function mr(e) {
|
|
|
2020
2020
|
};
|
|
2021
2021
|
let r = /* @__PURE__ */ new Set();
|
|
2022
2022
|
for (let i of e) {
|
|
2023
|
-
let e = typeof i == "object" && !!i, a =
|
|
2024
|
-
!a || r.has(a) || (r.add(a), t.push(a), e && n.set(a,
|
|
2023
|
+
let e = typeof i == "object" && !!i, a = mr(e ? i.symbol : i);
|
|
2024
|
+
!a || r.has(a) || (r.add(a), t.push(a), e && n.set(a, gr(i, a)));
|
|
2025
2025
|
}
|
|
2026
2026
|
return {
|
|
2027
2027
|
names: t,
|
|
2028
2028
|
info: n
|
|
2029
2029
|
};
|
|
2030
2030
|
}
|
|
2031
|
-
function
|
|
2031
|
+
function gr(e, t) {
|
|
2032
2032
|
return {
|
|
2033
|
-
...Object.fromEntries(Object.entries(e).filter(([e, t]) => e !== "__proto__" && (!
|
|
2033
|
+
...Object.fromEntries(Object.entries(e).filter(([e, t]) => e !== "__proto__" && (!pr.has(e) || typeof t == "string" && t.trim() !== ""))),
|
|
2034
2034
|
symbol: t
|
|
2035
2035
|
};
|
|
2036
2036
|
}
|
|
2037
|
-
function
|
|
2038
|
-
return Array.isArray(e) ? e.filter((e) => typeof e == "object" && !!e && typeof e.symbol == "string" && e.symbol !== "").map((e) =>
|
|
2037
|
+
function _r(e) {
|
|
2038
|
+
return Array.isArray(e) ? e.filter((e) => typeof e == "object" && !!e && typeof e.symbol == "string" && e.symbol !== "").map((e) => gr(e, e.symbol)) : [];
|
|
2039
2039
|
}
|
|
2040
|
-
function
|
|
2040
|
+
function vr(e, t) {
|
|
2041
2041
|
if (!t) return e;
|
|
2042
2042
|
if (!e) return t;
|
|
2043
2043
|
let n = Object.entries(t).filter(([, e]) => e != null);
|
|
2044
2044
|
return Object.fromEntries([...Object.entries(e), ...n]);
|
|
2045
2045
|
}
|
|
2046
|
-
function
|
|
2046
|
+
function yr(e) {
|
|
2047
2047
|
let t = e.lastIndexOf(":");
|
|
2048
2048
|
return t <= 0 || t === e.length - 1 ? {
|
|
2049
2049
|
venue: "",
|
|
@@ -2053,33 +2053,33 @@ function vr(e) {
|
|
|
2053
2053
|
ticker: e.slice(t + 1)
|
|
2054
2054
|
};
|
|
2055
2055
|
}
|
|
2056
|
-
var
|
|
2057
|
-
function
|
|
2058
|
-
return !t || typeof t.symbol != "string" ? null : t.symbol.toUpperCase() === e.toUpperCase() || t.symbol.includes(":") !== e.includes(":") &&
|
|
2056
|
+
var br = (e) => yr(e).ticker.toUpperCase();
|
|
2057
|
+
function xr(e, t) {
|
|
2058
|
+
return !t || typeof t.symbol != "string" ? null : t.symbol.toUpperCase() === e.toUpperCase() || t.symbol.includes(":") !== e.includes(":") && br(t.symbol) === br(e) ? t : null;
|
|
2059
2059
|
}
|
|
2060
|
-
function
|
|
2060
|
+
function Sr(e) {
|
|
2061
2061
|
return [e?.description, e?.exchange].filter(Boolean).join(" · ") || null;
|
|
2062
2062
|
}
|
|
2063
|
-
var
|
|
2064
|
-
function
|
|
2063
|
+
var Cr = () => typeof document > "u" ? void 0 : document.baseURI;
|
|
2064
|
+
function wr(e, t = Cr()) {
|
|
2065
2065
|
if (typeof e != "string") return null;
|
|
2066
2066
|
let n = e.trim();
|
|
2067
|
-
if (!n || n.length >
|
|
2067
|
+
if (!n || n.length > ur) return null;
|
|
2068
2068
|
let r;
|
|
2069
2069
|
try {
|
|
2070
2070
|
r = new URL(n, t);
|
|
2071
2071
|
} catch {
|
|
2072
2072
|
return null;
|
|
2073
2073
|
}
|
|
2074
|
-
return r.protocol === "data:" ?
|
|
2074
|
+
return r.protocol === "data:" ? dr.test(r.href) && r.href.length <= ur ? r.href : null : fr.has(r.protocol) && r.href.length <= lr ? r.href : null;
|
|
2075
2075
|
}
|
|
2076
2076
|
//#endregion
|
|
2077
2077
|
//#region src/widget/WidgetToolbar.ts
|
|
2078
|
-
var
|
|
2078
|
+
var Tr = 0, M = "data-tcw-folded", Er = 1 / 64, Dr = [
|
|
2079
2079
|
"venue",
|
|
2080
2080
|
"ticker",
|
|
2081
2081
|
"cut"
|
|
2082
|
-
],
|
|
2082
|
+
], Or = {
|
|
2083
2083
|
T: "toolbar.timeframes.ticks",
|
|
2084
2084
|
s: "toolbar.timeframes.seconds",
|
|
2085
2085
|
m: "toolbar.timeframes.minutes",
|
|
@@ -2088,11 +2088,11 @@ var wr = 0, M = "data-tcw-folded", Tr = 1 / 64, Er = [
|
|
|
2088
2088
|
w: "toolbar.timeframes.weeks",
|
|
2089
2089
|
M: "toolbar.timeframes.months"
|
|
2090
2090
|
};
|
|
2091
|
-
function
|
|
2091
|
+
function kr(e, t) {
|
|
2092
2092
|
let n = e.querySelector(".tcw-host-btn-text")?.textContent ?? "";
|
|
2093
2093
|
n === t ? e.removeAttribute("aria-label") : e.setAttribute("aria-label", n ? `${t}: ${n}` : t);
|
|
2094
2094
|
}
|
|
2095
|
-
var
|
|
2095
|
+
var Ar = class {
|
|
2096
2096
|
config;
|
|
2097
2097
|
callbacks;
|
|
2098
2098
|
t;
|
|
@@ -2101,7 +2101,7 @@ var kr = class {
|
|
|
2101
2101
|
tfGroup = null;
|
|
2102
2102
|
tfDropdown = null;
|
|
2103
2103
|
tfFavorites = [];
|
|
2104
|
-
uid = (
|
|
2104
|
+
uid = (Tr++).toString(36);
|
|
2105
2105
|
tfRendered = "";
|
|
2106
2106
|
themeBtn = null;
|
|
2107
2107
|
fullscreenBtn = null;
|
|
@@ -2149,7 +2149,7 @@ var kr = class {
|
|
|
2149
2149
|
e.setAttribute(M, "");
|
|
2150
2150
|
break;
|
|
2151
2151
|
}
|
|
2152
|
-
for (let n of
|
|
2152
|
+
for (let n of Dr) {
|
|
2153
2153
|
if (t()) return;
|
|
2154
2154
|
e.dataset.tcwSqueeze = n;
|
|
2155
2155
|
}
|
|
@@ -2162,7 +2162,7 @@ var kr = class {
|
|
|
2162
2162
|
let e = r.getBoundingClientRect();
|
|
2163
2163
|
s = Math.max(s, (i ? t.right - e.left : e.right - t.left) / n);
|
|
2164
2164
|
}
|
|
2165
|
-
return Math.ceil(s -
|
|
2165
|
+
return Math.ceil(s - Er) <= Math.floor(o + Er);
|
|
2166
2166
|
}
|
|
2167
2167
|
foldedState() {
|
|
2168
2168
|
let e = [...this.el.querySelectorAll(".tcw-toolbar-overflow")];
|
|
@@ -2206,7 +2206,7 @@ var kr = class {
|
|
|
2206
2206
|
let e = document.createElement("div");
|
|
2207
2207
|
e.style.position = "relative", e.style.display = "inline-flex", O(e, "toolbar.timeframeMenu");
|
|
2208
2208
|
let t = document.createElement("button");
|
|
2209
|
-
t.className = "tcw-btn tcw-tf-more", t.dataset.role = "timeframes", t.title = this.t("toolbar.timeframes"), t.setAttribute("aria-label", this.t("toolbar.timeframes")), this.tfCurrent = document.createElement("span"), this.tfCurrent.className = "tcw-tf-current", t.appendChild(this.tfCurrent), t.insertAdjacentHTML("beforeend", k("chevronDown", 12)), e.appendChild(t), n.appendChild(e), this.tfDropdown = new
|
|
2209
|
+
t.className = "tcw-btn tcw-tf-more", t.dataset.role = "timeframes", t.title = this.t("toolbar.timeframes"), t.setAttribute("aria-label", this.t("toolbar.timeframes")), this.tfCurrent = document.createElement("span"), this.tfCurrent.className = "tcw-tf-current", t.appendChild(this.tfCurrent), t.insertAdjacentHTML("beforeend", k("chevronDown", 12)), e.appendChild(t), n.appendChild(e), this.tfDropdown = new wn(e, {
|
|
2210
2210
|
width: "150px",
|
|
2211
2211
|
layer: this.layer
|
|
2212
2212
|
}), n.classList.add("tcw-toolbar--tf-menu"), this.buildTimeframeMenu();
|
|
@@ -2215,7 +2215,7 @@ var kr = class {
|
|
|
2215
2215
|
let i = document.createElement("div");
|
|
2216
2216
|
i.style.position = "relative", i.style.display = "inline-flex", O(i, "toolbar.chartType");
|
|
2217
2217
|
let a = document.createElement("button");
|
|
2218
|
-
a.className = "tcw-dropdown-trigger", a.dataset.role = "charttype", i.appendChild(a), n.appendChild(i), this.chartTypeDropdown = new
|
|
2218
|
+
a.className = "tcw-dropdown-trigger", a.dataset.role = "charttype", i.appendChild(a), n.appendChild(i), this.chartTypeDropdown = new wn(i, {
|
|
2219
2219
|
width: "160px",
|
|
2220
2220
|
layer: this.layer
|
|
2221
2221
|
}), this.buildChartTypeMenu(), n.appendChild(this.sep());
|
|
@@ -2242,7 +2242,7 @@ var kr = class {
|
|
|
2242
2242
|
let e = this.iconBtn("bell", this.t("toolbar.priceAlerts"), t.onToggleAlerts);
|
|
2243
2243
|
e.dataset.role = "alerts", e.setAttribute("aria-pressed", "false"), O(e, "alerts", "toolbar.alerts"), n.appendChild(e);
|
|
2244
2244
|
}
|
|
2245
|
-
this.trade =
|
|
2245
|
+
this.trade = cr.create(t, this.t, () => this.rootEl(), (e) => this.menuAnchor(e)), this.trade && n.appendChild(this.trade.button), n.appendChild(this.sep());
|
|
2246
2246
|
let s = this.iconBtn("camera", this.t("toolbar.screenshot"), t.onScreenshot);
|
|
2247
2247
|
O(s, "screenshot", "toolbar.screenshot"), n.appendChild(s);
|
|
2248
2248
|
let c = this.iconBtn("settings", this.t("toolbar.settings"), t.onSettings);
|
|
@@ -2282,7 +2282,7 @@ var kr = class {
|
|
|
2282
2282
|
let e = document.createElement("span");
|
|
2283
2283
|
e.className = "tcw-host-btn-text", e.textContent = n, t.appendChild(e);
|
|
2284
2284
|
}
|
|
2285
|
-
return
|
|
2285
|
+
return kr(t, e.label), t.addEventListener("click", () => e.onClick(t)), (e.side === "left" ? this.hostLeft : this.hostRight)?.appendChild(t), this.scheduleFit(), t;
|
|
2286
2286
|
}
|
|
2287
2287
|
hostSlot(e) {
|
|
2288
2288
|
return e === "left" ? this.hostLeft : this.hostRight;
|
|
@@ -2296,7 +2296,7 @@ var kr = class {
|
|
|
2296
2296
|
t && (e ? t.removeAttribute("aria-disabled") : t.setAttribute("aria-disabled", "true"));
|
|
2297
2297
|
}
|
|
2298
2298
|
tidy() {
|
|
2299
|
-
this.trade?.tidy(),
|
|
2299
|
+
this.trade?.tidy(), hn(this.el, "tcw-toolbar-sep", "tcw-toolbar-spacer"), this.scheduleFit();
|
|
2300
2300
|
}
|
|
2301
2301
|
setHistory(e, t) {
|
|
2302
2302
|
this.undoBtn && (this.undoBtn.disabled = !e), this.redoBtn && (this.redoBtn.disabled = !t);
|
|
@@ -2328,11 +2328,11 @@ var kr = class {
|
|
|
2328
2328
|
this.fullscreenBtn.innerHTML = k(e ? "minimize" : "maximize", 14), this.fullscreenBtn.title = t, this.fullscreenBtn.setAttribute("aria-pressed", String(e));
|
|
2329
2329
|
}
|
|
2330
2330
|
chartTypeLabel(e) {
|
|
2331
|
-
return
|
|
2331
|
+
return zn(e, this.t);
|
|
2332
2332
|
}
|
|
2333
2333
|
buildChartTypeMenu() {
|
|
2334
2334
|
if (!this.chartTypeDropdown) return;
|
|
2335
|
-
let e = this.config.chartTypes.map((e) => `<button class="tcw-dropdown-item tcw-dropdown-item--icon" data-ct="${A(e.value)}">${
|
|
2335
|
+
let e = this.config.chartTypes.map((e) => `<button class="tcw-dropdown-item tcw-dropdown-item--icon" data-ct="${A(e.value)}">${Cn(e.value, 16)}<span>${A(this.chartTypeLabel(e))}</span></button>`).join("");
|
|
2336
2336
|
this.chartTypeDropdown.setContent(e), this.chartTypeDropdown.panel.querySelectorAll(".tcw-dropdown-item").forEach((e) => {
|
|
2337
2337
|
e.addEventListener("click", (e) => {
|
|
2338
2338
|
let t = e.currentTarget.dataset.ct;
|
|
@@ -2356,8 +2356,8 @@ var kr = class {
|
|
|
2356
2356
|
buildTimeframeMenu() {
|
|
2357
2357
|
if (!this.tfDropdown) return;
|
|
2358
2358
|
let e = A(this.t("toolbar.timeframes.pin")), t = A(this.t("toolbar.timeframes.remove")), n = "";
|
|
2359
|
-
for (let { unit: r, timeframes: i } of
|
|
2360
|
-
n += `<div class="tcw-tf-section" data-tf-section="${r}" role="group" aria-label="${A(this.t(
|
|
2359
|
+
for (let { unit: r, timeframes: i } of tr(this.config.timeframes)) {
|
|
2360
|
+
n += `<div class="tcw-tf-section" data-tf-section="${r}" role="group" aria-label="${A(this.t(Or[r]))}"><div class="tcw-dropdown-label">${A(this.t(Or[r]))}</div>`;
|
|
2361
2361
|
for (let r of i) {
|
|
2362
2362
|
let i = this.tfFavorites.includes(r.value), [a, o] = [A(r.value), A(r.label)];
|
|
2363
2363
|
n += `<div class="tcw-tf-row"><button class="tcw-dropdown-item" data-tf-pick="${a}">${o}</button>` + (r.custom && this.callbacks.onRemoveTimeframe ? `<button class="tcw-tf-remove" data-tf-remove="${a}" title="${t}" aria-label="${t}: ${o}">${k("x", 12)}</button>` : "") + `<button class="tcw-tf-star${i ? " tcw-active" : ""}" data-tf-star="${a}" aria-pressed="${i}" title="${e}" aria-label="${e}: ${o}">${k("star", 12)}</button></div>`;
|
|
@@ -2366,7 +2366,7 @@ var kr = class {
|
|
|
2366
2366
|
}
|
|
2367
2367
|
if (this.callbacks.onAddTimeframe) {
|
|
2368
2368
|
let e = A(this.t("toolbar.timeframes.custom")), t = A(this.t("toolbar.timeframes.add"));
|
|
2369
|
-
n += `<form class="tcw-tf-custom" ${
|
|
2369
|
+
n += `<form class="tcw-tf-custom" ${pn("customTimeframes")} novalidate><input class="tcw-tf-custom-input" type="text" autocomplete="off" spellcheck="false" maxlength="6" placeholder="7m, 90m, 2h…" aria-label="${e}" aria-describedby="tcw-tf-hint-${this.uid}"><button type="submit" class="tcw-tf-custom-add" title="${t}" aria-label="${t}">${k("plus", 12)}</button><div class="tcw-tf-custom-hint" id="tcw-tf-hint-${this.uid}" role="status"></div></form>`;
|
|
2370
2370
|
}
|
|
2371
2371
|
this.tfDropdown.setContent(n);
|
|
2372
2372
|
let r = this.tfDropdown.panel;
|
|
@@ -2409,7 +2409,7 @@ var kr = class {
|
|
|
2409
2409
|
let t = this.el.querySelector("[data-role=\"symbol\"]");
|
|
2410
2410
|
if (!t || this.symbolShown === e) return;
|
|
2411
2411
|
this.symbolShown = e;
|
|
2412
|
-
let { venue: n, ticker: r } =
|
|
2412
|
+
let { venue: n, ticker: r } = yr(e), i = (e, t) => {
|
|
2413
2413
|
let n = document.createElement("span");
|
|
2414
2414
|
return n.className = e, n.textContent = t, n;
|
|
2415
2415
|
};
|
|
@@ -2420,7 +2420,7 @@ var kr = class {
|
|
|
2420
2420
|
let t = this.el.querySelector("[data-role=\"charttype\"]");
|
|
2421
2421
|
if (t) {
|
|
2422
2422
|
let n = this.config.chartTypes.find((t) => t.value === e.chartType), r = n ? this.chartTypeLabel(n) : e.chartType;
|
|
2423
|
-
t.innerHTML =
|
|
2423
|
+
t.innerHTML = Cn(e.chartType, 16), t.title = r, t.setAttribute("aria-label", r);
|
|
2424
2424
|
}
|
|
2425
2425
|
let n = this.el.querySelector("[data-role=\"indicators\"]");
|
|
2426
2426
|
if (n) {
|
|
@@ -2451,28 +2451,28 @@ var kr = class {
|
|
|
2451
2451
|
};
|
|
2452
2452
|
//#endregion
|
|
2453
2453
|
//#region src/widget/hostButtons.ts
|
|
2454
|
-
function
|
|
2454
|
+
function jr(e, t, n) {
|
|
2455
2455
|
e.classList.toggle("tcw-active", t), n && e.setAttribute("aria-pressed", String(t));
|
|
2456
2456
|
}
|
|
2457
|
-
function
|
|
2457
|
+
function Mr(e, t, n) {
|
|
2458
2458
|
let r = n == null ? "" : String(n), i = e.querySelector(".tcw-host-btn-text");
|
|
2459
|
-
return (i?.textContent ?? "") === r ? !1 : (i || (i = document.createElement("span"), i.className = "tcw-host-btn-text", e.appendChild(i)), i.textContent = r,
|
|
2459
|
+
return (i?.textContent ?? "") === r ? !1 : (i || (i = document.createElement("span"), i.className = "tcw-host-btn-text", e.appendChild(i)), i.textContent = r, kr(e, t), !0);
|
|
2460
2460
|
}
|
|
2461
2461
|
//#endregion
|
|
2462
2462
|
//#region src/widget/WidgetDrawingSidebar.ts
|
|
2463
|
-
var
|
|
2464
|
-
function
|
|
2463
|
+
var Nr = 16, Pr = 150, Fr = 4;
|
|
2464
|
+
function Ir(e) {
|
|
2465
2465
|
let t = `sidebar.${e}`;
|
|
2466
|
-
return
|
|
2466
|
+
return en.includes(t) ? t : null;
|
|
2467
2467
|
}
|
|
2468
|
-
function
|
|
2468
|
+
function Lr(e, t) {
|
|
2469
2469
|
for (let n of e) {
|
|
2470
2470
|
let e = n.tools.find((e) => e.value === t);
|
|
2471
2471
|
if (e) return e.label;
|
|
2472
2472
|
}
|
|
2473
2473
|
return t;
|
|
2474
2474
|
}
|
|
2475
|
-
var
|
|
2475
|
+
var Rr = "--tcw-fab-plot-left", zr = class {
|
|
2476
2476
|
config;
|
|
2477
2477
|
callbacks;
|
|
2478
2478
|
el;
|
|
@@ -2512,7 +2512,7 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2512
2512
|
}
|
|
2513
2513
|
setPlotLeft(e) {
|
|
2514
2514
|
let t = `${Math.max(0, Math.round(e))}px`;
|
|
2515
|
-
this.fab.style.getPropertyValue(
|
|
2515
|
+
this.fab.style.getPropertyValue(Rr) !== t && this.fab.style.setProperty(Rr, t);
|
|
2516
2516
|
}
|
|
2517
2517
|
isNarrow() {
|
|
2518
2518
|
return this.el.closest("[data-tcw-narrow]") !== null;
|
|
@@ -2547,14 +2547,14 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2547
2547
|
e.section !== void 0 && r !== void 0 && e.section !== r && this.appendDivider(), r = e.section;
|
|
2548
2548
|
let i = document.createElement("div");
|
|
2549
2549
|
i.className = "tcw-tool-group-wrap";
|
|
2550
|
-
let a =
|
|
2550
|
+
let a = Ir(e.section);
|
|
2551
2551
|
a && O(i, a);
|
|
2552
2552
|
let o = document.createElement("button");
|
|
2553
2553
|
o.className = "tcw-sidebar-btn";
|
|
2554
2554
|
let s = e.tools[0].value;
|
|
2555
2555
|
e.tools.length > 1 ? o.setAttribute("aria-label", `${e.label}: ${e.tools[0].label}`) : o.title = e.label;
|
|
2556
2556
|
let c = document.createElement("span");
|
|
2557
|
-
if (c.className = "tcw-sidebar-icon", c.innerHTML =
|
|
2557
|
+
if (c.className = "tcw-sidebar-icon", c.innerHTML = Sn(s, Nr), o.appendChild(c), this.groupIcons.push(c), this.groupTools.push(s), e.tools.length > 1) {
|
|
2558
2558
|
let e = document.createElement("span");
|
|
2559
2559
|
e.className = "tcw-multi-dot", o.appendChild(e);
|
|
2560
2560
|
}
|
|
@@ -2627,7 +2627,7 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2627
2627
|
this.favoritesEl.style.display = e ? "" : "none", this.favoritesDivider && (this.favoritesDivider.style.display = e ? "" : "none");
|
|
2628
2628
|
for (let e of this.favorites) {
|
|
2629
2629
|
let t = document.createElement("button");
|
|
2630
|
-
t.className = "tcw-sidebar-btn", t.title = h(this.t("sidebar.unpinHint"), { tool:
|
|
2630
|
+
t.className = "tcw-sidebar-btn", t.title = h(this.t("sidebar.unpinHint"), { tool: Lr(this.config.drawingToolGroups, e) }), t.dataset.toolValue = e, t.innerHTML = Sn(e, Nr), t.addEventListener("click", () => this.pick(e)), t.addEventListener("contextmenu", (t) => {
|
|
2631
2631
|
t.preventDefault(), this.callbacks.onToggleFavorite?.(e);
|
|
2632
2632
|
}), this.favoritesEl.appendChild(t);
|
|
2633
2633
|
}
|
|
@@ -2649,7 +2649,7 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2649
2649
|
let t = document.createElement("div");
|
|
2650
2650
|
t.className = "tcw-flyout-row", t.setAttribute("role", "none"), t.dataset.toolValue = e.value;
|
|
2651
2651
|
let r = document.createElement("button");
|
|
2652
|
-
r.className = "tcw-flyout-item", r.setAttribute("role", "menuitem"), r.tabIndex = -1, r.innerHTML =
|
|
2652
|
+
r.className = "tcw-flyout-item", r.setAttribute("role", "menuitem"), r.tabIndex = -1, r.innerHTML = Sn(e.value, Nr);
|
|
2653
2653
|
let a = document.createElement("span");
|
|
2654
2654
|
a.className = "tcw-flyout-name", a.textContent = e.label, r.appendChild(a);
|
|
2655
2655
|
let o = this.config.shortcuts?.[e.value];
|
|
@@ -2711,14 +2711,14 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2711
2711
|
}
|
|
2712
2712
|
placeFlyout(e, t) {
|
|
2713
2713
|
let n = this.host.getBoundingClientRect(), r = t.getBoundingClientRect();
|
|
2714
|
-
e.style.maxHeight = `${Math.max(0, this.host.clientHeight -
|
|
2715
|
-
let i = this.host.clientHeight - e.offsetHeight -
|
|
2714
|
+
e.style.maxHeight = `${Math.max(0, this.host.clientHeight - Fr * 2)}px`;
|
|
2715
|
+
let i = this.host.clientHeight - e.offsetHeight - Fr;
|
|
2716
2716
|
this.host.closest("[dir]")?.getAttribute("dir") === "rtl" ? (e.style.left = "", e.style.right = `${n.right - r.left}px`) : (e.style.right = "", e.style.left = `${r.right - n.left}px`), e.style.top = `${Math.max(0, Math.min(r.top - n.top, i))}px`;
|
|
2717
2717
|
}
|
|
2718
2718
|
scheduleHideFlyout() {
|
|
2719
2719
|
this.cancelHideFlyout(), this.flyoutHideTimer = setTimeout(() => {
|
|
2720
2720
|
this.flyoutHideTimer = null, this.hideFlyout();
|
|
2721
|
-
},
|
|
2721
|
+
}, Pr);
|
|
2722
2722
|
}
|
|
2723
2723
|
cancelHideFlyout() {
|
|
2724
2724
|
this.flyoutHideTimer !== null && (clearTimeout(this.flyoutHideTimer), this.flyoutHideTimer = null);
|
|
@@ -2729,11 +2729,11 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2729
2729
|
update(e) {
|
|
2730
2730
|
this.cursorBtn && this.cursorBtn.classList.toggle("tcw-active", e.activeTool === null);
|
|
2731
2731
|
let t = e.activeTool ?? "";
|
|
2732
|
-
t !== this.fabShows && (this.fabShows = t, this.fab.innerHTML = e.activeTool ?
|
|
2732
|
+
t !== this.fabShows && (this.fabShows = t, this.fab.innerHTML = e.activeTool ? Sn(e.activeTool, 18) : k("penLine", 18)), this.fab.classList.toggle("tcw-active", e.activeTool !== null || e.eraser || e.zoomArea);
|
|
2733
2733
|
let { drawingToolGroups: n } = this.config;
|
|
2734
2734
|
for (let t = 0; t < n.length; t++) {
|
|
2735
2735
|
let r = n[t].tools.some((t) => t.value === e.activeTool);
|
|
2736
|
-
this.groupButtons[t].classList.toggle("tcw-active", r), r && e.activeTool && e.activeTool !== this.groupTools[t] && (this.groupTools[t] = e.activeTool, this.groupIcons[t].innerHTML =
|
|
2736
|
+
this.groupButtons[t].classList.toggle("tcw-active", r), r && e.activeTool && e.activeTool !== this.groupTools[t] && (this.groupTools[t] = e.activeTool, this.groupIcons[t].innerHTML = Sn(e.activeTool, Nr), n[t].tools.length > 1 && this.groupButtons[t].setAttribute("aria-label", `${n[t].label}: ${Lr(n, e.activeTool)}`));
|
|
2737
2737
|
}
|
|
2738
2738
|
if (this.flyoutEl && this.flyoutEl.querySelectorAll(".tcw-flyout-item").forEach((t) => {
|
|
2739
2739
|
let n = t;
|
|
@@ -2753,7 +2753,7 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2753
2753
|
return this.hostEl;
|
|
2754
2754
|
}
|
|
2755
2755
|
tidy() {
|
|
2756
|
-
|
|
2756
|
+
hn(this.el, "tcw-sidebar-divider", "tcw-sidebar-spacer");
|
|
2757
2757
|
}
|
|
2758
2758
|
toggleButton(e, t, n) {
|
|
2759
2759
|
let r = document.createElement("button");
|
|
@@ -2769,17 +2769,17 @@ var Lr = "--tcw-fab-plot-left", Rr = class {
|
|
|
2769
2769
|
destroy() {
|
|
2770
2770
|
this.setOpen(!1), this.hideFlyout(), this.fab.remove(), this.el.remove();
|
|
2771
2771
|
}
|
|
2772
|
-
},
|
|
2772
|
+
}, Br = "button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
|
|
2773
2773
|
function N(e, t) {
|
|
2774
2774
|
if (e.key !== "Tab") return;
|
|
2775
|
-
let n = document.activeElement, r = [...t.querySelectorAll(
|
|
2775
|
+
let n = document.activeElement, r = [...t.querySelectorAll(Br)].filter((e) => e.tabIndex >= 0 && (e.getClientRects().length > 0 || e === n));
|
|
2776
2776
|
if (r.length === 0) return;
|
|
2777
2777
|
let i = r[0], a = r[r.length - 1], o = n instanceof Node && t.contains(n), s = (e, t) => (e.compareDocumentPosition(t) & Node.DOCUMENT_POSITION_PRECEDING) !== 0;
|
|
2778
2778
|
e.shiftKey && (!o || n === i || s(i, n)) ? (e.preventDefault(), a.focus()) : !e.shiftKey && (!o || n === a || s(n, a)) && (e.preventDefault(), i.focus());
|
|
2779
2779
|
}
|
|
2780
2780
|
//#endregion
|
|
2781
2781
|
//#region src/widget/settingsControls.ts
|
|
2782
|
-
function
|
|
2782
|
+
function P(e, t) {
|
|
2783
2783
|
let n = document.createElement("label");
|
|
2784
2784
|
n.className = "tcw-settings-row";
|
|
2785
2785
|
let r = document.createElement("span");
|
|
@@ -2800,19 +2800,19 @@ function Hr(e, t) {
|
|
|
2800
2800
|
n.classList.toggle("tcw-on", e), n.setAttribute("aria-checked", String(e)), t(e);
|
|
2801
2801
|
}), n;
|
|
2802
2802
|
}
|
|
2803
|
-
function
|
|
2803
|
+
function F(e, t, n) {
|
|
2804
2804
|
let r = document.createElement("input");
|
|
2805
2805
|
return r.type = "number", r.className = "tcw-indi-input", r.value = String(e), r.step = String(t.step ?? (Number.isInteger(e) ? 1 : .001)), t.min !== void 0 && (r.min = String(t.min)), t.max !== void 0 && (r.max = String(t.max)), r.addEventListener("change", () => {
|
|
2806
2806
|
if (r.value.trim() === "") return;
|
|
2807
2807
|
let e = Number(r.value);
|
|
2808
|
-
Number.isFinite(e) && (t.min !== void 0 && (e = Math.max(t.min, e)), t.max !== void 0 && (e = Math.min(t.max, e)), r.value = String(e), n(e));
|
|
2808
|
+
Number.isFinite(e) && (t.whole && (e = Math.round(e)), t.min !== void 0 && (e = Math.max(t.min, e)), t.max !== void 0 && (e = Math.min(t.max, e)), r.value = String(e), n(e));
|
|
2809
2809
|
}), r;
|
|
2810
2810
|
}
|
|
2811
|
-
function
|
|
2811
|
+
function I(e, t) {
|
|
2812
2812
|
let n = document.createElement("input");
|
|
2813
|
-
return n.type = "color", n.className = "tcw-indi-color", n.value =
|
|
2813
|
+
return n.type = "color", n.className = "tcw-indi-color", n.value = R(e), n.addEventListener("input", () => t(n.value)), n;
|
|
2814
2814
|
}
|
|
2815
|
-
function
|
|
2815
|
+
function L(e, t, n) {
|
|
2816
2816
|
let r = document.createElement("select");
|
|
2817
2817
|
r.className = "tcw-indi-input tcw-indi-select";
|
|
2818
2818
|
for (let t of e) {
|
|
@@ -2821,7 +2821,7 @@ function I(e, t, n) {
|
|
|
2821
2821
|
}
|
|
2822
2822
|
return r.value = t, r.addEventListener("change", () => n(r.value)), r;
|
|
2823
2823
|
}
|
|
2824
|
-
function
|
|
2824
|
+
function R(e) {
|
|
2825
2825
|
if (typeof e != "string") return "#000000";
|
|
2826
2826
|
let t = e.trim();
|
|
2827
2827
|
if (/^#[0-9a-f]{6}$/i.test(t)) return t.toLowerCase();
|
|
@@ -2834,18 +2834,18 @@ function L(e) {
|
|
|
2834
2834
|
n[3]
|
|
2835
2835
|
].map((e) => Math.min(255, Number(e)).toString(16).padStart(2, "0")).join("")}`;
|
|
2836
2836
|
let r = Ur(t);
|
|
2837
|
-
return r !== null && r !== t ?
|
|
2837
|
+
return r !== null && r !== t ? R(r) : "#000000";
|
|
2838
2838
|
}
|
|
2839
|
-
var
|
|
2839
|
+
var z;
|
|
2840
2840
|
function Ur(e) {
|
|
2841
|
-
if (
|
|
2842
|
-
|
|
2841
|
+
if (z === void 0) try {
|
|
2842
|
+
z = typeof document < "u" ? document.createElement("canvas").getContext("2d") : null;
|
|
2843
2843
|
} catch {
|
|
2844
|
-
|
|
2844
|
+
z = null;
|
|
2845
2845
|
}
|
|
2846
|
-
if (!
|
|
2847
|
-
|
|
2848
|
-
let t = String(
|
|
2846
|
+
if (!z) return null;
|
|
2847
|
+
z.fillStyle = "#010203", z.fillStyle = e;
|
|
2848
|
+
let t = String(z.fillStyle);
|
|
2849
2849
|
return t === "#010203" ? null : t;
|
|
2850
2850
|
}
|
|
2851
2851
|
function Wr(e) {
|
|
@@ -2854,7 +2854,7 @@ function Wr(e) {
|
|
|
2854
2854
|
return t ? Math.max(0, Math.min(1, Number(t[1]))) : 1;
|
|
2855
2855
|
}
|
|
2856
2856
|
function Gr(e, t) {
|
|
2857
|
-
let n =
|
|
2857
|
+
let n = R(e), [r, i, a] = [
|
|
2858
2858
|
1,
|
|
2859
2859
|
3,
|
|
2860
2860
|
5
|
|
@@ -2944,7 +2944,7 @@ function ti(e, t, n, r, i) {
|
|
|
2944
2944
|
let c = document.createElement("span");
|
|
2945
2945
|
c.className = "tcw-color-hex", c.id = `tcw-color-${++Xr}`, s.setAttribute("aria-describedby", c.id);
|
|
2946
2946
|
let l = null, u = (t) => {
|
|
2947
|
-
s.value =
|
|
2947
|
+
s.value = R(t ?? r.start?.()), c.textContent = t ?? i("settings.auto"), a.classList.toggle("tcw-color-auto", t === null), t !== null && r.start && !l ? (l = document.createElement("button"), l.type = "button", l.className = "tcw-color-auto-btn", l.textContent = i("settings.auto"), l.setAttribute("aria-label", `${e}: ${i("settings.auto")}`), l.addEventListener("click", () => {
|
|
2948
2948
|
n(null), s.focus(), u(r.read());
|
|
2949
2949
|
}), o.appendChild(l)) : t === null && l && (l.remove(), l = null);
|
|
2950
2950
|
};
|
|
@@ -2955,14 +2955,14 @@ function ti(e, t, n, r, i) {
|
|
|
2955
2955
|
sync: () => u(r.read())
|
|
2956
2956
|
};
|
|
2957
2957
|
}
|
|
2958
|
-
function
|
|
2958
|
+
function B(e, t, n) {
|
|
2959
2959
|
let r = ei(e), i = document.createElement("button");
|
|
2960
2960
|
return i.type = "button", i.className = `tcw-toggle${t ? " tcw-on" : ""}`, i.setAttribute("role", "switch"), i.setAttribute("aria-checked", String(t)), i.setAttribute("aria-label", e), i.addEventListener("click", () => {
|
|
2961
2961
|
let e = !i.classList.contains("tcw-on");
|
|
2962
2962
|
i.classList.toggle("tcw-on", e), i.setAttribute("aria-checked", String(e)), n(e);
|
|
2963
2963
|
}), r.appendChild(i), r;
|
|
2964
2964
|
}
|
|
2965
|
-
function
|
|
2965
|
+
function V(e, t, n, r) {
|
|
2966
2966
|
let i = ei(e), a = document.createElement("select");
|
|
2967
2967
|
a.className = "tcw-settings-select", a.setAttribute("aria-label", e);
|
|
2968
2968
|
for (let e of n) {
|
|
@@ -3012,7 +3012,7 @@ function ii(e, t, n, r, i, a = "en-US") {
|
|
|
3012
3012
|
}
|
|
3013
3013
|
//#endregion
|
|
3014
3014
|
//#region src/widget/WidgetSettings.ts
|
|
3015
|
-
var
|
|
3015
|
+
var H = [
|
|
3016
3016
|
{
|
|
3017
3017
|
id: "symbol",
|
|
3018
3018
|
icon: "chartType:candlestick"
|
|
@@ -3087,7 +3087,7 @@ var V = [
|
|
|
3087
3087
|
(t[Math.min(e, t.length - 1)] ?? this.tabButtons.find((e) => e.dataset.tab === this.currentTab))?.focus();
|
|
3088
3088
|
}
|
|
3089
3089
|
panelControls() {
|
|
3090
|
-
return this.bodyEl ? [...this.bodyEl.querySelectorAll(
|
|
3090
|
+
return this.bodyEl ? [...this.bodyEl.querySelectorAll(Br)] : [];
|
|
3091
3091
|
}
|
|
3092
3092
|
close() {
|
|
3093
3093
|
this.finish(!0);
|
|
@@ -3131,9 +3131,9 @@ var V = [
|
|
|
3131
3131
|
let e = document.createElement("div");
|
|
3132
3132
|
e.className = "tcw-set-body";
|
|
3133
3133
|
let t = document.createElement("div");
|
|
3134
|
-
t.className = "tcw-set-nav", t.setAttribute("role", "tablist"), t.setAttribute("aria-orientation", "vertical"), t.setAttribute("aria-label", this.t("settings.title")), t.addEventListener("keydown", (e) => this.onTabKey(e)), this.tabButtons =
|
|
3134
|
+
t.className = "tcw-set-nav", t.setAttribute("role", "tablist"), t.setAttribute("aria-orientation", "vertical"), t.setAttribute("aria-label", this.t("settings.title")), t.addEventListener("keydown", (e) => this.onTabKey(e)), this.tabButtons = H.map(({ id: e, icon: t }) => {
|
|
3135
3135
|
let n = document.createElement("button");
|
|
3136
|
-
return n.type = "button", n.className = "tcw-set-tab", n.id = `tcw-set-tab-${this.uid}-${e}`, n.dataset.tab = e, n.setAttribute("role", "tab"), n.setAttribute("aria-controls", `tcw-set-panel-${this.uid}`), n.innerHTML = `${t.startsWith("chartType:") ?
|
|
3136
|
+
return n.type = "button", n.className = "tcw-set-tab", n.id = `tcw-set-tab-${this.uid}-${e}`, n.dataset.tab = e, n.setAttribute("role", "tab"), n.setAttribute("aria-controls", `tcw-set-panel-${this.uid}`), n.innerHTML = `${t.startsWith("chartType:") ? Cn(t.slice(10), 16) : k(t, 16)}<span></span>`, n.querySelector("span").textContent = this.t(`settings.tab.${e}`), n.addEventListener("click", () => this.selectTab(e)), n;
|
|
3137
3137
|
}), t.append(...this.tabButtons);
|
|
3138
3138
|
let n = document.createElement("div");
|
|
3139
3139
|
return n.className = "tcw-modal-body tcw-set-panel", n.id = `tcw-set-panel-${this.uid}`, n.setAttribute("role", "tabpanel"), this.bodyEl = n, e.append(t, n), e;
|
|
@@ -3160,8 +3160,8 @@ var V = [
|
|
|
3160
3160
|
this.currentTab = e, this.markTabs(), this.renderTabContent(), t && this.tabButtons.find((t) => t.dataset.tab === e)?.focus();
|
|
3161
3161
|
}
|
|
3162
3162
|
onTabKey(e) {
|
|
3163
|
-
let t =
|
|
3164
|
-
n < 0 || (e.preventDefault(), this.selectTab(
|
|
3163
|
+
let t = H.findIndex((e) => e.id === this.currentTab), n = e.key === "ArrowDown" || e.key === "ArrowRight" ? (t + 1) % H.length : e.key === "ArrowUp" || e.key === "ArrowLeft" ? (t - 1 + H.length) % H.length : e.key === "Home" ? 0 : e.key === "End" ? H.length - 1 : -1;
|
|
3164
|
+
n < 0 || (e.preventDefault(), this.selectTab(H[n].id, !0));
|
|
3165
3165
|
}
|
|
3166
3166
|
openTemplates() {
|
|
3167
3167
|
let e = this.templateBtn;
|
|
@@ -3213,18 +3213,18 @@ var V = [
|
|
|
3213
3213
|
this.renderLayersTab(this.currentSettings);
|
|
3214
3214
|
break;
|
|
3215
3215
|
case "trading":
|
|
3216
|
-
for (let e of
|
|
3216
|
+
for (let e of Gt) (!e.trading || this.available.trading !== !1) && this.renderLookSection(e);
|
|
3217
3217
|
break;
|
|
3218
3218
|
}
|
|
3219
3219
|
}
|
|
3220
3220
|
renderSymbolTab(e) {
|
|
3221
|
-
this.renderChartTypeSection(), this.addSection(void 0, [
|
|
3221
|
+
this.renderChartTypeSection(), this.addSection(void 0, [B(this.t("settings.mainSeries"), e.mainSeriesVisible, (e) => this.patch({ mainSeriesVisible: e })), B(this.t("settings.extendedHours"), e.extendedHours, (e) => this.patch({ extendedHours: e }))]);
|
|
3222
3222
|
let t = this.t("common.show");
|
|
3223
|
-
this.renderLookSection(
|
|
3223
|
+
this.renderLookSection(Lt), this.available.volume !== !1 && this.renderLookSection(Rt, [B(t, e.volumeVisible, (e) => this.patch({ volumeVisible: e }))]), this.renderLookSection(zt, [B(t, e.highLowLines, (e) => this.patch({ highLowLines: e }))]);
|
|
3224
3224
|
}
|
|
3225
3225
|
renderStatusLineTab(e) {
|
|
3226
|
-
let t = this.available.legend !== !1, n = t ?
|
|
3227
|
-
this.addSection(void 0, [...t ? [
|
|
3226
|
+
let t = this.available.legend !== !1, n = t ? Ht : Ht.filter((e) => !Vt.includes(e));
|
|
3227
|
+
this.addSection(void 0, [...t ? [B(this.t("settings.ohlcLegend"), e.legendVisible, (e) => this.patch({ legendVisible: e }))] : [], ...n.map((e) => this.lookRow(e))]);
|
|
3228
3228
|
}
|
|
3229
3229
|
renderScalesTab(e) {
|
|
3230
3230
|
let t = [
|
|
@@ -3244,25 +3244,25 @@ var V = [
|
|
|
3244
3244
|
value: "indexedTo100",
|
|
3245
3245
|
label: this.t("settings.scale.indexedTo100")
|
|
3246
3246
|
}
|
|
3247
|
-
].filter((e) => e.value !== "logarithmic" || this.available.logScale !== !1), n = this.available.exchangeZone?.(), r =
|
|
3247
|
+
].filter((e) => e.value !== "logarithmic" || this.available.logScale !== !1), n = this.available.exchangeZone?.(), r = lt(e.timezone, Date.now(), this.t("settings.timezone.local"), n === void 0 ? void 0 : {
|
|
3248
3248
|
label: this.t("settings.timezone.exchange"),
|
|
3249
3249
|
zone: n
|
|
3250
3250
|
});
|
|
3251
3251
|
this.addSection(void 0, [
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
...this.available.barCountdown === !1 ? [] : [
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
]), this.addSection(this.t("settings.section.axes"),
|
|
3252
|
+
V(this.t("settings.priceScale"), e.scaleMode, t, (e) => this.patch({ scaleMode: e })),
|
|
3253
|
+
B(this.t("settings.autoScale"), e.autoScale, (e) => this.patch({ autoScale: e })),
|
|
3254
|
+
B(this.t("settings.invertScale"), e.invertScale, (e) => this.patch({ invertScale: e })),
|
|
3255
|
+
B(this.t("settings.leftScale"), e.leftPriceScale, (e) => this.patch({ leftPriceScale: e })),
|
|
3256
|
+
B(this.t("settings.indicatorValues"), e.indicatorValueLabels, (e) => this.patch({ indicatorValueLabels: e })),
|
|
3257
|
+
B(this.t("settings.alignAxisLabels"), e.alignAxisLabels, (e) => this.patch({ alignAxisLabels: e })),
|
|
3258
|
+
...this.available.barCountdown === !1 ? [] : [B(this.t("settings.barCountdown"), e.barCountdown, (e) => this.patch({ barCountdown: e }))],
|
|
3259
|
+
V(this.t("settings.timezone"), e.timezone, r, (e) => this.patch({ timezone: e })),
|
|
3260
|
+
V(this.t("settings.numberLocale"), e.numberLocale, Ln(e.numberLocale), (e) => this.patch({ numberLocale: e }))
|
|
3261
|
+
]), this.addSection(this.t("settings.section.axes"), Ut.map((e) => this.lookRow(e)));
|
|
3262
3262
|
}
|
|
3263
3263
|
renderAppearanceTab(e) {
|
|
3264
|
-
let [t, n, r, ...i] =
|
|
3265
|
-
this.renderLookSection(t), this.renderLookSection(n, [
|
|
3264
|
+
let [t, n, r, ...i] = Wt;
|
|
3265
|
+
this.renderLookSection(t), this.renderLookSection(n, [B(this.t("common.show"), e.gridVisible, (e) => this.patch({ gridVisible: e }))]), this.renderLookSection(r, [V(this.t("settings.crosshairMode"), e.crosshairMode, [
|
|
3266
3266
|
{
|
|
3267
3267
|
label: this.t("settings.crosshair.magnet"),
|
|
3268
3268
|
value: "magnet"
|
|
@@ -3280,10 +3280,10 @@ var V = [
|
|
|
3280
3280
|
}
|
|
3281
3281
|
renderLayersTab(e) {
|
|
3282
3282
|
let t = (e) => `${Math.round(e * 100)}%`, n = (e) => this.t(e);
|
|
3283
|
-
this.addSection(void 0, [
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3283
|
+
this.addSection(void 0, [B(n("settings.volumeProfile"), e.volumeProfileVisible, (e) => this.patch({ volumeProfileVisible: e }))]), this.addSection(void 0, [
|
|
3284
|
+
B(n("settings.marketProfile"), e.marketProfileVisible, (e) => this.patch({ marketProfileVisible: e })),
|
|
3285
|
+
B(n("settings.marketProfileSplit"), e.marketProfileSplit, (e) => this.patch({ marketProfileSplit: e })),
|
|
3286
|
+
B(n("settings.marketProfileLetters"), e.marketProfileLetters, (e) => this.patch({ marketProfileLetters: e })),
|
|
3287
3287
|
ni(n("settings.marketProfileBuckets"), e.marketProfileBuckets, {
|
|
3288
3288
|
min: 8,
|
|
3289
3289
|
max: 200,
|
|
@@ -3294,22 +3294,22 @@ var V = [
|
|
|
3294
3294
|
max: 1,
|
|
3295
3295
|
step: .05
|
|
3296
3296
|
}, (e) => this.patch({ marketProfileOpacity: e }), t)
|
|
3297
|
-
]), this.addSection(void 0, [
|
|
3297
|
+
]), this.addSection(void 0, [B(n("settings.depthHeatmap"), e.depthHeatmapVisible, (e) => this.patch({ depthHeatmapVisible: e })), ni(n("settings.depthHeatmapOpacity"), e.depthHeatmapOpacity, {
|
|
3298
3298
|
min: .1,
|
|
3299
3299
|
max: 1,
|
|
3300
3300
|
step: .05
|
|
3301
3301
|
}, (e) => this.patch({ depthHeatmapOpacity: e }), t)]), this.addSection(void 0, [
|
|
3302
|
-
|
|
3302
|
+
B(n("settings.swingMarkers"), e.pivotMarkersVisible, (e) => this.patch({ pivotMarkersVisible: e })),
|
|
3303
3303
|
ni(n("settings.swingStrength"), e.pivotStrength, {
|
|
3304
3304
|
min: 2,
|
|
3305
3305
|
max: 20,
|
|
3306
3306
|
step: 1
|
|
3307
3307
|
}, (e) => this.patch({ pivotStrength: e })),
|
|
3308
|
-
|
|
3308
|
+
B(n("settings.swingStructure"), e.pivotStructureLabels, (e) => this.patch({ pivotStructureLabels: e }))
|
|
3309
3309
|
]), this.addSection(void 0, [
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3310
|
+
B(n("settings.sessionShading"), e.sessionShadingVisible, (e) => this.patch({ sessionShadingVisible: e })),
|
|
3311
|
+
B(n("settings.periodLevels"), e.periodLevelsVisible, (e) => this.patch({ periodLevelsVisible: e })),
|
|
3312
|
+
V(n("settings.periodLevelsBasis"), e.periodLevelsPeriod, [{
|
|
3313
3313
|
value: "day",
|
|
3314
3314
|
label: n("settings.priorDay")
|
|
3315
3315
|
}, {
|
|
@@ -3338,7 +3338,7 @@ var V = [
|
|
|
3338
3338
|
}] : [], s;
|
|
3339
3339
|
switch (_[e.keys[0]]) {
|
|
3340
3340
|
case "boolean": {
|
|
3341
|
-
i =
|
|
3341
|
+
i = B(t, n() === !0, a);
|
|
3342
3342
|
let e = i.querySelector("button");
|
|
3343
3343
|
s = () => {
|
|
3344
3344
|
let t = n() === !0;
|
|
@@ -3347,13 +3347,13 @@ var V = [
|
|
|
3347
3347
|
break;
|
|
3348
3348
|
}
|
|
3349
3349
|
case "lineStyle":
|
|
3350
|
-
i =
|
|
3350
|
+
i = V(t, r(), [...o, ...this.lineStyles()], (e) => a(e === "" ? null : di(e))), s = () => {
|
|
3351
3351
|
i.querySelector("select").value = r();
|
|
3352
3352
|
};
|
|
3353
3353
|
break;
|
|
3354
3354
|
case "width": {
|
|
3355
3355
|
let e = n(), c = typeof e == "number" && !ai.includes(e) ? [...ai, e].sort((e, t) => e - t) : ai;
|
|
3356
|
-
i =
|
|
3356
|
+
i = V(t, r(), [...o, ...c.map((e) => ({
|
|
3357
3357
|
value: String(e),
|
|
3358
3358
|
label: `${e}px`
|
|
3359
3359
|
}))], (e) => a(e === "" ? null : Number(e))), s = () => {
|
|
@@ -3395,7 +3395,7 @@ var V = [
|
|
|
3395
3395
|
}
|
|
3396
3396
|
renderChartTypeSection() {
|
|
3397
3397
|
if (!this.bodyEl || !this.currentSettings || !this.chartType) return;
|
|
3398
|
-
let e = this.chartType, t = this.currentSettings.chartTypeOptions ?? {}, n =
|
|
3398
|
+
let e = this.chartType, t = this.currentSettings.chartTypeOptions ?? {}, n = Mt.find((t) => t.value === e), r = $r(n ? zn(n, this.t) : e), i = () => this.currentSettings?.chartTypeOptions ?? {}, a = (e, t) => this.patch({ chartTypeOptions: {
|
|
3399
3399
|
...i(),
|
|
3400
3400
|
[e]: t
|
|
3401
3401
|
} }), o = (e, t, n, i) => r.appendChild(ii(this.t(e), t, n, i, this.t, this.currentSettings?.numberLocale || void 0));
|
|
@@ -3418,7 +3418,7 @@ var V = [
|
|
|
3418
3418
|
}, (e) => a("lineBreak", ui(i().lineBreak, "lines", e)));
|
|
3419
3419
|
break;
|
|
3420
3420
|
case "kagi":
|
|
3421
|
-
o("settings.reversal", t.kagi?.reversal ?? null, si, (e) => a("kagi", ui(i().kagi, "reversal", e))), r.appendChild(
|
|
3421
|
+
o("settings.reversal", t.kagi?.reversal ?? null, si, (e) => a("kagi", ui(i().kagi, "reversal", e))), r.appendChild(V(this.t("settings.reversalType"), t.kagi?.reversalType ?? "percent", [{
|
|
3422
3422
|
value: "percent",
|
|
3423
3423
|
label: this.t("settings.reversalType.percent")
|
|
3424
3424
|
}, {
|
|
@@ -3443,7 +3443,7 @@ var V = [
|
|
|
3443
3443
|
break;
|
|
3444
3444
|
default: break;
|
|
3445
3445
|
}
|
|
3446
|
-
for (let t of
|
|
3446
|
+
for (let t of Jt(e)) r.appendChild(this.lookRow(t));
|
|
3447
3447
|
this.bodyEl.appendChild(r);
|
|
3448
3448
|
}
|
|
3449
3449
|
patch(e) {
|
|
@@ -3943,11 +3943,11 @@ function Vi(e) {
|
|
|
3943
3943
|
return t;
|
|
3944
3944
|
}
|
|
3945
3945
|
function Hi(e) {
|
|
3946
|
-
let { ticker: t } =
|
|
3946
|
+
let { ticker: t } = yr(e), n = /[\p{L}\p{N}]/u.exec(t);
|
|
3947
3947
|
return n ? n[0].toUpperCase() : "";
|
|
3948
3948
|
}
|
|
3949
3949
|
function Ui(e, t) {
|
|
3950
|
-
let n =
|
|
3950
|
+
let n = wr(t?.logo);
|
|
3951
3951
|
if (!n || Pi.has(n)) return Gi(e, t);
|
|
3952
3952
|
let r = document.createElement("img");
|
|
3953
3953
|
return r.className = "tcw-ss-badge", r.alt = "", r.width = Mi, r.height = Mi, r.draggable = !1, r.setAttribute("aria-hidden", "true"), r.setAttribute("loading", "lazy"), r.setAttribute("decoding", "async"), r.setAttribute("referrerpolicy", "no-referrer"), r.addEventListener("error", () => {
|
|
@@ -4010,7 +4010,7 @@ function ta(e, t) {
|
|
|
4010
4010
|
function na(e, t) {
|
|
4011
4011
|
let n = document.createElement("span");
|
|
4012
4012
|
n.className = "tcw-ss-symbol", n.dir = "ltr";
|
|
4013
|
-
let { venue: r } =
|
|
4013
|
+
let { venue: r } = yr(e), i = (n, r, i) => {
|
|
4014
4014
|
let a = document.createElement("span");
|
|
4015
4015
|
return a.className = n, a.innerHTML = ea(e, t, r, i), a;
|
|
4016
4016
|
};
|
|
@@ -4140,12 +4140,12 @@ var la = 229, ua = 1, da = class {
|
|
|
4140
4140
|
this.input && (this.input.value = t), t ? (this.filter(), this.searchFn && this.searchNow()) : this.listGiven(), this.input?.focus();
|
|
4141
4141
|
}
|
|
4142
4142
|
learnGiven(e) {
|
|
4143
|
-
let t =
|
|
4143
|
+
let t = hr(e.start.symbols);
|
|
4144
4144
|
this.given = t.names, this.givenInfo = t.info, this.foldedNames = /* @__PURE__ */ new Map();
|
|
4145
4145
|
let n = e.start.current, r = e.kind === "search" ? e.start.currentInfo : null;
|
|
4146
4146
|
if (r && typeof r == "object" && n) {
|
|
4147
|
-
let { description: e, logo: t } =
|
|
4148
|
-
this.givenInfo.set(n,
|
|
4147
|
+
let { description: e, logo: t } = gr(r, n);
|
|
4148
|
+
this.givenInfo.set(n, vr({
|
|
4149
4149
|
symbol: n,
|
|
4150
4150
|
description: e,
|
|
4151
4151
|
logo: t
|
|
@@ -4153,7 +4153,7 @@ var la = 229, ua = 1, da = class {
|
|
|
4153
4153
|
}
|
|
4154
4154
|
}
|
|
4155
4155
|
infoOf(e) {
|
|
4156
|
-
return
|
|
4156
|
+
return vr(this.givenInfo.get(e), this.heard.get(e));
|
|
4157
4157
|
}
|
|
4158
4158
|
build(e) {
|
|
4159
4159
|
let t = document.createElement("div");
|
|
@@ -4276,8 +4276,8 @@ var la = 229, ua = 1, da = class {
|
|
|
4276
4276
|
try {
|
|
4277
4277
|
let r = await t(e, n.signal);
|
|
4278
4278
|
if (n.signal.aborted) return;
|
|
4279
|
-
let i =
|
|
4280
|
-
for (let e of i) this.heard.set(e.symbol,
|
|
4279
|
+
let i = _r(r);
|
|
4280
|
+
for (let e of i) this.heard.set(e.symbol, vr(this.heard.get(e.symbol), e));
|
|
4281
4281
|
this.rows = i.map((e) => ({
|
|
4282
4282
|
symbol: e.symbol,
|
|
4283
4283
|
score: 0,
|
|
@@ -4435,17 +4435,17 @@ var la = 229, ua = 1, da = class {
|
|
|
4435
4435
|
"Bar replay": "toolbar.replay",
|
|
4436
4436
|
Drawing: "hotkeys.group.drawing",
|
|
4437
4437
|
More: "hotkeys.group.more"
|
|
4438
|
-
},
|
|
4438
|
+
}, U = Si, ma = [
|
|
4439
4439
|
{
|
|
4440
4440
|
title: "Search & navigation",
|
|
4441
4441
|
entries: [
|
|
4442
4442
|
{
|
|
4443
|
-
keys: [
|
|
4443
|
+
keys: [U, "K"],
|
|
4444
4444
|
label: "hotkeys.commandPalette",
|
|
4445
4445
|
feature: "hotkeys.commandPalette"
|
|
4446
4446
|
},
|
|
4447
4447
|
{
|
|
4448
|
-
keys: [
|
|
4448
|
+
keys: [U, "P"],
|
|
4449
4449
|
label: "hotkeys.symbolSearch",
|
|
4450
4450
|
feature: "hotkeys.symbolSearch"
|
|
4451
4451
|
},
|
|
@@ -4465,7 +4465,7 @@ var la = 229, ua = 1, da = class {
|
|
|
4465
4465
|
feature: "hotkeys.resetView"
|
|
4466
4466
|
},
|
|
4467
4467
|
{
|
|
4468
|
-
keys: [
|
|
4468
|
+
keys: [U, "S"],
|
|
4469
4469
|
label: "hotkeys.saveLayout",
|
|
4470
4470
|
feature: "hotkeys.save"
|
|
4471
4471
|
},
|
|
@@ -4494,11 +4494,11 @@ var la = 229, ua = 1, da = class {
|
|
|
4494
4494
|
label: "hotkeys.pan"
|
|
4495
4495
|
},
|
|
4496
4496
|
{
|
|
4497
|
-
keys: [
|
|
4497
|
+
keys: [U, "key.drag"],
|
|
4498
4498
|
label: "hotkeys.boxSelect"
|
|
4499
4499
|
},
|
|
4500
4500
|
{
|
|
4501
|
-
keys: [
|
|
4501
|
+
keys: [U, "key.click"],
|
|
4502
4502
|
label: "hotkeys.toggleSelect"
|
|
4503
4503
|
},
|
|
4504
4504
|
{
|
|
@@ -4601,12 +4601,12 @@ var la = 229, ua = 1, da = class {
|
|
|
4601
4601
|
title: "Drawing",
|
|
4602
4602
|
entries: [
|
|
4603
4603
|
{
|
|
4604
|
-
keys: [
|
|
4604
|
+
keys: [U, "Z"],
|
|
4605
4605
|
label: "hotkeys.undo"
|
|
4606
4606
|
},
|
|
4607
4607
|
{
|
|
4608
4608
|
keys: [
|
|
4609
|
-
|
|
4609
|
+
U,
|
|
4610
4610
|
"Shift",
|
|
4611
4611
|
"Z"
|
|
4612
4612
|
],
|
|
@@ -4617,11 +4617,11 @@ var la = 229, ua = 1, da = class {
|
|
|
4617
4617
|
label: "hotkeys.cancelDrawing"
|
|
4618
4618
|
},
|
|
4619
4619
|
{
|
|
4620
|
-
keys: [
|
|
4620
|
+
keys: [U, "C"],
|
|
4621
4621
|
label: "hotkeys.copy"
|
|
4622
4622
|
},
|
|
4623
4623
|
{
|
|
4624
|
-
keys: [
|
|
4624
|
+
keys: [U, "V"],
|
|
4625
4625
|
label: "hotkeys.paste"
|
|
4626
4626
|
},
|
|
4627
4627
|
{
|
|
@@ -4633,12 +4633,12 @@ var la = 229, ua = 1, da = class {
|
|
|
4633
4633
|
label: "hotkeys.drawingSettings"
|
|
4634
4634
|
},
|
|
4635
4635
|
{
|
|
4636
|
-
keys: [
|
|
4636
|
+
keys: [U, "G"],
|
|
4637
4637
|
label: "hotkeys.group"
|
|
4638
4638
|
},
|
|
4639
4639
|
{
|
|
4640
4640
|
keys: [
|
|
4641
|
-
|
|
4641
|
+
U,
|
|
4642
4642
|
"Shift",
|
|
4643
4643
|
"G"
|
|
4644
4644
|
],
|
|
@@ -4646,7 +4646,7 @@ var la = 229, ua = 1, da = class {
|
|
|
4646
4646
|
},
|
|
4647
4647
|
{
|
|
4648
4648
|
keys: [
|
|
4649
|
-
|
|
4649
|
+
U,
|
|
4650
4650
|
"]",
|
|
4651
4651
|
"["
|
|
4652
4652
|
],
|
|
@@ -4654,7 +4654,7 @@ var la = 229, ua = 1, da = class {
|
|
|
4654
4654
|
},
|
|
4655
4655
|
{
|
|
4656
4656
|
keys: [
|
|
4657
|
-
|
|
4657
|
+
U,
|
|
4658
4658
|
"Shift",
|
|
4659
4659
|
"]",
|
|
4660
4660
|
"["
|
|
@@ -4666,7 +4666,7 @@ var la = 229, ua = 1, da = class {
|
|
|
4666
4666
|
label: "hotkeys.finishPath"
|
|
4667
4667
|
},
|
|
4668
4668
|
{
|
|
4669
|
-
keys: [
|
|
4669
|
+
keys: [U, "key.drag"],
|
|
4670
4670
|
label: "hotkeys.copyDrag"
|
|
4671
4671
|
},
|
|
4672
4672
|
{
|
|
@@ -4674,7 +4674,7 @@ var la = 229, ua = 1, da = class {
|
|
|
4674
4674
|
label: "hotkeys.keepAngle"
|
|
4675
4675
|
},
|
|
4676
4676
|
{
|
|
4677
|
-
keys: [
|
|
4677
|
+
keys: [U],
|
|
4678
4678
|
label: "hotkeys.flipMagnet"
|
|
4679
4679
|
},
|
|
4680
4680
|
{
|
|
@@ -5325,7 +5325,7 @@ var Oa = 50, ka = 500, Aa = 60, ja = (e) => typeof e == "string" && e.trim().sli
|
|
|
5325
5325
|
function Ma(e) {
|
|
5326
5326
|
let t = [];
|
|
5327
5327
|
for (let n of e) {
|
|
5328
|
-
let e =
|
|
5328
|
+
let e = mr(n);
|
|
5329
5329
|
if (e && !t.includes(e) && t.push(e), t.length === ka) break;
|
|
5330
5330
|
}
|
|
5331
5331
|
return t;
|
|
@@ -5413,7 +5413,7 @@ var Pa = (e) => ({
|
|
|
5413
5413
|
this.lists.length <= 1 || !this.lists.some((t) => t.id === e) || (this.lists = this.lists.filter((t) => t.id !== e), this.active === e && (this.active = this.lists[0].id), this.changed());
|
|
5414
5414
|
}
|
|
5415
5415
|
add(e, t = this.active) {
|
|
5416
|
-
let n =
|
|
5416
|
+
let n = mr(e), r = this.lists.find((e) => e.id === t);
|
|
5417
5417
|
return !n || !r || r.symbols.includes(n) || r.symbols.length >= ka ? !1 : (this.update(t, (e) => ({
|
|
5418
5418
|
...e,
|
|
5419
5419
|
symbols: [...e.symbols, n]
|
|
@@ -5501,19 +5501,19 @@ var Pa = (e) => ({
|
|
|
5501
5501
|
}
|
|
5502
5502
|
render(e) {
|
|
5503
5503
|
let t = document.createElement("div");
|
|
5504
|
-
t.className = "tcw-syminfo-head", t.append(
|
|
5504
|
+
t.className = "tcw-syminfo-head", t.append(W("div", "tcw-syminfo-symbol", e.symbol)), e.description && t.append(W("div", "tcw-syminfo-desc", e.description)), e.meta && t.append(W("div", "tcw-syminfo-meta", e.meta));
|
|
5505
5505
|
let n = document.createElement("div");
|
|
5506
|
-
if (n.className = "tcw-syminfo-quote", e.price && n.append(
|
|
5507
|
-
let t =
|
|
5506
|
+
if (n.className = "tcw-syminfo-quote", e.price && n.append(W("span", "tcw-syminfo-price", e.price)), e.change) {
|
|
5507
|
+
let t = W("span", "tcw-syminfo-change", e.change.text);
|
|
5508
5508
|
t.classList.add(e.change.up ? "tcw-up" : "tcw-down"), n.append(t);
|
|
5509
5509
|
}
|
|
5510
|
-
let r =
|
|
5510
|
+
let r = W("div", "tcw-syminfo-status", e.status.text);
|
|
5511
5511
|
r.dataset.state = e.status.state;
|
|
5512
5512
|
let i = document.createElement("dl");
|
|
5513
5513
|
i.className = "tcw-syminfo-stats";
|
|
5514
5514
|
for (let t of e.stats) {
|
|
5515
5515
|
let e = document.createElement("div");
|
|
5516
|
-
e.className = "tcw-syminfo-stat", e.append(
|
|
5516
|
+
e.className = "tcw-syminfo-stat", e.append(W("dt", "", t.label), W("dd", "", t.value)), i.append(e);
|
|
5517
5517
|
}
|
|
5518
5518
|
this.bodyEl.replaceChildren(t, n, r, i);
|
|
5519
5519
|
}
|
|
@@ -5522,10 +5522,10 @@ var Pa = (e) => ({
|
|
|
5522
5522
|
this.newsEl.replaceChildren();
|
|
5523
5523
|
return;
|
|
5524
5524
|
}
|
|
5525
|
-
let t =
|
|
5525
|
+
let t = W("div", "tcw-syminfo-news-title", this.t("symbolInfo.news"));
|
|
5526
5526
|
if (e.kind === "loading" || e.kind === "failed" || e.items.length === 0) {
|
|
5527
5527
|
let t = e.kind === "loading" ? "symbolInfo.loading" : e.kind === "failed" ? "symbolInfo.newsFailed" : "symbolInfo.noNews";
|
|
5528
|
-
this.newsEl.replaceChildren(
|
|
5528
|
+
this.newsEl.replaceChildren(W("div", "tcw-syminfo-news-note", this.t(t)));
|
|
5529
5529
|
return;
|
|
5530
5530
|
}
|
|
5531
5531
|
let n = document.createElement("ul");
|
|
@@ -5535,8 +5535,8 @@ var Pa = (e) => ({
|
|
|
5535
5535
|
if (e.className = "tcw-syminfo-news-item", t.url) {
|
|
5536
5536
|
let n = document.createElement("a");
|
|
5537
5537
|
n.href = t.url, n.target = "_blank", n.rel = "noopener noreferrer", n.textContent = t.title, e.append(n);
|
|
5538
|
-
} else e.append(
|
|
5539
|
-
t.meta && e.append(
|
|
5538
|
+
} else e.append(W("span", "", t.title));
|
|
5539
|
+
t.meta && e.append(W("div", "tcw-syminfo-news-meta", t.meta)), n.append(e);
|
|
5540
5540
|
}
|
|
5541
5541
|
this.newsEl.replaceChildren(t, n);
|
|
5542
5542
|
}
|
|
@@ -5544,7 +5544,7 @@ var Pa = (e) => ({
|
|
|
5544
5544
|
this.el.remove();
|
|
5545
5545
|
}
|
|
5546
5546
|
};
|
|
5547
|
-
function
|
|
5547
|
+
function W(e, t, n) {
|
|
5548
5548
|
let r = document.createElement(e);
|
|
5549
5549
|
return t && (r.className = t), r.textContent = n, r;
|
|
5550
5550
|
}
|
|
@@ -6414,7 +6414,7 @@ function Po(e) {
|
|
|
6414
6414
|
for (let t of Object.values(e)) t && typeof t == "object" && Po(t);
|
|
6415
6415
|
return Object.freeze(e);
|
|
6416
6416
|
}
|
|
6417
|
-
var Fo = (e) => typeof e == "string" && Object.prototype.hasOwnProperty.call(ko, e),
|
|
6417
|
+
var Fo = (e) => typeof e == "string" && Object.prototype.hasOwnProperty.call(ko, e), G = (e, t, n) => typeof e == "number" && Number.isFinite(e) && e >= t && e <= n, Io = (e) => typeof e == "string" && e.trim().length > 0 && e.length <= 300 && !/[;{}<>\\]|url\s*\(|expression\s*\(|\/\*/i.test(e) && Lo(e);
|
|
6418
6418
|
function Lo(e) {
|
|
6419
6419
|
let t = 0, n = "";
|
|
6420
6420
|
for (let r of e) if (n) r === n && (n = "");
|
|
@@ -6433,13 +6433,13 @@ function zo(e, t, n) {
|
|
|
6433
6433
|
}
|
|
6434
6434
|
return r;
|
|
6435
6435
|
}
|
|
6436
|
-
function
|
|
6437
|
-
let t = typeof e == "string" ? { preset: e } : e ?? {}, n = Fo(t.preset) ? t.preset : ho, r = ko[n], i = zo(r.radius, t.radius, (e, t) =>
|
|
6436
|
+
function Bo(e) {
|
|
6437
|
+
let t = typeof e == "string" ? { preset: e } : e ?? {}, n = Fo(t.preset) ? t.preset : ho, r = ko[n], i = zo(r.radius, t.radius, (e, t) => G(t, 0, 999)), a = Ro(t.density, [
|
|
6438
6438
|
"compact",
|
|
6439
6439
|
"comfortable",
|
|
6440
6440
|
"spacious",
|
|
6441
6441
|
"airy"
|
|
6442
|
-
]) ? t.density : "comfortable", o = a === "airy" ? "spacious" : a, s = zo(o === "compact" || o === "spacious" ? (r.density ?? Ao)[o] : r.sizes, t.sizes, (e, t) => e === "icon" ?
|
|
6442
|
+
]) ? t.density : "comfortable", o = a === "airy" ? "spacious" : a, s = zo(o === "compact" || o === "spacious" ? (r.density ?? Ao)[o] : r.sizes, t.sizes, (e, t) => e === "icon" ? G(t, 10, 32) : G(t, 16, 80)), c = zo(r.font, t.font, (e, t) => e === "family" || e === "mono" ? Io(t) : e === "size" ? G(t, 11, 20) : e === "weight" || e === "strongWeight" ? G(t, 100, 900) : e === "labelCase" ? t === "none" || t === "uppercase" : G(t, 0, .5)), l = a === "airy" && t.font?.mono === void 0 ? {
|
|
6443
6443
|
...c,
|
|
6444
6444
|
mono: c.family
|
|
6445
6445
|
} : c;
|
|
@@ -6447,12 +6447,12 @@ function G(e) {
|
|
|
6447
6447
|
preset: n,
|
|
6448
6448
|
density: a,
|
|
6449
6449
|
radius: i,
|
|
6450
|
-
components: zo(jo(i, r.components), t.components, (e, t) =>
|
|
6450
|
+
components: zo(jo(i, r.components), t.components, (e, t) => G(t, 0, 999)),
|
|
6451
6451
|
sizes: s,
|
|
6452
6452
|
font: l,
|
|
6453
|
-
borders: zo(r.borders, t.borders, (e, t) => e === "width" ?
|
|
6453
|
+
borders: zo(r.borders, t.borders, (e, t) => e === "width" ? G(t, 0, 4) : typeof t == "boolean"),
|
|
6454
6454
|
shadows: zo(r.shadows, t.shadows, (e, t) => Io(t)),
|
|
6455
|
-
blur:
|
|
6455
|
+
blur: G(t.blur, 0, 40) ? t.blur : r.blur,
|
|
6456
6456
|
active: Ro(t.active, [
|
|
6457
6457
|
"tint",
|
|
6458
6458
|
"solid",
|
|
@@ -6461,11 +6461,11 @@ function G(e) {
|
|
|
6461
6461
|
toolbar: Ro(t.toolbar, ["docked", "floating"]) ? t.toolbar : r.toolbar,
|
|
6462
6462
|
sidebar: Ro(t.sidebar, ["docked", "floating"]) ? t.sidebar : r.sidebar,
|
|
6463
6463
|
intervals: Ro(t.intervals, ["plain", "segmented"]) ? t.intervals : r.intervals,
|
|
6464
|
-
tagRadius:
|
|
6464
|
+
tagRadius: G(t.tagRadius, 0, 999) ? t.tagRadius : r.tagRadius,
|
|
6465
6465
|
scale: typeof t.scale == "number" && Number.isFinite(t.scale) && t.scale >= yo && t.scale <= bo ? t.scale : "auto"
|
|
6466
6466
|
};
|
|
6467
6467
|
}
|
|
6468
|
-
function
|
|
6468
|
+
function Vo(e) {
|
|
6469
6469
|
let t = (e) => `${e}px`, n = e.radius, r = e.components, i = e.sizes, a = e.font;
|
|
6470
6470
|
return {
|
|
6471
6471
|
"--tcw-radius-xs": t(n.xs),
|
|
@@ -6510,14 +6510,14 @@ function Bo(e) {
|
|
|
6510
6510
|
"--tcw-surface-opacity": e.blur > 0 ? "82%" : "100%"
|
|
6511
6511
|
};
|
|
6512
6512
|
}
|
|
6513
|
-
function
|
|
6513
|
+
function Ho(e, t, n = {}) {
|
|
6514
6514
|
let r = n.variables !== !1;
|
|
6515
|
-
for (let [n, i] of Object.entries(
|
|
6515
|
+
for (let [n, i] of Object.entries(Vo(t))) r ? e.style.setProperty(n, i) : e.style.removeProperty(n);
|
|
6516
6516
|
e.dataset.tcwUi = t.preset, e.dataset.tcwActive = t.active, e.dataset.tcwToolbar = t.toolbar, e.dataset.tcwSidebar = t.sidebar, e.dataset.tcwIntervals = t.intervals, e.dataset.tcwSeparators = t.borders.separators ? "on" : "off";
|
|
6517
6517
|
}
|
|
6518
6518
|
//#endregion
|
|
6519
6519
|
//#region src/widget/WidgetObjectTree.ts
|
|
6520
|
-
var
|
|
6520
|
+
var Uo = class {
|
|
6521
6521
|
el;
|
|
6522
6522
|
indicatorsEl;
|
|
6523
6523
|
drawingsEl;
|
|
@@ -6650,7 +6650,7 @@ var Ho = class {
|
|
|
6650
6650
|
if (!e.isConnected) return;
|
|
6651
6651
|
this.renaming = !0;
|
|
6652
6652
|
let i = document.createElement("input");
|
|
6653
|
-
i.type = "text", i.className = "tcw-tree-rename", i.value = t, i.maxLength =
|
|
6653
|
+
i.type = "text", i.className = "tcw-tree-rename", i.value = t, i.maxLength = Wo, i.setAttribute("aria-label", n);
|
|
6654
6654
|
let a = !1, o = (t) => {
|
|
6655
6655
|
if (a) return;
|
|
6656
6656
|
a = !0;
|
|
@@ -6742,7 +6742,7 @@ var Ho = class {
|
|
|
6742
6742
|
let i = document.createElement("button");
|
|
6743
6743
|
return i.type = "button", i.className = `tcw-tree-btn ${n}`.trim(), i.setAttribute("aria-label", t), i.title = t, i.innerHTML = k(e, 14), i.addEventListener("click", r), i;
|
|
6744
6744
|
}
|
|
6745
|
-
},
|
|
6745
|
+
}, Wo = 80, Go = {
|
|
6746
6746
|
trendLine: "Trend Line",
|
|
6747
6747
|
ray: "Ray",
|
|
6748
6748
|
extendedLine: "Extended Line",
|
|
@@ -6789,23 +6789,23 @@ var Ho = class {
|
|
|
6789
6789
|
anchoredText: "Anchored Text",
|
|
6790
6790
|
anchoredNote: "Anchored Note"
|
|
6791
6791
|
};
|
|
6792
|
-
function
|
|
6792
|
+
function Ko(e, t) {
|
|
6793
6793
|
let n = `tool.${e}`, r = t?.(n);
|
|
6794
|
-
return r && r !== n ? r :
|
|
6794
|
+
return r && r !== n ? r : Go[e] ?? e;
|
|
6795
6795
|
}
|
|
6796
6796
|
//#endregion
|
|
6797
6797
|
//#region src/widget/indicatorSettingsTabs.ts
|
|
6798
|
-
var
|
|
6798
|
+
var qo = [
|
|
6799
6799
|
1,
|
|
6800
6800
|
1.5,
|
|
6801
6801
|
2,
|
|
6802
6802
|
3,
|
|
6803
6803
|
4
|
|
6804
|
-
],
|
|
6804
|
+
], Jo = [
|
|
6805
6805
|
"solid",
|
|
6806
6806
|
"dashed",
|
|
6807
6807
|
"dotted"
|
|
6808
|
-
],
|
|
6808
|
+
], Yo = "#4c8dff", Xo = 10, Zo = {
|
|
6809
6809
|
ticks: "toolbar.timeframes.ticks",
|
|
6810
6810
|
seconds: "toolbar.timeframes.seconds",
|
|
6811
6811
|
minutes: "toolbar.timeframes.minutes",
|
|
@@ -6814,26 +6814,26 @@ var Ko = [
|
|
|
6814
6814
|
weeks: "toolbar.timeframes.weeks",
|
|
6815
6815
|
months: "toolbar.timeframes.months"
|
|
6816
6816
|
};
|
|
6817
|
-
function
|
|
6818
|
-
let a =
|
|
6819
|
-
for (let e of [...t.plots].sort((e, t) => e.color - t.color)) a.appendChild(
|
|
6820
|
-
let o =
|
|
6817
|
+
function Qo(e, t, n, r, i) {
|
|
6818
|
+
let a = rs();
|
|
6819
|
+
for (let e of [...t.plots].sort((e, t) => e.color - t.color)) a.appendChild($o(e, t, n, r));
|
|
6820
|
+
let o = L(qo.map((e) => ({
|
|
6821
6821
|
value: String(e),
|
|
6822
6822
|
label: `${e} px`
|
|
6823
6823
|
})), String(t.lineWidth), (e) => n.lineWidth(Number(e)));
|
|
6824
|
-
if (o.dataset.role = "line-width", a.appendChild(
|
|
6825
|
-
let e =
|
|
6824
|
+
if (o.dataset.role = "line-width", a.appendChild(P(r("indicatorSettings.lineWidth"), o)), t.scale && n.scale) {
|
|
6825
|
+
let e = L([{
|
|
6826
6826
|
value: "right",
|
|
6827
6827
|
label: r("indicatorSettings.scale.right")
|
|
6828
6828
|
}, {
|
|
6829
6829
|
value: "left",
|
|
6830
6830
|
label: r("indicatorSettings.scale.left")
|
|
6831
6831
|
}], t.scale, (e) => n.scale?.(e === "left" ? "left" : "right"));
|
|
6832
|
-
e.dataset.role = "scale", a.appendChild(
|
|
6832
|
+
e.dataset.role = "scale", a.appendChild(P(r("indicatorSettings.scale"), e));
|
|
6833
6833
|
}
|
|
6834
|
-
e.appendChild(a), t.levels && n.levels && e.appendChild(
|
|
6834
|
+
e.appendChild(a), t.levels && n.levels && e.appendChild(es([...t.levels], n.levels, r, i));
|
|
6835
6835
|
}
|
|
6836
|
-
function
|
|
6836
|
+
function $o(e, t, n, r) {
|
|
6837
6837
|
let i = t.plotStyles[e.key] ?? {}, a = document.createElement("div");
|
|
6838
6838
|
a.className = "tcw-settings-row tcw-indi-plot", a.dataset.plot = e.key;
|
|
6839
6839
|
let o = document.createElement("label");
|
|
@@ -6845,11 +6845,11 @@ function Qo(e, t, n, r) {
|
|
|
6845
6845
|
let l = document.createElement("span");
|
|
6846
6846
|
l.className = "tcw-indi-plot-controls";
|
|
6847
6847
|
let u = (e, r) => {
|
|
6848
|
-
let i =
|
|
6848
|
+
let i = I(t.colors[e] ?? t.colors[0] ?? Yo, (t) => n.color(e, t));
|
|
6849
6849
|
return i.setAttribute("aria-label", r), i;
|
|
6850
6850
|
};
|
|
6851
6851
|
if (e.tone !== void 0 && e.downColor !== void 0 ? l.append(u(e.color, `${e.title} ${r("indicatorSettings.up")}`), u(e.downColor, `${e.title} ${r("indicatorSettings.down")}`)) : l.appendChild(u(e.color, e.title)), (e.kind ?? "line") === "line" || e.kind === "step") {
|
|
6852
|
-
let t =
|
|
6852
|
+
let t = L(Jo.map((e) => ({
|
|
6853
6853
|
value: e,
|
|
6854
6854
|
label: r(`drawingSettings.lineStyle.${e}`)
|
|
6855
6855
|
})), i.lineStyle ?? "solid", (t) => n.plot(e.key, { lineStyle: t }));
|
|
@@ -6857,21 +6857,21 @@ function Qo(e, t, n, r) {
|
|
|
6857
6857
|
}
|
|
6858
6858
|
return a.append(o, l), a;
|
|
6859
6859
|
}
|
|
6860
|
-
function
|
|
6861
|
-
let i =
|
|
6860
|
+
function es(e, t, n, r) {
|
|
6861
|
+
let i = rs(), a = e, o = () => {
|
|
6862
6862
|
let e = document.createElement("div");
|
|
6863
6863
|
e.className = "tcw-settings-section-title", e.textContent = n("indicatorSettings.tab.levels");
|
|
6864
6864
|
let t = a.map((e, t) => c(e, t)), r = document.createElement("button");
|
|
6865
6865
|
r.type = "button", r.className = "tcw-reset-link tcw-indi-add", r.textContent = `+ ${n("indicatorSettings.addLevel")}`, r.addEventListener("click", () => {
|
|
6866
6866
|
let e = a[a.length - 1];
|
|
6867
|
-
s([...a, e === void 0 ? 0 : e +
|
|
6867
|
+
s([...a, e === void 0 ? 0 : e + Xo]);
|
|
6868
6868
|
let t = i.querySelectorAll(".tcw-indi-level input");
|
|
6869
6869
|
t[t.length - 1]?.focus();
|
|
6870
|
-
}), i.replaceChildren(e, ...a.length === 0 ? [
|
|
6870
|
+
}), i.replaceChildren(e, ...a.length === 0 ? [is(n("indicatorSettings.noLevels"))] : t, r);
|
|
6871
6871
|
}, s = (e) => {
|
|
6872
6872
|
a = e, t([...e]), o();
|
|
6873
6873
|
}, c = (e, o) => {
|
|
6874
|
-
let c =
|
|
6874
|
+
let c = F(e, { step: "any" }, (e) => {
|
|
6875
6875
|
a = a.map((t, n) => n === o ? e : t), t([...a]);
|
|
6876
6876
|
});
|
|
6877
6877
|
c.id = `tcw-indi-level-${r}-${o}`;
|
|
@@ -6890,7 +6890,7 @@ function $o(e, t, n, r) {
|
|
|
6890
6890
|
};
|
|
6891
6891
|
return o(), i;
|
|
6892
6892
|
}
|
|
6893
|
-
function
|
|
6893
|
+
function ts(e, t, n, r) {
|
|
6894
6894
|
let i = new Map(Re.map((e) => {
|
|
6895
6895
|
let n = t?.[e], r = Array.isArray(n) ? n : [1, Le[e]];
|
|
6896
6896
|
return [e, {
|
|
@@ -6905,11 +6905,11 @@ function es(e, t, n, r) {
|
|
|
6905
6905
|
n ? (i > 1 || o < Le[t]) && (e[t] = [i, o]) : e[t] = !1;
|
|
6906
6906
|
}
|
|
6907
6907
|
n(Object.keys(e).length > 0 ? e : null);
|
|
6908
|
-
}, o =
|
|
6909
|
-
for (let e of Re) o.appendChild(
|
|
6908
|
+
}, o = rs();
|
|
6909
|
+
for (let e of Re) o.appendChild(ns(e, i.get(e), a, r));
|
|
6910
6910
|
e.appendChild(o);
|
|
6911
6911
|
}
|
|
6912
|
-
function
|
|
6912
|
+
function ns(e, t, n, r) {
|
|
6913
6913
|
let i = document.createElement("div");
|
|
6914
6914
|
i.className = "tcw-settings-row tcw-indi-unit", i.dataset.unit = e;
|
|
6915
6915
|
let a = document.createElement("label");
|
|
@@ -6917,18 +6917,18 @@ function ts(e, t, n, r) {
|
|
|
6917
6917
|
let o = document.createElement("input");
|
|
6918
6918
|
o.type = "checkbox", o.checked = t.on;
|
|
6919
6919
|
let s = document.createElement("span");
|
|
6920
|
-
s.className = "tcw-settings-label", s.textContent = r(
|
|
6920
|
+
s.className = "tcw-settings-label", s.textContent = r(Zo[e]), a.append(o, s), i.appendChild(a);
|
|
6921
6921
|
let c = [];
|
|
6922
6922
|
if (e !== "ticks") {
|
|
6923
6923
|
let a = (i, a) => {
|
|
6924
|
-
let o =
|
|
6924
|
+
let o = F(t[i], {
|
|
6925
6925
|
min: 1,
|
|
6926
6926
|
max: Le[e],
|
|
6927
6927
|
step: 1
|
|
6928
6928
|
}, (e) => {
|
|
6929
6929
|
t[i] = Math.round(e), o.value = String(t[i]), n();
|
|
6930
6930
|
});
|
|
6931
|
-
return o.setAttribute("aria-label", `${r(
|
|
6931
|
+
return o.setAttribute("aria-label", `${r(Zo[e])}: ${r(a)}`), o.disabled = !t.on, c.push(o), o;
|
|
6932
6932
|
}, o = document.createElement("span");
|
|
6933
6933
|
o.className = "tcw-indi-range";
|
|
6934
6934
|
let s = document.createElement("span");
|
|
@@ -6940,17 +6940,17 @@ function ts(e, t, n, r) {
|
|
|
6940
6940
|
n();
|
|
6941
6941
|
}), i;
|
|
6942
6942
|
}
|
|
6943
|
-
function
|
|
6943
|
+
function rs() {
|
|
6944
6944
|
let e = document.createElement("div");
|
|
6945
6945
|
return e.className = "tcw-settings-section", e;
|
|
6946
6946
|
}
|
|
6947
|
-
function
|
|
6947
|
+
function is(e) {
|
|
6948
6948
|
let t = document.createElement("div");
|
|
6949
6949
|
return t.className = "tcw-settings-label", t.textContent = e, t;
|
|
6950
6950
|
}
|
|
6951
6951
|
//#endregion
|
|
6952
6952
|
//#region src/widget/WidgetIndicatorSettings.ts
|
|
6953
|
-
var
|
|
6953
|
+
var as = 1, os = 1.5, ss = {
|
|
6954
6954
|
visible: !0,
|
|
6955
6955
|
lineStyle: "solid"
|
|
6956
6956
|
}, cs = (e, t) => JSON.stringify(e) === JSON.stringify(t), ls = (e) => JSON.parse(JSON.stringify(e));
|
|
@@ -6985,7 +6985,7 @@ var fs = class {
|
|
|
6985
6985
|
tab = "inputs";
|
|
6986
6986
|
tabButtons = [];
|
|
6987
6987
|
returnFocus = null;
|
|
6988
|
-
uid =
|
|
6988
|
+
uid = as++;
|
|
6989
6989
|
t;
|
|
6990
6990
|
constructor(e, t, n) {
|
|
6991
6991
|
this.callbacks = t, this.t = n ?? ((e) => d[e]), this.backdrop = document.createElement("div"), this.backdrop.className = "tcw-modal-backdrop", this.backdrop.hidden = !0;
|
|
@@ -7096,7 +7096,7 @@ var fs = class {
|
|
|
7096
7096
|
renderBody() {
|
|
7097
7097
|
this.bodyEl.replaceChildren();
|
|
7098
7098
|
let e = this.target;
|
|
7099
|
-
e && (this.tab === "style" ? this.renderStyle(e) : this.tab === "visibility" ?
|
|
7099
|
+
e && (this.tab === "style" ? this.renderStyle(e) : this.tab === "visibility" ? ts(this.bodyEl, this.look.intervals, (e) => this.setIntervals(e), this.t) : this.renderInputs());
|
|
7100
7100
|
}
|
|
7101
7101
|
currentValue(e) {
|
|
7102
7102
|
if (e in this.draft) return this.draft[e];
|
|
@@ -7109,25 +7109,41 @@ var fs = class {
|
|
|
7109
7109
|
renderInputs() {
|
|
7110
7110
|
let e = document.createElement("div");
|
|
7111
7111
|
e.className = "tcw-settings-section";
|
|
7112
|
-
let t =
|
|
7112
|
+
let t = Ge({
|
|
7113
|
+
defaultConfig: this.target.defaults,
|
|
7114
|
+
inputs: this.target.inputs
|
|
7115
|
+
});
|
|
7113
7116
|
t.length === 0 && e.appendChild(this.note(this.t("indicatorSettings.noInputs")));
|
|
7114
7117
|
for (let n of t) e.appendChild(this.fieldRow(n));
|
|
7115
7118
|
this.bodyEl.appendChild(e);
|
|
7116
7119
|
}
|
|
7117
7120
|
fieldRow(e) {
|
|
7118
|
-
let t =
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7121
|
+
let t = e.name, n = this.currentValue(t), r;
|
|
7122
|
+
switch (e.kind) {
|
|
7123
|
+
case "source":
|
|
7124
|
+
r = this.sourceControl(t, String(n ?? "close"));
|
|
7125
|
+
break;
|
|
7126
|
+
case "choice":
|
|
7127
|
+
r = this.choiceControl(t, e.options ?? [], n);
|
|
7128
|
+
break;
|
|
7129
|
+
case "boolean":
|
|
7130
|
+
r = Hr(!!n, (e) => this.setValue(t, e));
|
|
7131
|
+
break;
|
|
7132
|
+
case "int":
|
|
7133
|
+
case "number":
|
|
7134
|
+
r = F(Number(n), {
|
|
7135
|
+
min: e.min,
|
|
7136
|
+
max: e.max,
|
|
7137
|
+
step: e.step,
|
|
7138
|
+
whole: e.kind === "int"
|
|
7139
|
+
}, (e) => this.setValue(t, e));
|
|
7140
|
+
break;
|
|
7141
|
+
case "color":
|
|
7142
|
+
r = I(String(n), (e) => this.setValue(t, e));
|
|
7143
|
+
break;
|
|
7144
|
+
default: r = this.textControl(t, String(n ?? ""));
|
|
7145
|
+
}
|
|
7146
|
+
return P(e.label ?? fo(t, this.t) ?? us(t), r);
|
|
7131
7147
|
}
|
|
7132
7148
|
sourceControl(e, t) {
|
|
7133
7149
|
let n = document.createElement("select");
|
|
@@ -7160,7 +7176,7 @@ var fs = class {
|
|
|
7160
7176
|
}
|
|
7161
7177
|
renderStyle(e) {
|
|
7162
7178
|
let t = e.instanceId, n = () => this.target === e, r = (e) => n() && this.callbacks.onStyle?.(t, e), i = (e) => n() && this.callbacks.onLevels?.(t, e), a = (e) => n() && this.callbacks.onScale?.(t, e);
|
|
7163
|
-
|
|
7179
|
+
Qo(this.bodyEl, {
|
|
7164
7180
|
plots: e.colors && this.callbacks.onStyle ? e.plots ?? [] : [],
|
|
7165
7181
|
colors: this.look.colors,
|
|
7166
7182
|
plotStyles: this.look.plots,
|
|
@@ -7226,7 +7242,7 @@ var fs = class {
|
|
|
7226
7242
|
let e = this.target;
|
|
7227
7243
|
if (!e) return;
|
|
7228
7244
|
let t = Object.fromEntries(Object.entries(this.currentParams()).filter(([t, n]) => !cs(n, e.defaults[t]) && !(typeof n == "string" && ge(n)))), n = {};
|
|
7229
|
-
|
|
7245
|
+
Je(this.look.colors) || (n.colors = [...this.look.colors]), this.look.lineWidth !== os && (n.lineWidths = [this.look.lineWidth]), Object.keys(this.look.plots).length > 0 && (n.plots = ls(this.look.plots)), this.callbacks.onSaveDefault?.(e.indicatorId, {
|
|
7230
7246
|
params: t,
|
|
7231
7247
|
style: n
|
|
7232
7248
|
});
|
|
@@ -7602,7 +7618,7 @@ var Is = {
|
|
|
7602
7618
|
}
|
|
7603
7619
|
}, Rs = (e) => typeof e == "object" && !!e && !Array.isArray(e);
|
|
7604
7620
|
function zs(e) {
|
|
7605
|
-
return e === "local" ||
|
|
7621
|
+
return e === "local" || st(e) !== null;
|
|
7606
7622
|
}
|
|
7607
7623
|
function Bs(e) {
|
|
7608
7624
|
try {
|
|
@@ -7612,7 +7628,7 @@ function Bs(e) {
|
|
|
7612
7628
|
}
|
|
7613
7629
|
}
|
|
7614
7630
|
function Vs(e, t) {
|
|
7615
|
-
let n =
|
|
7631
|
+
let n = Ft[e];
|
|
7616
7632
|
if (e === "chartTypeOptions") return Rs(t) ? ye(t) : void 0;
|
|
7617
7633
|
if (typeof t != typeof n) return;
|
|
7618
7634
|
if (typeof t == "number") {
|
|
@@ -7629,7 +7645,7 @@ function Vs(e, t) {
|
|
|
7629
7645
|
function K(e, t = js) {
|
|
7630
7646
|
if (!Rs(e)) return {};
|
|
7631
7647
|
let n = {};
|
|
7632
|
-
for (let r of Object.keys(
|
|
7648
|
+
for (let r of Object.keys(Ft)) {
|
|
7633
7649
|
if (t.has(r) || !Object.prototype.hasOwnProperty.call(e, r)) continue;
|
|
7634
7650
|
let i = Vs(r, e[r]);
|
|
7635
7651
|
i !== void 0 && (n[r] = i);
|
|
@@ -7691,7 +7707,7 @@ function Zs(e) {
|
|
|
7691
7707
|
}
|
|
7692
7708
|
function Qs(e) {
|
|
7693
7709
|
let { overrides: t } = ve(e);
|
|
7694
|
-
return Object.fromEntries(Object.entries(t).filter(([e, t]) => t !== null &&
|
|
7710
|
+
return Object.fromEntries(Object.entries(t).filter(([e, t]) => t !== null && Yt.includes(e)));
|
|
7695
7711
|
}
|
|
7696
7712
|
function $s() {
|
|
7697
7713
|
try {
|
|
@@ -8187,7 +8203,7 @@ function jc(e, t, n, r) {
|
|
|
8187
8203
|
let i = [], a = Ac();
|
|
8188
8204
|
a.appendChild(Mc(t.style(), n, i, r));
|
|
8189
8205
|
let o = Oc.filter((e) => t.defs[e]?.kind === "choice");
|
|
8190
|
-
o.length > 0 && a.appendChild(J(r("drawingSettings.lineEnds"), ...o.map((e) => Y(
|
|
8206
|
+
o.length > 0 && a.appendChild(J(r("drawingSettings.lineEnds"), ...o.map((e) => Y(L([{
|
|
8191
8207
|
value: "normal",
|
|
8192
8208
|
label: r("drawingSettings.lineEnd.normal")
|
|
8193
8209
|
}, {
|
|
@@ -8203,31 +8219,31 @@ function jc(e, t, n, r) {
|
|
|
8203
8219
|
for (let [a, o] of Object.entries(t.defs)) o.kind === "levels" && e.appendChild(Fc(a, o, t, n, i, r));
|
|
8204
8220
|
}
|
|
8205
8221
|
function Mc(e, t, n, r) {
|
|
8206
|
-
let i = Y(
|
|
8222
|
+
let i = Y(I(e.color, (e) => {
|
|
8207
8223
|
t.style({ color: e });
|
|
8208
8224
|
for (let t of n) t(e);
|
|
8209
|
-
}), r("drawingSettings.color")), a = Y(
|
|
8225
|
+
}), r("drawingSettings.color")), a = Y(L(xc.map((e) => ({
|
|
8210
8226
|
value: String(e),
|
|
8211
8227
|
label: `${e} px`
|
|
8212
|
-
})), String(e.lineWidth), (e) => t.style({ lineWidth: Number(e) })), r("drawingSettings.lineWidth")), o = Y(
|
|
8228
|
+
})), String(e.lineWidth), (e) => t.style({ lineWidth: Number(e) })), r("drawingSettings.lineWidth")), o = Y(L(Sc.map((e) => ({
|
|
8213
8229
|
value: e,
|
|
8214
8230
|
label: r(`drawingSettings.lineStyle.${e}`)
|
|
8215
8231
|
})), e.lineStyle, (e) => t.style({ lineStyle: e })), r("drawingSettings.lineStyle"));
|
|
8216
8232
|
return J(r("drawingSettings.line"), i, a, o);
|
|
8217
8233
|
}
|
|
8218
8234
|
function Nc(e, t, n, r) {
|
|
8219
|
-
let i = e.fillColor ?? Gr(e.color, Dc), a =
|
|
8235
|
+
let i = e.fillColor ?? Gr(e.color, Dc), a = R(i), o = Wr(i), s = e.fillColor !== void 0, c = () => {
|
|
8220
8236
|
s = !0, t.style({
|
|
8221
8237
|
fillColor: Gr(a, o),
|
|
8222
8238
|
fillOpacity: o
|
|
8223
8239
|
});
|
|
8224
|
-
}, l = Y(
|
|
8240
|
+
}, l = Y(I(a, (e) => {
|
|
8225
8241
|
a = e, c();
|
|
8226
8242
|
}), r("drawingSettings.fill"));
|
|
8227
8243
|
n.push((e) => {
|
|
8228
|
-
s || (a =
|
|
8244
|
+
s || (a = R(e), l.value = a);
|
|
8229
8245
|
});
|
|
8230
|
-
let u = Y(
|
|
8246
|
+
let u = Y(F(Math.round(o * 100), {
|
|
8231
8247
|
min: 0,
|
|
8232
8248
|
max: 100,
|
|
8233
8249
|
step: 5
|
|
@@ -8240,18 +8256,18 @@ function Pc(e, t, n, r, i) {
|
|
|
8240
8256
|
let a = kc(i, e, t.label), o = n[e];
|
|
8241
8257
|
switch (t.kind) {
|
|
8242
8258
|
case "boolean": return Vr(a, !!o, (t) => r.options({ [e]: t }));
|
|
8243
|
-
case "number": return
|
|
8259
|
+
case "number": return P(a, F(Number(o), {
|
|
8244
8260
|
min: t.min,
|
|
8245
8261
|
max: t.max,
|
|
8246
8262
|
step: t.step
|
|
8247
8263
|
}, (t) => r.options({ [e]: t })));
|
|
8248
|
-
case "choice": return
|
|
8264
|
+
case "choice": return P(a, L(t.choices.map((t) => ({
|
|
8249
8265
|
value: t.value,
|
|
8250
8266
|
label: kc(i, `${e}.${t.value}`, t.label)
|
|
8251
8267
|
})), String(o), (t) => r.options({ [e]: t })));
|
|
8252
8268
|
case "text": {
|
|
8253
8269
|
let t = document.createElement("input");
|
|
8254
|
-
return t.type = "text", t.className = "tcw-indi-input", t.value = String(o ?? ""), t.addEventListener("change", () => r.options({ [e]: t.value })),
|
|
8270
|
+
return t.type = "text", t.className = "tcw-indi-input", t.value = String(o ?? ""), t.addEventListener("change", () => r.options({ [e]: t.value })), P(a, t);
|
|
8255
8271
|
}
|
|
8256
8272
|
}
|
|
8257
8273
|
}
|
|
@@ -8272,15 +8288,15 @@ function Fc(e, t, n, r, i, a) {
|
|
|
8272
8288
|
...e,
|
|
8273
8289
|
visible: d.checked
|
|
8274
8290
|
} : e)));
|
|
8275
|
-
let f = Y(
|
|
8291
|
+
let f = Y(F(e.value, { step: .001 }, (e) => l(c().map((n, r) => r === t ? {
|
|
8276
8292
|
...n,
|
|
8277
8293
|
value: e
|
|
8278
|
-
} : n))), a("drawingSettings.levelValue") + s), p = Y(
|
|
8294
|
+
} : n))), a("drawingSettings.levelValue") + s), p = Y(I(e.color ?? n.style().color, (e) => l(c().map((n, r) => r === t ? {
|
|
8279
8295
|
...n,
|
|
8280
8296
|
color: e
|
|
8281
8297
|
} : n))), a("drawingSettings.levelColor") + s);
|
|
8282
8298
|
i.push((e) => {
|
|
8283
|
-
c()[t]?.color === void 0 && (p.value =
|
|
8299
|
+
c()[t]?.color === void 0 && (p.value = R(e));
|
|
8284
8300
|
});
|
|
8285
8301
|
let m = document.createElement("button");
|
|
8286
8302
|
m.type = "button", m.className = "tcw-level-remove", m.setAttribute("aria-label", a("drawingSettings.removeLevel") + s), m.innerHTML = k("x", 12), m.addEventListener("click", () => {
|
|
@@ -8376,33 +8392,33 @@ function Gc(e, t, n, r = !1) {
|
|
|
8376
8392
|
function Kc(e, t, n, r, i, a, o = !1) {
|
|
8377
8393
|
let s = Ac(), c = document.createElement("textarea");
|
|
8378
8394
|
c.className = "tcw-indi-input tcw-drawing-text", c.rows = 3, c.value = t.text ?? "", c.addEventListener("input", () => n({ text: c.value }));
|
|
8379
|
-
let l =
|
|
8395
|
+
let l = P(r("drawingSettings.text"), c);
|
|
8380
8396
|
l.classList.add("tcw-text-row"), s.appendChild(l);
|
|
8381
|
-
let u = Y(
|
|
8397
|
+
let u = Y(L(Cc.map((e) => ({
|
|
8382
8398
|
value: String(e),
|
|
8383
8399
|
label: `${e} px`
|
|
8384
8400
|
})), String(t.fontSize ?? i?.fontSize ?? wc), (e) => n({ fontSize: Number(e) })), r("drawingSettings.fontSize"));
|
|
8385
|
-
s.appendChild(J(r("drawingSettings.fontSize"), u, Gc(r("drawingSettings.bold"), t.bold === !0, (e) => n({ bold: e })), Gc(r("drawingSettings.italic"), t.italic === !0, (e) => n({ italic: e })))), s.appendChild(J(r("drawingSettings.textColor"), Y(
|
|
8401
|
+
s.appendChild(J(r("drawingSettings.fontSize"), u, Gc(r("drawingSettings.bold"), t.bold === !0, (e) => n({ bold: e })), Gc(r("drawingSettings.italic"), t.italic === !0, (e) => n({ italic: e })))), s.appendChild(J(r("drawingSettings.textColor"), Y(I(t.textColor ?? a ?? t.color, (e) => n({ textColor: e })), r("drawingSettings.textColor")))), e.appendChild(s), i && e.appendChild(Jc(t, n, r, i)), o && e.appendChild(qc(t, n, r));
|
|
8386
8402
|
}
|
|
8387
8403
|
function qc(e, t, n) {
|
|
8388
8404
|
let r = Ac();
|
|
8389
|
-
return r.appendChild(J(n("drawingSettings.align"), Y(
|
|
8405
|
+
return r.appendChild(J(n("drawingSettings.align"), Y(L(Uc.map((e) => ({
|
|
8390
8406
|
value: e,
|
|
8391
8407
|
label: n(`drawingSettings.align.${e}`)
|
|
8392
|
-
})), e.textAlign ?? "center", (e) => t({ textAlign: e })), n("drawingSettings.align")))), r.appendChild(J(n("drawingSettings.vAlign"), Y(
|
|
8408
|
+
})), e.textAlign ?? "center", (e) => t({ textAlign: e })), n("drawingSettings.align")))), r.appendChild(J(n("drawingSettings.vAlign"), Y(L(Wc.map((e) => ({
|
|
8393
8409
|
value: e,
|
|
8394
8410
|
label: n(`drawingSettings.vAlign.${e}`)
|
|
8395
8411
|
})), e.textVAlign ?? "top", (e) => t({ textVAlign: e })), n("drawingSettings.vAlign")))), r;
|
|
8396
8412
|
}
|
|
8397
8413
|
function Jc(e, t, n, r) {
|
|
8398
8414
|
let i = Ac();
|
|
8399
|
-
i.appendChild(J(n("drawingSettings.align"), Y(
|
|
8415
|
+
i.appendChild(J(n("drawingSettings.align"), Y(L(Uc.map((e) => ({
|
|
8400
8416
|
value: e,
|
|
8401
8417
|
label: n(`drawingSettings.align.${e}`)
|
|
8402
8418
|
})), e.textAlign ?? "left", (e) => t({ textAlign: e })), n("drawingSettings.align"))));
|
|
8403
8419
|
let a = e.fillColor ?? Gr(e.color, Dc);
|
|
8404
|
-
i.appendChild(J(n("drawingSettings.background"), Gc(n("drawingSettings.background"), e.textBackground ?? r.box, (e) => t({ textBackground: e }), !0), Y(
|
|
8405
|
-
let o = e.textWrap ?? r.wrap, s = o > 0 ? o : r.wrap > 0 ? r.wrap : zc, c = o > 0, l = Y(
|
|
8420
|
+
i.appendChild(J(n("drawingSettings.background"), Gc(n("drawingSettings.background"), e.textBackground ?? r.box, (e) => t({ textBackground: e }), !0), Y(I(a, (e) => t({ fillColor: Gr(e, Wr(a)) })), n("drawingSettings.backgroundColor")))), i.appendChild(J(n("drawingSettings.border"), Gc(n("drawingSettings.border"), e.textBorder ?? r.border, (e) => t({ textBorder: e }), !0), Y(I(e.borderColor ?? e.color, (e) => t({ borderColor: e })), n("drawingSettings.borderColor"))));
|
|
8421
|
+
let o = e.textWrap ?? r.wrap, s = o > 0 ? o : r.wrap > 0 ? r.wrap : zc, c = o > 0, l = Y(F(s, {
|
|
8406
8422
|
min: Bc,
|
|
8407
8423
|
max: Vc,
|
|
8408
8424
|
step: Hc
|
|
@@ -8430,7 +8446,7 @@ function Yc(e, t, n, r) {
|
|
|
8430
8446
|
}), e.appendChild(i);
|
|
8431
8447
|
}
|
|
8432
8448
|
function Xc(e, t, n) {
|
|
8433
|
-
let r = t.roundPrice ?? ((e) => e), i = t.priceStep?.(), a =
|
|
8449
|
+
let r = t.roundPrice ?? ((e) => e), i = t.priceStep?.(), a = F(r(e), { step: i !== void 0 && i > 0 ? i : "any" }, (e) => {
|
|
8434
8450
|
let t = r(e);
|
|
8435
8451
|
a.value = String(t), n(t);
|
|
8436
8452
|
});
|
|
@@ -8553,7 +8569,7 @@ var Zc = 12, Qc = "t:", $c = 1, el = class {
|
|
|
8553
8569
|
}, this.t);
|
|
8554
8570
|
break;
|
|
8555
8571
|
case "visibility":
|
|
8556
|
-
|
|
8572
|
+
ts(this.bodyEl, this.intervals, (e) => this.setIntervals(e), this.t);
|
|
8557
8573
|
break;
|
|
8558
8574
|
default: jc(this.bodyEl, {
|
|
8559
8575
|
style: () => this.style,
|
|
@@ -10068,11 +10084,11 @@ var nu = 0, ru = class {
|
|
|
10068
10084
|
this.el.remove();
|
|
10069
10085
|
}
|
|
10070
10086
|
check() {
|
|
10071
|
-
let e =
|
|
10087
|
+
let e = Qn(this.input.value) !== null;
|
|
10072
10088
|
!e && this.input.value.trim() !== "" ? this.input.setAttribute("aria-invalid", "true") : this.input.removeAttribute("aria-invalid"), this.hint.textContent = e || this.input.value.trim() === "" ? this.labels.hint : this.labels.invalid;
|
|
10073
10089
|
}
|
|
10074
10090
|
apply() {
|
|
10075
|
-
let e =
|
|
10091
|
+
let e = Qn(this.input.value);
|
|
10076
10092
|
if (e && this.onApply(e)) {
|
|
10077
10093
|
this.close();
|
|
10078
10094
|
return;
|
|
@@ -10354,7 +10370,7 @@ var Ou = ["date", "range"], ku = 1, Au = class {
|
|
|
10354
10370
|
});
|
|
10355
10371
|
let c = document.createElement("div");
|
|
10356
10372
|
c.className = "tcw-goto-fields", c.id = `tcw-goto-panel-${this.uid}`, c.setAttribute("role", "tabpanel");
|
|
10357
|
-
let l = new
|
|
10373
|
+
let l = new Tt(e.calendar, this.locale(), (e) => this.pickDay(e));
|
|
10358
10374
|
l.element.classList.add("tcw-goto-calendar"), s.append(c, l.element, this.buildFooter(e)), r.append(i, this.buildTabs(e), s), t.appendChild(r), this.layer().appendChild(t), this.backdrop = t, this.fieldsEl = c, this.month = l;
|
|
10359
10375
|
}
|
|
10360
10376
|
buildTabs(e) {
|
|
@@ -10981,11 +10997,11 @@ function sd(e, t, n, r) {
|
|
|
10981
10997
|
opacity: 1
|
|
10982
10998
|
}, o = [];
|
|
10983
10999
|
for (let e of i) {
|
|
10984
|
-
if (!
|
|
11000
|
+
if (!Xe(e, { plots: r })) continue;
|
|
10985
11001
|
let i = t[e.key];
|
|
10986
11002
|
typeof i != "number" || !Number.isFinite(i) || o.push({
|
|
10987
11003
|
value: i,
|
|
10988
|
-
color: n.length ?
|
|
11004
|
+
color: n.length ? Ye(e, a, t) : null
|
|
10989
11005
|
});
|
|
10990
11006
|
}
|
|
10991
11007
|
return o;
|
|
@@ -10999,13 +11015,13 @@ function ld(e) {
|
|
|
10999
11015
|
}), cd.set(e, t)), t;
|
|
11000
11016
|
}
|
|
11001
11017
|
function ud(e, t = "en-US") {
|
|
11002
|
-
return Math.abs(e) >= 1e6 ? ld(t).format(e) : ce(e,
|
|
11018
|
+
return Math.abs(e) >= 1e6 ? ld(t).format(e) : ce(e, qe(e), t);
|
|
11003
11019
|
}
|
|
11004
11020
|
//#endregion
|
|
11005
11021
|
//#region src/widget/compareLegend.ts
|
|
11006
11022
|
var dd = 2, fd = 2;
|
|
11007
11023
|
function pd(e, t = "en-US") {
|
|
11008
|
-
return ce(e, Math.max(dd,
|
|
11024
|
+
return ce(e, Math.max(dd, qe(e)), t);
|
|
11009
11025
|
}
|
|
11010
11026
|
function md(e, t = "en-US") {
|
|
11011
11027
|
return `${wl(ce(Math.abs(e), fd, t), e, ce(0, fd, t))}%`;
|
|
@@ -11325,7 +11341,7 @@ var wd = class {
|
|
|
11325
11341
|
if (!this.open) return;
|
|
11326
11342
|
if (this.bodyEl.replaceChildren(), !e.ohlc) {
|
|
11327
11343
|
let e = document.createElement("div");
|
|
11328
|
-
e.className = "tcw-datawin-empty", e.textContent = this.t(
|
|
11344
|
+
e.className = "tcw-datawin-empty", e.textContent = this.t(Dt() ? "dataWindow.touch" : "dataWindow.hover"), this.bodyEl.appendChild(e);
|
|
11329
11345
|
return;
|
|
11330
11346
|
}
|
|
11331
11347
|
let t = this.callbacks.formatPrice, n = e.ohlc;
|
|
@@ -11697,7 +11713,7 @@ var hf = 4, gf = 1, _f = 7, vf = 17, yf = 3, bf = 150, xf = 5e3, Sf = 8, Cf = 6e
|
|
|
11697
11713
|
"barCountdown",
|
|
11698
11714
|
"indicatorValueLabels",
|
|
11699
11715
|
"alignAxisLabels"
|
|
11700
|
-
], Af =
|
|
11716
|
+
], Af = Yt.filter((e) => _[e] !== "color"), jf = () => typeof document < "u" && document.hidden, Mf = 200;
|
|
11701
11717
|
function Nf(e) {
|
|
11702
11718
|
if (!e.feed) return e;
|
|
11703
11719
|
if (e.adapter) throw TypeError("A widget takes an adapter or a feed, not both");
|
|
@@ -11873,23 +11889,23 @@ var Pf = class {
|
|
|
11873
11889
|
constructor(e, t = {}) {
|
|
11874
11890
|
let r = Nf(t);
|
|
11875
11891
|
this.options = r, this.replayStep = r.replayStep ?? "auto";
|
|
11876
|
-
let i =
|
|
11892
|
+
let i = hr(r.symbols ?? Pt);
|
|
11877
11893
|
this.symbols = i.names, this.symbolCatalog = i.info;
|
|
11878
11894
|
let a = r.chartOptions;
|
|
11879
11895
|
if (this.settingsState = {
|
|
11880
|
-
...
|
|
11896
|
+
...Ft,
|
|
11881
11897
|
...a?.crosshair?.mode ? { crosshairMode: a.crosshair.mode } : {},
|
|
11882
11898
|
...a?.logScale && a.features?.logScale !== !1 ? {
|
|
11883
11899
|
logScale: !0,
|
|
11884
11900
|
scaleMode: "logarithmic"
|
|
11885
11901
|
} : {},
|
|
11886
11902
|
...a?.numberLocale ? { numberLocale: a.numberLocale } : {},
|
|
11887
|
-
...a?.timeZone == null ? {} : { timezone:
|
|
11903
|
+
...a?.timeZone == null ? {} : { timezone: ct(a.timeZone) },
|
|
11888
11904
|
...a?.leftPriceScale === void 0 ? {} : { leftPriceScale: a.leftPriceScale },
|
|
11889
11905
|
...a?.highLowLines === void 0 ? {} : { highLowLines: a.highLowLines },
|
|
11890
11906
|
...a?.extendedHours === void 0 ? {} : { extendedHours: a.extendedHours },
|
|
11891
11907
|
...a?.chartTypeOptions ? { chartTypeOptions: ye(a.chartTypeOptions) } : {}
|
|
11892
|
-
}, this.t = p(m(r.locale, r.messages)), this.featureState =
|
|
11908
|
+
}, this.t = p(m(r.locale, r.messages)), this.featureState = cn(r), r.persistLayouts) {
|
|
11893
11909
|
let e = r.persistLayouts === !0 ? {} : r.persistLayouts;
|
|
11894
11910
|
this.layoutKeyPrefix = e.keyPrefix ?? "tcw:layout:", this.layoutDebounceMs = e.debounceMs ?? 1500;
|
|
11895
11911
|
}
|
|
@@ -11932,8 +11948,8 @@ var Pf = class {
|
|
|
11932
11948
|
barCountdown: u.barCountdown !== !1,
|
|
11933
11949
|
indicatorValueLabels: u.indicatorValueLabels === !0,
|
|
11934
11950
|
alignAxisLabels: u.alignAxisLabels !== !1
|
|
11935
|
-
}, this.settingsState = { ...this.settingsDefaults }, this.timeframes =
|
|
11936
|
-
let e =
|
|
11951
|
+
}, this.settingsState = { ...this.settingsDefaults }, this.timeframes = $n(qn(r.timeframes, u.timeframes), this.customTimeframes.list(), u.timeframes), !this.timeframes.some((e) => this.timeframeFavorites.has(e))) {
|
|
11952
|
+
let e = Jn(this.timeframes, u.defaultTimeframeFavorites, !!r.timeframes?.length);
|
|
11937
11953
|
for (let t of e) this.timeframeFavorites.add(t);
|
|
11938
11954
|
}
|
|
11939
11955
|
let f = r.timeframe ?? "5m", ee = !u.timeframes?.length || u.timeframes.includes(f) ? f : this.timeframes[0] ?? f;
|
|
@@ -11951,11 +11967,11 @@ var Pf = class {
|
|
|
11951
11967
|
stayInDrawing: !1,
|
|
11952
11968
|
connectionState: r.adapter ? "connecting" : "disconnected",
|
|
11953
11969
|
connectionMessage: r.adapter ? this.t("status.connecting") : ""
|
|
11954
|
-
},
|
|
11970
|
+
}, yn(), this.root = document.createElement("div"), this.root.className = "tcw-root", this.root.dataset.tcwTheme = c ? "dark" : "light";
|
|
11955
11971
|
let g = r.dir === "ltr" || r.dir === "rtl" ? r.dir : Gf(r.locale) ? "rtl" : "ltr";
|
|
11956
11972
|
this.root.dir = g, this.portal.dir = g, e.appendChild(this.root), this.tooltip = new Ku(this.root), this.portal.className = "tcw-root tcw-portal", this.portal.dataset.tcwTheme = this.root.dataset.tcwTheme, this.stopKeyboardInset = Cu([this.root, this.portal]), this.stopNarrow = wu(this.root, (e) => {
|
|
11957
11973
|
this.toolbar?.fit(), e || this.sidebar?.closeOverlay(), this.syncRail();
|
|
11958
|
-
}), this.ui =
|
|
11974
|
+
}), this.ui = Bo(r.ui), this.uiVariables = r.ui !== void 0, this.uiScale = this.scaleNow(), this.applyLookTokens(), typeof ResizeObserver < "u" && (this.scaleObserver = new ResizeObserver(() => this.fitScale()), this.scaleObserver.observe(this.root)), this.markSwitchedOff(), this.stopFormControls = jt([this.root, this.portal], {
|
|
11959
11975
|
layer: this.overlayHost,
|
|
11960
11976
|
labels: () => ({
|
|
11961
11977
|
prevMonth: this.t("calendar.prevMonth"),
|
|
@@ -11963,11 +11979,11 @@ var Pf = class {
|
|
|
11963
11979
|
today: this.t("calendar.today")
|
|
11964
11980
|
}),
|
|
11965
11981
|
locale: () => this.intlLocale()
|
|
11966
|
-
}), this.toolbar = new
|
|
11982
|
+
}), this.toolbar = new Ar(this.root, {
|
|
11967
11983
|
symbols: this.symbols,
|
|
11968
11984
|
timeframes: this.timeframeMenu(),
|
|
11969
11985
|
timeframeFavorites: this.pinnedTimeframes(),
|
|
11970
|
-
chartTypes: r.chartTypes ?
|
|
11986
|
+
chartTypes: r.chartTypes ? Mt.filter((e) => r.chartTypes.includes(e.value)) : Mt
|
|
11971
11987
|
}, {
|
|
11972
11988
|
onSymbolClick: () => this.handleSymbolClick(),
|
|
11973
11989
|
onSymbolInfo: () => this.toggleSymbolInfo(),
|
|
@@ -11994,8 +12010,8 @@ var Pf = class {
|
|
|
11994
12010
|
onToggleFullscreen: typeof document < "u" && document.fullscreenEnabled ? () => this.toggleFullscreen() : void 0
|
|
11995
12011
|
}, this.t, this.overlayHost);
|
|
11996
12012
|
let _ = document.createElement("div");
|
|
11997
|
-
_.className = "tcw-body", r.drawingFavorites && this.favoritesStore.seedDefaults(r.drawingFavorites), this.sidebar = new
|
|
11998
|
-
drawingToolGroups:
|
|
12013
|
+
_.className = "tcw-body", r.drawingFavorites && this.favoritesStore.seedDefaults(r.drawingFavorites), this.sidebar = new zr(_, {
|
|
12014
|
+
drawingToolGroups: Bn(Nt, this.t),
|
|
11999
12015
|
favorites: this.favoritesStore.list(),
|
|
12000
12016
|
shortcuts: Ya()
|
|
12001
12017
|
}, {
|
|
@@ -12099,7 +12115,7 @@ var Pf = class {
|
|
|
12099
12115
|
now: () => this.clockNow(),
|
|
12100
12116
|
options: () => ({
|
|
12101
12117
|
current: this.settingsState.timezone,
|
|
12102
|
-
list:
|
|
12118
|
+
list: lt(this.settingsState.timezone, Date.now(), this.t("settings.timezone.local"), this.exchangeChoice())
|
|
12103
12119
|
}),
|
|
12104
12120
|
onPick: (e) => this.changeSettings({ timezone: e })
|
|
12105
12121
|
},
|
|
@@ -12393,14 +12409,14 @@ var Pf = class {
|
|
|
12393
12409
|
...this.chartMenuContext(s),
|
|
12394
12410
|
...o ? { pane: this.chart.getPaneScale(o) } : {}
|
|
12395
12411
|
};
|
|
12396
|
-
this.menuPane = o ?? null, this.openChartMenu(
|
|
12412
|
+
this.menuPane = o ?? null, this.openChartMenu(gn(Sl(t, c, this.t), rn, this.featureState), n, r, {
|
|
12397
12413
|
area: t,
|
|
12398
12414
|
price: s,
|
|
12399
12415
|
time: a
|
|
12400
12416
|
});
|
|
12401
12417
|
}), this.chart.on("priceAxisAdd", (e) => {
|
|
12402
12418
|
if (!this.featureState["menu.priceAxisAdd"]) return;
|
|
12403
|
-
let { price: t, x: n, y: r } = e.payload, i = this.chart.roundPrice(t), a =
|
|
12419
|
+
let { price: t, x: n, y: r } = e.payload, i = this.chart.roundPrice(t), a = gn(gl(this.chartMenuContext(i), this.t), rn, this.featureState);
|
|
12404
12420
|
this.openChartMenu(a, n, r, {
|
|
12405
12421
|
area: "priceAxisAdd",
|
|
12406
12422
|
price: i
|
|
@@ -12521,7 +12537,7 @@ var Pf = class {
|
|
|
12521
12537
|
onIntervals: (e, t) => this.chart.setIndicatorIntervals(e, t),
|
|
12522
12538
|
onSaveDefault: (e, t) => this.saveIndicatorDefault(e, t),
|
|
12523
12539
|
onClose: () => this.chart.endIndicatorEdit()
|
|
12524
|
-
}, this.t), this.objectTree = new
|
|
12540
|
+
}, this.t), this.objectTree = new Uo(this.root, {
|
|
12525
12541
|
onClose: () => this.closePanelByHand("objectTree"),
|
|
12526
12542
|
onRemoveIndicator: (e) => this.handleRemoveIndicator(e),
|
|
12527
12543
|
onConfigureIndicator: (e) => this.openIndicatorSettings(e),
|
|
@@ -12640,7 +12656,7 @@ var Pf = class {
|
|
|
12640
12656
|
e && this.importState(e);
|
|
12641
12657
|
}
|
|
12642
12658
|
setSymbols(e) {
|
|
12643
|
-
let t =
|
|
12659
|
+
let t = hr(e);
|
|
12644
12660
|
this.symbols = t.names, this.symbolCatalog = t.info;
|
|
12645
12661
|
let n = this.watchlistStore;
|
|
12646
12662
|
n && this.watchlistFromSymbols && n.replace(n.getLists().map((e) => e.id === "default" ? {
|
|
@@ -12652,14 +12668,14 @@ var Pf = class {
|
|
|
12652
12668
|
return this.symbols.map((e) => this.symbolCatalog.get(e) ?? e);
|
|
12653
12669
|
}
|
|
12654
12670
|
chartSymbolInfo() {
|
|
12655
|
-
let e = this.chart.getSymbolInfo(), t = e && e !== this.chartInfoAtSwitch ? e :
|
|
12656
|
-
return t ?
|
|
12671
|
+
let e = this.chart.getSymbolInfo(), t = e && e !== this.chartInfoAtSwitch ? e : xr(this.state.symbol, e);
|
|
12672
|
+
return t ? gr(t, this.state.symbol) : null;
|
|
12657
12673
|
}
|
|
12658
12674
|
displayInfo() {
|
|
12659
|
-
return
|
|
12675
|
+
return vr(this.symbolCatalog.get(this.state.symbol), this.chartSymbolInfo()) ?? null;
|
|
12660
12676
|
}
|
|
12661
12677
|
refreshSymbolTitle() {
|
|
12662
|
-
this.toolbar?.setSymbolDescription(
|
|
12678
|
+
this.toolbar?.setSymbolDescription(Sr(this.displayInfo()));
|
|
12663
12679
|
}
|
|
12664
12680
|
getWatchlists() {
|
|
12665
12681
|
return this.watchlistStore?.getLists() ?? [];
|
|
@@ -12857,7 +12873,7 @@ var Pf = class {
|
|
|
12857
12873
|
if (this.chart.setDataTimeframe(e), this.options.resampleTimeframes !== !1) {
|
|
12858
12874
|
if (!this.baseSeries) {
|
|
12859
12875
|
let e = this.chart.getData();
|
|
12860
|
-
e.length > 0 && (this.baseSeries = e, this.baseTimeframeMs =
|
|
12876
|
+
e.length > 0 && (this.baseSeries = e, this.baseTimeframeMs = nt(e));
|
|
12861
12877
|
}
|
|
12862
12878
|
await this.switchLocalTimeframe();
|
|
12863
12879
|
}
|
|
@@ -12876,7 +12892,7 @@ var Pf = class {
|
|
|
12876
12892
|
return this.chart;
|
|
12877
12893
|
}
|
|
12878
12894
|
setUI(e) {
|
|
12879
|
-
this.ui =
|
|
12895
|
+
this.ui = Bo(e), this.uiVariables = !0, this.uiScale = this.scaleNow(), this.applyLookTokens(), this.applyChartShapes(), this.applyLegendFont(), this.applyChartLook();
|
|
12880
12896
|
}
|
|
12881
12897
|
scaleNow() {
|
|
12882
12898
|
if (this.ui.scale !== "auto" && this.ui.scale !== void 0) return this.ui.scale;
|
|
@@ -12886,8 +12902,8 @@ var Pf = class {
|
|
|
12886
12902
|
applyLookTokens() {
|
|
12887
12903
|
let e = So(this.ui, this.uiScale);
|
|
12888
12904
|
for (let t of [this.root, this.portal]) {
|
|
12889
|
-
if (
|
|
12890
|
-
let n =
|
|
12905
|
+
if (Ho(t, e, { variables: this.uiVariables }), this.uiVariables) continue;
|
|
12906
|
+
let n = Vo(e);
|
|
12891
12907
|
for (let e of nf) this.uiScale === 1 ? t.style.removeProperty(e) : t.style.setProperty(e, n[e]);
|
|
12892
12908
|
}
|
|
12893
12909
|
}
|
|
@@ -12903,7 +12919,7 @@ var Pf = class {
|
|
|
12903
12919
|
}
|
|
12904
12920
|
}
|
|
12905
12921
|
getUI() {
|
|
12906
|
-
return
|
|
12922
|
+
return Bo({ ...this.ui });
|
|
12907
12923
|
}
|
|
12908
12924
|
applyLegendFont() {
|
|
12909
12925
|
this.chart.setLegend({
|
|
@@ -12945,7 +12961,7 @@ var Pf = class {
|
|
|
12945
12961
|
if (!this.destroyed) {
|
|
12946
12962
|
this.destroyed = !0, this.stopKeyboardInset?.(), this.stopKeyboardInset = null, this.stopNarrow?.(), this.dockObserver?.disconnect(), this.scaleObserver?.disconnect(), this.inlineText?.close(), this.stopNarrow = null, this.stopFormControls?.(), this.stopFormControls = null, this.boundGlobalKeydown && document.removeEventListener("keydown", this.boundGlobalKeydown), document.removeEventListener("fullscreenchange", this.onFullscreenChange), this.unregisterKeys(), this.tooltip.destroy(), this.legendFrame && cancelAnimationFrame(this.legendFrame), this.indicatorLegend?.destroy(), this.portal.remove(), document.fullscreenElement === this.root && document.exitFullscreen().catch(() => {}), this.flushActiveLayout(), this.commandPalette?.destroy(), this.symbolSearch?.destroy(), this.hotkeySheet?.destroy(), this.replayPollInterval && clearInterval(this.replayPollInterval), this.replayShade?.remove(), this.replayBar?.destroy(), this.dragDrop?.detach(), this.alertsPanel?.destroy(), this.objectTree?.destroy(), this.indicatorSettings?.destroy(), this.indicatorPicker?.destroy(), this.drawingStyle?.destroy(), this.drawingSettings?.destroy(), this.drawingMenu?.destroy(), this.clearMenu?.destroy(), this.cancelTextPrompt?.(), this.selectionToolbar?.destroy(), this.selectionToolbarFrame !== null && cancelAnimationFrame(this.selectionToolbarFrame), this.chartMenu?.destroy(), this.legendMenu?.destroy();
|
|
12947
12963
|
for (let e of this.hostMenus) e.destroy();
|
|
12948
|
-
this.hostMenus.clear(), this.templatePrompt?.destroy(), this.chartTemplatePrompt?.destroy(), this.drawingTemplatePrompt?.destroy(), this.intervalInput?.destroy(), this.markerTip?.remove(), this.layoutSession?.destroy(), this.layoutsUI?.destroy(), this.settingsListeners.clear(), this.accountPanel?.destroy(), this.orderTicket?.destroy(), this.accountFrame && cancelAnimationFrame(this.accountFrame), this.bracketBar?.destroy(), this.alertNotifier?.destroy(), this.depthLadder?.destroy(), this.dataWindow?.destroy(), this.watchlistInterval && clearInterval(this.watchlistInterval), this.marketTimer && clearInterval(this.marketTimer), this.clockTimer && clearInterval(this.clockTimer), this.onPageShown && document.removeEventListener("visibilitychange", this.onPageShown), this.onPageShown = null, this.chartNav?.destroy(), this.symbolInfoPanel?.destroy(), this.dock?.destroy(), this.stopQuotes?.(), this.stopQuotes = null, this.watchlist?.destroy(), this.toolbar?.destroy(), this.sidebar?.destroy(), this.settings?.destroy(), this.statusBar?.destroy(), this.goToDate?.destroy(), this.loading.destroy(), this.historyPill.destroy(), this.chart.destroy(), this.root.remove(),
|
|
12964
|
+
this.hostMenus.clear(), this.templatePrompt?.destroy(), this.chartTemplatePrompt?.destroy(), this.drawingTemplatePrompt?.destroy(), this.intervalInput?.destroy(), this.markerTip?.remove(), this.layoutSession?.destroy(), this.layoutsUI?.destroy(), this.settingsListeners.clear(), this.accountPanel?.destroy(), this.orderTicket?.destroy(), this.accountFrame && cancelAnimationFrame(this.accountFrame), this.bracketBar?.destroy(), this.alertNotifier?.destroy(), this.depthLadder?.destroy(), this.dataWindow?.destroy(), this.watchlistInterval && clearInterval(this.watchlistInterval), this.marketTimer && clearInterval(this.marketTimer), this.clockTimer && clearInterval(this.clockTimer), this.onPageShown && document.removeEventListener("visibilitychange", this.onPageShown), this.onPageShown = null, this.chartNav?.destroy(), this.symbolInfoPanel?.destroy(), this.dock?.destroy(), this.stopQuotes?.(), this.stopQuotes = null, this.watchlist?.destroy(), this.toolbar?.destroy(), this.sidebar?.destroy(), this.settings?.destroy(), this.statusBar?.destroy(), this.goToDate?.destroy(), this.loading.destroy(), this.historyPill.destroy(), this.chart.destroy(), this.root.remove(), bn();
|
|
12949
12965
|
}
|
|
12950
12966
|
}
|
|
12951
12967
|
handleSymbolClick() {
|
|
@@ -12988,12 +13004,12 @@ var Pf = class {
|
|
|
12988
13004
|
timeframeForPreset(e) {
|
|
12989
13005
|
let t = this.state.timeframe, n = this.chart.getData();
|
|
12990
13006
|
if (n.length < 2) return t;
|
|
12991
|
-
let r = se(n), i = n[n.length - 1].time * r, a = e === "All" ? n[0].time * r :
|
|
13007
|
+
let r = se(n), i = n[n.length - 1].time * r, a = e === "All" ? n[0].time * r : Ze(e, i, this.displayTimezone());
|
|
12992
13008
|
if (a === null) return t;
|
|
12993
13009
|
let o = n.length - 1;
|
|
12994
13010
|
for (; o > 0 && n[o - 1].time * r >= a;) o--;
|
|
12995
13011
|
let s = this.displayTimezone();
|
|
12996
|
-
return
|
|
13012
|
+
return ir({
|
|
12997
13013
|
dayShare: n.slice(-Mf).some((e) => {
|
|
12998
13014
|
let t = e.time * r, n = new Date(t + he(s, t) * 6e4).getUTCDay();
|
|
12999
13015
|
return n === 0 || n === 6;
|
|
@@ -13007,11 +13023,11 @@ var Pf = class {
|
|
|
13007
13023
|
});
|
|
13008
13024
|
}
|
|
13009
13025
|
canShowTimeframe(e) {
|
|
13010
|
-
if (this.adapter) return
|
|
13026
|
+
if (this.adapter) return Qe(this.adapter, e);
|
|
13011
13027
|
if (this.options.resampleTimeframes === !1) return !1;
|
|
13012
13028
|
let t = this.chart.getData();
|
|
13013
13029
|
if (t.length < 2) return !1;
|
|
13014
|
-
let n = this.baseSeries ? this.baseTimeframeMs :
|
|
13030
|
+
let n = this.baseSeries ? this.baseTimeframeMs : nt(t);
|
|
13015
13031
|
return !(n > 0) || C(e) >= n;
|
|
13016
13032
|
}
|
|
13017
13033
|
toggleFullscreen() {
|
|
@@ -13165,11 +13181,11 @@ var Pf = class {
|
|
|
13165
13181
|
}] : [];
|
|
13166
13182
|
});
|
|
13167
13183
|
if (i.length === 0) return;
|
|
13168
|
-
let a =
|
|
13184
|
+
let a = gn(ul({
|
|
13169
13185
|
selected: i,
|
|
13170
13186
|
canConfigure: this.drawingSettings !== null,
|
|
13171
13187
|
canAlert: this.chart.canAddDrawingAlert(e)
|
|
13172
|
-
}, this.t),
|
|
13188
|
+
}, this.t), an, this.featureState), o = i.map((e) => e.id), s = r.get(e), c = s ? this.options.drawingMenuItems?.({
|
|
13173
13189
|
id: e,
|
|
13174
13190
|
type: s.type,
|
|
13175
13191
|
selected: o
|
|
@@ -13268,7 +13284,7 @@ var Pf = class {
|
|
|
13268
13284
|
};
|
|
13269
13285
|
}
|
|
13270
13286
|
timezoneChoices() {
|
|
13271
|
-
return
|
|
13287
|
+
return lt(this.settingsState.timezone, Date.now(), this.t("settings.timezone.local"), this.exchangeChoice()).map(({ value: e, label: t }) => ({
|
|
13272
13288
|
value: e,
|
|
13273
13289
|
label: t
|
|
13274
13290
|
}));
|
|
@@ -13286,7 +13302,7 @@ var Pf = class {
|
|
|
13286
13302
|
let t = this.featureState;
|
|
13287
13303
|
this.featureState = {
|
|
13288
13304
|
...t,
|
|
13289
|
-
...
|
|
13305
|
+
...sn(e)
|
|
13290
13306
|
};
|
|
13291
13307
|
let n = (e) => t[e] !== this.featureState[e];
|
|
13292
13308
|
this.markSwitchedOff(), this.closeSwitchedOff((e) => t[e] && !this.featureState[e]), n("selectionToolbar") && this.updateSelectionToolbar(), n("indicatorLegend") && (this.chart.setPaneTitlesVisible(!this.featureState.indicatorLegend), this.scheduleLegend()), n("menu.priceAxisAdd") && this.chart.setFeatures({ priceAxisAddButton: this.priceAxisAddDefault && this.featureState["menu.priceAxisAdd"] }), n("dragDropImport") && (this.featureState.dragDropImport ? this.dragDrop?.attach() : this.dragDrop?.detach()), [
|
|
@@ -13373,7 +13389,7 @@ var Pf = class {
|
|
|
13373
13389
|
}
|
|
13374
13390
|
}
|
|
13375
13391
|
markSwitchedOff() {
|
|
13376
|
-
let e =
|
|
13392
|
+
let e = ln(this.featureState);
|
|
13377
13393
|
for (let t of [this.root, this.portal]) e ? t.dataset.tcwOff = e : delete t.dataset.tcwOff;
|
|
13378
13394
|
this.toolbar?.setSymbolSearch(this.featureState.symbolSearch), this.toolbar?.tidy(), this.sidebar?.tidy(), this.syncRail(), this.statusBar?.fit();
|
|
13379
13395
|
}
|
|
@@ -13382,8 +13398,8 @@ var Pf = class {
|
|
|
13382
13398
|
let t = this.toolbar, n = t.addHostButton(e);
|
|
13383
13399
|
return t.tidy(), {
|
|
13384
13400
|
element: n,
|
|
13385
|
-
setActive: (t) =>
|
|
13386
|
-
setText: (t) => void
|
|
13401
|
+
setActive: (t) => jr(n, t, e.toggle === !0),
|
|
13402
|
+
setText: (t) => void Mr(n, e.label, t),
|
|
13387
13403
|
remove: () => {
|
|
13388
13404
|
n.remove(), t.tidy();
|
|
13389
13405
|
}
|
|
@@ -13413,7 +13429,7 @@ var Pf = class {
|
|
|
13413
13429
|
});
|
|
13414
13430
|
return r.setAttribute("aria-haspopup", "menu"), r.setAttribute("aria-expanded", "false"), t.tidy(), {
|
|
13415
13431
|
element: r,
|
|
13416
|
-
setText: (t) => void
|
|
13432
|
+
setText: (t) => void Mr(r, e.label, t),
|
|
13417
13433
|
remove: () => {
|
|
13418
13434
|
n.destroy(), this.hostMenus.delete(n), r.remove(), t.tidy();
|
|
13419
13435
|
}
|
|
@@ -13425,7 +13441,7 @@ var Pf = class {
|
|
|
13425
13441
|
let n = t.addHostButton(e);
|
|
13426
13442
|
return {
|
|
13427
13443
|
element: n,
|
|
13428
|
-
setActive: (t) =>
|
|
13444
|
+
setActive: (t) => jr(n, t, e.toggle === !0),
|
|
13429
13445
|
remove: () => {
|
|
13430
13446
|
n.remove(), t.tidy();
|
|
13431
13447
|
}
|
|
@@ -13629,7 +13645,7 @@ var Pf = class {
|
|
|
13629
13645
|
this.changeSettings({ scaleMode: this.chart.getScaleMode() === e ? "regular" : e });
|
|
13630
13646
|
}
|
|
13631
13647
|
displayTimezone() {
|
|
13632
|
-
let e =
|
|
13648
|
+
let e = st(this.settingsState.timezone);
|
|
13633
13649
|
return e === "exchange" ? this.chart.getEffectiveTimeZone() : e;
|
|
13634
13650
|
}
|
|
13635
13651
|
toggleGoToDate() {
|
|
@@ -13675,14 +13691,14 @@ var Pf = class {
|
|
|
13675
13691
|
timeframeMenu() {
|
|
13676
13692
|
return this.timeframes.map((e) => ({
|
|
13677
13693
|
value: e,
|
|
13678
|
-
label:
|
|
13694
|
+
label: Wn(e),
|
|
13679
13695
|
custom: this.customTimeframes.has(e)
|
|
13680
13696
|
}));
|
|
13681
13697
|
}
|
|
13682
13698
|
handleAddTimeframe(e) {
|
|
13683
13699
|
if (!this.featureState.customTimeframes) return !1;
|
|
13684
|
-
let t =
|
|
13685
|
-
return !t || !this.chart.isTimeframeAllowed(t) || this.adapter && !
|
|
13700
|
+
let t = Qn(e);
|
|
13701
|
+
return !t || !this.chart.isTimeframeAllowed(t) || this.adapter && !Qe(this.adapter, t) || !this.adapter && Oe(t) !== null ? !1 : (this.timeframes.includes(t) || (this.customTimeframes.add(t), this.timeframeFavorites.add(t), this.timeframes = $n(this.timeframes, [t]), this.toolbar?.setTimeframes(this.timeframeMenu(), this.pinnedTimeframes())), this.handleTimeframe(t), !0);
|
|
13686
13702
|
}
|
|
13687
13703
|
showMarkerTip(e) {
|
|
13688
13704
|
let { marker: t } = e;
|
|
@@ -13701,7 +13717,7 @@ var Pf = class {
|
|
|
13701
13717
|
this.markerTip.style.left = `${l}px`, this.markerTip.style.top = `${u}px`;
|
|
13702
13718
|
}
|
|
13703
13719
|
selectTypedTimeframe(e) {
|
|
13704
|
-
return !this.chart.isTimeframeAllowed(e) || !this.timeframes.includes(e) && !this.featureState.customTimeframes || this.adapter && !
|
|
13720
|
+
return !this.chart.isTimeframeAllowed(e) || !this.timeframes.includes(e) && !this.featureState.customTimeframes || this.adapter && !Qe(this.adapter, e) ? !1 : (this.timeframes.includes(e) || (this.customTimeframes.add(e), this.timeframes = $n(this.timeframes, [e]), this.toolbar?.setTimeframes(this.timeframeMenu(), this.pinnedTimeframes())), this.handleTimeframe(e), !0);
|
|
13705
13721
|
}
|
|
13706
13722
|
applyIndicatorTemplate(e) {
|
|
13707
13723
|
if (!this.featureState.indicatorTemplates) return;
|
|
@@ -13736,7 +13752,7 @@ var Pf = class {
|
|
|
13736
13752
|
this.timeframeFavorites.toggle(e), this.toolbar?.setTimeframeFavorites(this.pinnedTimeframes()), this.updateUI();
|
|
13737
13753
|
}
|
|
13738
13754
|
setData(e) {
|
|
13739
|
-
this.localSeq++, this.baseSeries = e, this.baseTimeframeMs =
|
|
13755
|
+
this.localSeq++, this.baseSeries = e, this.baseTimeframeMs = nt(e), this.applyTimeframeData(), this.adapter || this.loading.end();
|
|
13740
13756
|
}
|
|
13741
13757
|
async switchLocalTimeframe() {
|
|
13742
13758
|
if (!this.baseSeries) return;
|
|
@@ -13753,7 +13769,7 @@ var Pf = class {
|
|
|
13753
13769
|
let e = performance.now(), t = C(this.state.timeframe);
|
|
13754
13770
|
if (this.baseTimeframeMs > 0 && t > this.baseTimeframeMs) {
|
|
13755
13771
|
let e = this.chart.getExchangeTimeZone() ?? null;
|
|
13756
|
-
this.chart.setData(
|
|
13772
|
+
this.chart.setData(tt(this.baseSeries, this.state.timeframe, this.resampleOptions(e))), this.builtInZone = e;
|
|
13757
13773
|
} else this.chart.setData(this.baseSeries), this.builtInZone = void 0;
|
|
13758
13774
|
this.lastLocalSwitchMs = performance.now() - e;
|
|
13759
13775
|
}
|
|
@@ -13824,7 +13840,7 @@ var Pf = class {
|
|
|
13824
13840
|
id: e.id,
|
|
13825
13841
|
params: e.params
|
|
13826
13842
|
})), t = this.getSettings(), n = Ws(t, {
|
|
13827
|
-
...
|
|
13843
|
+
...Ft,
|
|
13828
13844
|
...Object.fromEntries(kf.map((e) => [e, this.settingsDefaults[e]]))
|
|
13829
13845
|
});
|
|
13830
13846
|
return Nd({
|
|
@@ -14101,7 +14117,7 @@ var Pf = class {
|
|
|
14101
14117
|
visible: e.visible
|
|
14102
14118
|
})), t = this.chart.getDrawings().map((e) => ({
|
|
14103
14119
|
id: e.id,
|
|
14104
|
-
label: e.name ||
|
|
14120
|
+
label: e.name || Ko(e.type, this.t),
|
|
14105
14121
|
visible: e.visible,
|
|
14106
14122
|
offInterval: e.visible && !this.chart.isDrawingShown(e.id),
|
|
14107
14123
|
locked: e.locked,
|
|
@@ -14179,14 +14195,14 @@ var Pf = class {
|
|
|
14179
14195
|
for (;;) {
|
|
14180
14196
|
let n = this.state.timeframe, r = null, i = null;
|
|
14181
14197
|
try {
|
|
14182
|
-
r = await
|
|
14198
|
+
r = await et(e).fetchHistory(t, n, this.compareDepth());
|
|
14183
14199
|
} catch (e) {
|
|
14184
14200
|
i = e;
|
|
14185
14201
|
}
|
|
14186
14202
|
if (this.destroyed) return null;
|
|
14187
14203
|
if (n === this.state.timeframe) return r && r.length > 0 ? r : (i === null ? this.say(h(this.t("toast.compareNoBars"), {
|
|
14188
14204
|
symbol: t,
|
|
14189
|
-
interval:
|
|
14205
|
+
interval: Wn(n)
|
|
14190
14206
|
}), "error") : this.sayCompareFailed(t, i), null);
|
|
14191
14207
|
}
|
|
14192
14208
|
}
|
|
@@ -14242,7 +14258,7 @@ var Pf = class {
|
|
|
14242
14258
|
this.symbolLoads.set(e, n);
|
|
14243
14259
|
let r = () => this.destroyed || t !== this.state.timeframe || this.symbolLoads.get(e) !== n;
|
|
14244
14260
|
try {
|
|
14245
|
-
let n = await
|
|
14261
|
+
let n = await et(this.adapter).fetchHistory(e, t, this.compareDepth());
|
|
14246
14262
|
if (r()) return;
|
|
14247
14263
|
this.chart.setSymbolSeries(e, n);
|
|
14248
14264
|
} catch (t) {
|
|
@@ -14259,7 +14275,7 @@ var Pf = class {
|
|
|
14259
14275
|
}
|
|
14260
14276
|
async refetchPercentCompares() {
|
|
14261
14277
|
if (!this.adapter || this.compares.length === 0) return;
|
|
14262
|
-
let e = ++this.compareFetchSeq, t =
|
|
14278
|
+
let e = ++this.compareFetchSeq, t = et(this.adapter);
|
|
14263
14279
|
this.compares = this.compares.map((e) => ({
|
|
14264
14280
|
...e,
|
|
14265
14281
|
failedAt: void 0
|
|
@@ -14292,7 +14308,7 @@ var Pf = class {
|
|
|
14292
14308
|
}
|
|
14293
14309
|
async fetchOlderCompares() {
|
|
14294
14310
|
if (!this.adapter || this.compares.length === 0) return;
|
|
14295
|
-
let e =
|
|
14311
|
+
let e = et(this.adapter), t = this.compareFetchSeq, n = this.state.timeframe;
|
|
14296
14312
|
for (let r of this.compares) {
|
|
14297
14313
|
if (r.timeframe !== n) {
|
|
14298
14314
|
r.failedAt !== n && (this.compareOlderPassed = !0);
|
|
@@ -14470,14 +14486,14 @@ var Pf = class {
|
|
|
14470
14486
|
category: "indicator",
|
|
14471
14487
|
active: [...this.state.activeIndicators.values()].some((e) => e.id === t.id)
|
|
14472
14488
|
});
|
|
14473
|
-
for (let t of
|
|
14489
|
+
for (let t of Mt) e.push({
|
|
14474
14490
|
id: t.value,
|
|
14475
|
-
label:
|
|
14491
|
+
label: zn(t, this.t),
|
|
14476
14492
|
category: "chartType",
|
|
14477
14493
|
active: this.state.chartType === t.value
|
|
14478
14494
|
});
|
|
14479
14495
|
let t = Ya();
|
|
14480
|
-
for (let n of
|
|
14496
|
+
for (let n of Bn(Nt, this.t)) for (let r of n.tools) e.push({
|
|
14481
14497
|
id: r.value,
|
|
14482
14498
|
label: r.label,
|
|
14483
14499
|
category: "drawing",
|
|
@@ -14486,7 +14502,7 @@ var Pf = class {
|
|
|
14486
14502
|
});
|
|
14487
14503
|
for (let t of this.timeframes) e.push({
|
|
14488
14504
|
id: t,
|
|
14489
|
-
label:
|
|
14505
|
+
label: Wn(t),
|
|
14490
14506
|
category: "timeframe",
|
|
14491
14507
|
active: this.state.timeframe === t
|
|
14492
14508
|
});
|
|
@@ -14598,7 +14614,7 @@ var Pf = class {
|
|
|
14598
14614
|
});
|
|
14599
14615
|
}
|
|
14600
14616
|
commandOn(e) {
|
|
14601
|
-
let t =
|
|
14617
|
+
let t = mn(e);
|
|
14602
14618
|
return t === void 0 || this.featureState[t];
|
|
14603
14619
|
}
|
|
14604
14620
|
openClearMenu(e) {
|
|
@@ -14771,7 +14787,7 @@ var Pf = class {
|
|
|
14771
14787
|
let t = this.chartTemplates.get(e);
|
|
14772
14788
|
if (!t) return;
|
|
14773
14789
|
let n = this.allowedSettings(t.settings);
|
|
14774
|
-
this.touchSettings(Object.keys(n),
|
|
14790
|
+
this.touchSettings(Object.keys(n), Yt), this.applySettings(n), this.chart.resetOverrides([...Yt], { layer: "user" }), this.chart.applyOverrides(t.style, { layer: "user" }), this.settings?.refresh(this.shownSettings()), this.say(h(this.t("templates.applied"), { name: e }));
|
|
14775
14791
|
}
|
|
14776
14792
|
promptSaveChartTemplate() {
|
|
14777
14793
|
this.chartTemplatePrompt ??= new ru(this.overlayHost(), this.t), this.chartTemplatePrompt.open({
|
|
@@ -14888,7 +14904,7 @@ var Pf = class {
|
|
|
14888
14904
|
scaleMode: this.userScaleMode(),
|
|
14889
14905
|
autoScale: e.isAutoScale?.(),
|
|
14890
14906
|
invertScale: e.isInvertScale?.(),
|
|
14891
|
-
timezone: t === void 0 ? void 0 :
|
|
14907
|
+
timezone: t === void 0 ? void 0 : ct(t),
|
|
14892
14908
|
numberLocale: e.getNumberLocale?.(),
|
|
14893
14909
|
highLowLines: e.isHighLowLinesVisible?.(),
|
|
14894
14910
|
extendedHours: e.isExtendedHoursVisible?.(),
|
|
@@ -15011,7 +15027,7 @@ var Pf = class {
|
|
|
15011
15027
|
name: e.name,
|
|
15012
15028
|
shortName: e.shortName ?? e.id.toUpperCase(),
|
|
15013
15029
|
placement: e.placement === "panel" ? "panel" : "overlay",
|
|
15014
|
-
category:
|
|
15030
|
+
category: Ke(e)
|
|
15015
15031
|
}));
|
|
15016
15032
|
}
|
|
15017
15033
|
indicatorCounts() {
|
|
@@ -15247,7 +15263,7 @@ var Pf = class {
|
|
|
15247
15263
|
return r(this.state.timeframe, (e) => this.hasReplayStep(e));
|
|
15248
15264
|
}
|
|
15249
15265
|
hasReplayStep(e) {
|
|
15250
|
-
if (this.adapter) return
|
|
15266
|
+
if (this.adapter) return Qe(this.adapter, e);
|
|
15251
15267
|
let t = C(e);
|
|
15252
15268
|
return this.baseSeries !== null && this.baseTimeframeMs > 0 && t >= this.baseTimeframeMs && t % this.baseTimeframeMs === 0;
|
|
15253
15269
|
}
|
|
@@ -15255,7 +15271,7 @@ var Pf = class {
|
|
|
15255
15271
|
return this.replayStep === "bar" || this.replayStep === "auto" && this.options.replayAnimate === !1 ? null : i(this.replayStep, this.state.timeframe, (e) => this.hasReplayStep(e));
|
|
15256
15272
|
}
|
|
15257
15273
|
chartFetchesReplaySteps() {
|
|
15258
|
-
return this.options.replayAnimate === !1 || !this.adapter || this.replayStep === "bar" ? !1 :
|
|
15274
|
+
return this.options.replayAnimate === !1 || !this.adapter || this.replayStep === "bar" ? !1 : et(this.adapter).fetchHistoryBefore !== void 0;
|
|
15259
15275
|
}
|
|
15260
15276
|
async replayStepsFor(e) {
|
|
15261
15277
|
let t = this.chart.getExchangeTimeZone() ?? null, { symbol: n, timeframe: r } = this.state, i = () => `${n}|${r}|${e}|${t}|${this.builtStepsZone(n, e)}`;
|
|
@@ -15264,18 +15280,18 @@ var Pf = class {
|
|
|
15264
15280
|
if (this.adapter) {
|
|
15265
15281
|
let t = Math.max(1, Math.round(C(r) / C(e))), i = Math.min(xf, Math.max(this.chart.getData().length, 100) * t);
|
|
15266
15282
|
try {
|
|
15267
|
-
a = await
|
|
15283
|
+
a = await et(this.adapter).fetchHistory(n, e, i);
|
|
15268
15284
|
} catch {
|
|
15269
15285
|
a = null;
|
|
15270
15286
|
}
|
|
15271
|
-
} else this.baseSeries && (a = C(e) === this.baseTimeframeMs ? this.baseSeries :
|
|
15287
|
+
} else this.baseSeries && (a = C(e) === this.baseTimeframeMs ? this.baseSeries : tt(this.baseSeries, e, this.resampleOptions(t)));
|
|
15272
15288
|
return !a || a.length === 0 ? null : (this.replayStepsCache = {
|
|
15273
15289
|
key: i(),
|
|
15274
15290
|
steps: a
|
|
15275
15291
|
}, a);
|
|
15276
15292
|
}
|
|
15277
15293
|
builtStepsZone(e, t) {
|
|
15278
|
-
let n = this.adapter ?
|
|
15294
|
+
let n = this.adapter ? et(this.adapter) : null;
|
|
15279
15295
|
if (!(n instanceof He)) return "";
|
|
15280
15296
|
let r = n.bucketFor(e, t);
|
|
15281
15297
|
return r ? String(r.timeZone ?? "UTC") : "";
|
|
@@ -15360,14 +15376,14 @@ var Pf = class {
|
|
|
15360
15376
|
}, this.showScaleMode()) : (this.settingsState = {
|
|
15361
15377
|
...this.settingsState,
|
|
15362
15378
|
logScale: e.scaleMode === "logarithmic"
|
|
15363
|
-
}, this.showScaleMode()), e.numberLocale !== void 0 && (this.chart.setNumberLocale(e.numberLocale), this.watchlist?.setLocale(e.numberLocale || void 0)), e.timezone !== void 0 && this.chart.setTimeZone(
|
|
15379
|
+
}, this.showScaleMode()), e.numberLocale !== void 0 && (this.chart.setNumberLocale(e.numberLocale), this.watchlist?.setLocale(e.numberLocale || void 0)), e.timezone !== void 0 && this.chart.setTimeZone(st(e.timezone)), e.highLowLines !== void 0 && this.chart.setHighLowLines(e.highLowLines), e.extendedHours !== void 0 && this.chart.setExtendedHours(e.extendedHours), e.mainSeriesVisible !== void 0 && this.chart.setMainSeriesVisible(e.mainSeriesVisible), e.chartTypeOptions !== void 0 && this.chart.setChartTypeOptions({
|
|
15364
15380
|
...Fs(),
|
|
15365
15381
|
...e.chartTypeOptions
|
|
15366
15382
|
}), t && !this.settingsEdit && this.publishSettings();
|
|
15367
15383
|
}
|
|
15368
15384
|
resetSettings() {
|
|
15369
15385
|
let e = { ...this.settingsState }, t = this.settingsStyle(), n = { ...this.settingsDefaults };
|
|
15370
|
-
this.touchSettings(Object.keys(n),
|
|
15386
|
+
this.touchSettings(Object.keys(n), Yt), this.applySettings(n), this.chart.resetOverrides([...Yt], { layer: "user" });
|
|
15371
15387
|
let r = { ...this.settingsState }, i = this.settingsStyle();
|
|
15372
15388
|
this.settings?.refresh(this.shownSettings()), !(this.settingsEdit || JSON.stringify([e, t]) === JSON.stringify([r, i])) && this.chart.recordUndo({
|
|
15373
15389
|
undo: () => this.restoreSettings(e, t),
|
|
@@ -15400,7 +15416,7 @@ var Pf = class {
|
|
|
15400
15416
|
redo: () => this.restoreSettings(o, null, i ? !1 : void 0)
|
|
15401
15417
|
});
|
|
15402
15418
|
}
|
|
15403
|
-
settingsStyle(e =
|
|
15419
|
+
settingsStyle(e = Yt) {
|
|
15404
15420
|
let t = this.chart.getOverrides?.({ layer: "user" }) ?? {}, n = Object.fromEntries(e.map((e) => {
|
|
15405
15421
|
let n = t[e];
|
|
15406
15422
|
return [e, typeof n == "string" || typeof n == "boolean" || typeof n == "number" ? n : null];
|
|
@@ -15568,7 +15584,7 @@ var Pf = class {
|
|
|
15568
15584
|
};
|
|
15569
15585
|
function Ff(e, t, n) {
|
|
15570
15586
|
let r = (e) => {
|
|
15571
|
-
let t =
|
|
15587
|
+
let t = $e(e.descriptor);
|
|
15572
15588
|
return t && ge(e.params[t])?.instanceId || null;
|
|
15573
15589
|
}, i = new Set([e]);
|
|
15574
15590
|
for (let e = !0; e;) {
|
|
@@ -15758,7 +15774,7 @@ var tp = class {
|
|
|
15758
15774
|
this.options = t, this.layout = Zf(t.layout) ? t.layout : "1x2", this.sync = {
|
|
15759
15775
|
...Jf,
|
|
15760
15776
|
...t.sync
|
|
15761
|
-
}, this.t = p(m(t.widget?.locale, t.widget?.messages)),
|
|
15777
|
+
}, this.t = p(m(t.widget?.locale, t.widget?.messages)), yn(), this.root = document.createElement("div"), this.root.className = "tcw-root tcw-grid", this.root.dataset.tcwTheme = t.widget?.theme === "light" ? "light" : "dark", Ho(this.root, Bo(t.widget?.ui), { variables: t.widget?.ui !== void 0 }), t.bar !== !1 && this.root.appendChild(this.buildBar()), this.cellsEl = document.createElement("div"), this.cellsEl.className = "tcw-grid-cells", this.root.appendChild(this.cellsEl), e.appendChild(this.root), this.stopNarrow = wu(this.root), this.applyShape();
|
|
15762
15778
|
for (let e = 0; e < this.shapeCount(); e++) this.cells.push(this.createCell(e));
|
|
15763
15779
|
this.markActive();
|
|
15764
15780
|
let n = this.cells[0]?.el.querySelector(".tcw-root")?.dataset.tcwTheme;
|
|
@@ -15812,13 +15828,13 @@ var tp = class {
|
|
|
15812
15828
|
return { ...this.sync };
|
|
15813
15829
|
}
|
|
15814
15830
|
setUI(e) {
|
|
15815
|
-
let t =
|
|
15816
|
-
|
|
15831
|
+
let t = Bo(e);
|
|
15832
|
+
Ho(this.root, t);
|
|
15817
15833
|
for (let e of this.cells) e.widget.setUI(t);
|
|
15818
15834
|
this.uiTheme = t;
|
|
15819
15835
|
}
|
|
15820
15836
|
getUI() {
|
|
15821
|
-
return
|
|
15837
|
+
return Bo(this.uiTheme ?? this.options.widget?.ui);
|
|
15822
15838
|
}
|
|
15823
15839
|
setSync(e) {
|
|
15824
15840
|
let t = this.sync;
|
|
@@ -15840,7 +15856,7 @@ var tp = class {
|
|
|
15840
15856
|
this.styleOverrides = t;
|
|
15841
15857
|
}
|
|
15842
15858
|
setFeatures(e) {
|
|
15843
|
-
let t =
|
|
15859
|
+
let t = sn(e);
|
|
15844
15860
|
for (let e of this.cells) e.widget.setFeatures(t);
|
|
15845
15861
|
this.featureSwitches = {
|
|
15846
15862
|
...this.featureSwitches,
|
|
@@ -15891,7 +15907,7 @@ var tp = class {
|
|
|
15891
15907
|
if (!this.destroyed) {
|
|
15892
15908
|
this.destroyed = !0, document.removeEventListener("keydown", this.onKeyDown), this.unregisterKeys(), this.stopNarrow(), this.drawingFrame && cancelAnimationFrame(this.drawingFrame), this.session?.destroy(), this.layoutsUI?.destroy();
|
|
15893
15909
|
for (let e of this.cells) this.destroyCell(e);
|
|
15894
|
-
this.cells = [], this.root.remove(),
|
|
15910
|
+
this.cells = [], this.root.remove(), bn();
|
|
15895
15911
|
}
|
|
15896
15912
|
}
|
|
15897
15913
|
shapeCount() {
|
|
@@ -16135,6 +16151,6 @@ function np(e, t) {
|
|
|
16135
16151
|
return n;
|
|
16136
16152
|
}
|
|
16137
16153
|
//#endregion
|
|
16138
|
-
export { v as CHART_TYPE_ICONS, Pf as ChartWidget, tp as ChartWidgetGrid, Jf as DEFAULT_GRID_SYNC, te as DRAWING_TOOL_ICONS, d as EN_MESSAGES, Xf as GRID_SHAPES, l as LayoutSession, o as MAX_LAYOUT_NAME, oe as UI_ICONS, ee as VI_MESSAGES,
|
|
16154
|
+
export { v as CHART_TYPE_ICONS, Pf as ChartWidget, tp as ChartWidgetGrid, Jf as DEFAULT_GRID_SYNC, te as DRAWING_TOOL_ICONS, d as EN_MESSAGES, Xf as GRID_SHAPES, l as LayoutSession, o as MAX_LAYOUT_NAME, oe as UI_ICONS, ee as VI_MESSAGES, en as WIDGET_FEATURES, Mo as WIDGET_UI_PRESETS, Ho as applyWidgetUI, c as cleanLayoutName, Cn as createChartTypeIcon, k as createIcon, Sn as createToolIcon, f as findWidgetLocale, ue as iconSvg, a as localStorageLayouts, t as memoryLayouts, ep as readGridLayout, Na as readWatchlists, yu as readWidgetLayout, u as registerWidgetLocale, Bo as resolveWidgetUI, Vo as widgetUIVariables };
|
|
16139
16155
|
|
|
16140
16156
|
//# sourceMappingURL=index.js.map
|