@trdrs/quickcharts 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/README.md +742 -180
  3. package/dist/adapters/rest.d.ts +3 -3
  4. package/dist/adapters/rest.js +2 -2
  5. package/dist/adapters/rest.js.map +1 -1
  6. package/dist/{ar-G7MVXRE4.js → ar-KSXQ2USS.js} +20 -20
  7. package/dist/ar-KSXQ2USS.js.map +1 -0
  8. package/dist/{assets-ySndlUS3.d.ts → assets-DOuBBsOp.d.ts} +50 -50
  9. package/dist/{ca_ES-EUSRU4VG.js → ca_ES-JG4FM55E.js} +20 -20
  10. package/dist/ca_ES-JG4FM55E.js.map +1 -0
  11. package/dist/{chunk-RDAK5MUM.js → chunk-6S6TO2N6.js} +41 -37
  12. package/dist/chunk-6S6TO2N6.js.map +1 -0
  13. package/dist/{chunk-KFBQSPNA.js → chunk-D3S26ARP.js} +2 -2
  14. package/dist/chunk-D3S26ARP.js.map +1 -0
  15. package/dist/{chunk-AKXIFHQN.js → chunk-KLPTCWA2.js} +1 -1
  16. package/dist/{chunk-AKXIFHQN.js.map → chunk-KLPTCWA2.js.map} +1 -1
  17. package/dist/{de-2SVTG25S.js → de-VSW2LHNF.js} +20 -20
  18. package/dist/de-VSW2LHNF.js.map +1 -0
  19. package/dist/drawings.d.ts +16 -16
  20. package/dist/drawings.js +12 -12
  21. package/dist/{es-UDHZM4W7.js → es-5ZXIPVOB.js} +20 -20
  22. package/dist/es-5ZXIPVOB.js.map +1 -0
  23. package/dist/feature-manifest.json +51 -3
  24. package/dist/{fr-35VN4G4S.js → fr-4F6DAWGD.js} +20 -20
  25. package/dist/fr-4F6DAWGD.js.map +1 -0
  26. package/dist/{he_IL-JPZMCURP.js → he_IL-B7PBQUEV.js} +20 -20
  27. package/dist/he_IL-B7PBQUEV.js.map +1 -0
  28. package/dist/{id_ID-XSTFHHJQ.js → id_ID-CYJRMXPC.js} +20 -20
  29. package/dist/id_ID-CYJRMXPC.js.map +1 -0
  30. package/dist/index.d.ts +599 -225
  31. package/dist/index.js +10110 -9106
  32. package/dist/index.js.map +1 -1
  33. package/dist/{it-EIY6JESQ.js → it-KTX4SG5P.js} +20 -20
  34. package/dist/it-KTX4SG5P.js.map +1 -0
  35. package/dist/{ja-42N4XRCW.js → ja-V7OURU5D.js} +20 -20
  36. package/dist/ja-V7OURU5D.js.map +1 -0
  37. package/dist/{ko-3VRPTIP3.js → ko-2RNEBYVE.js} +20 -20
  38. package/dist/ko-2RNEBYVE.js.map +1 -0
  39. package/dist/{ms_MY-SKN7O6M5.js → ms_MY-EY235E7Q.js} +20 -20
  40. package/dist/ms_MY-EY235E7Q.js.map +1 -0
  41. package/dist/{pl-TYARHCLT.js → pl-ADNVRP55.js} +20 -20
  42. package/dist/pl-ADNVRP55.js.map +1 -0
  43. package/dist/{pt-72IIFLL4.js → pt-OL2DR3DO.js} +20 -20
  44. package/dist/pt-OL2DR3DO.js.map +1 -0
  45. package/dist/quickcharts.css +218 -205
  46. package/dist/{resources-Ch8eA1Mw.d.ts → resources-Le6flcEn.d.ts} +3 -3
  47. package/dist/rest-openapi.json +11 -11
  48. package/dist/{ru-TPH4F7IB.js → ru-V6YFEPAF.js} +20 -20
  49. package/dist/ru-V6YFEPAF.js.map +1 -0
  50. package/dist/{sv-DC5RS67Z.js → sv-TORXQVE7.js} +20 -20
  51. package/dist/sv-TORXQVE7.js.map +1 -0
  52. package/dist/{th-I6H6AOZ3.js → th-K6SJSYSY.js} +20 -20
  53. package/dist/th-K6SJSYSY.js.map +1 -0
  54. package/dist/theme-manifest.json +99 -11
  55. package/dist/{tr-7FSUVCNW.js → tr-4AEM66KW.js} +20 -20
  56. package/dist/tr-4AEM66KW.js.map +1 -0
  57. package/dist/{vi-DLRPHLLH.js → vi-YU5XCEUU.js} +20 -20
  58. package/dist/vi-YU5XCEUU.js.map +1 -0
  59. package/dist/{zh-ZXIQBBEP.js → zh-QXKRYHU5.js} +20 -20
  60. package/dist/zh-QXKRYHU5.js.map +1 -0
  61. package/dist/{zh_TW-TYNUJU7U.js → zh_TW-AYPDKG4Q.js} +20 -20
  62. package/dist/zh_TW-AYPDKG4Q.js.map +1 -0
  63. package/package.json +1 -1
  64. package/dist/ar-G7MVXRE4.js.map +0 -1
  65. package/dist/ca_ES-EUSRU4VG.js.map +0 -1
  66. package/dist/chunk-KFBQSPNA.js.map +0 -1
  67. package/dist/chunk-RDAK5MUM.js.map +0 -1
  68. package/dist/de-2SVTG25S.js.map +0 -1
  69. package/dist/es-UDHZM4W7.js.map +0 -1
  70. package/dist/fr-35VN4G4S.js.map +0 -1
  71. package/dist/he_IL-JPZMCURP.js.map +0 -1
  72. package/dist/id_ID-XSTFHHJQ.js.map +0 -1
  73. package/dist/it-EIY6JESQ.js.map +0 -1
  74. package/dist/ja-42N4XRCW.js.map +0 -1
  75. package/dist/ko-3VRPTIP3.js.map +0 -1
  76. package/dist/ms_MY-SKN7O6M5.js.map +0 -1
  77. package/dist/pl-TYARHCLT.js.map +0 -1
  78. package/dist/pt-72IIFLL4.js.map +0 -1
  79. package/dist/ru-TPH4F7IB.js.map +0 -1
  80. package/dist/sv-DC5RS67Z.js.map +0 -1
  81. package/dist/th-I6H6AOZ3.js.map +0 -1
  82. package/dist/tr-7FSUVCNW.js.map +0 -1
  83. package/dist/vi-DLRPHLLH.js.map +0 -1
  84. package/dist/zh-ZXIQBBEP.js.map +0 -1
  85. package/dist/zh_TW-TYNUJU7U.js.map +0 -1
@@ -1,14 +1,14 @@
1
1
  /* Quick Charts stylesheet.
2
2
  * Generated from the typed theme source. Do not edit by hand.
3
3
  * Every rule is scoped to [data-qc-theme], the widget root element, and sits in a cascade
4
- * layer: the built-in palettes in trdrs.tokens, every recipe in trdrs.chart.
4
+ * layer: the built-in palettes in quickcharts.tokens, every recipe in quickcharts.chart.
5
5
  * The custom-property names below are private implementation, not API. The supported class
6
6
  * names are listed in the theme manifest under hooks; every other class is private.
7
7
  */
8
8
 
9
- @layer trdrs.tokens, trdrs.chart;
9
+ @layer quickcharts.tokens, quickcharts.chart;
10
10
 
11
- @layer trdrs.tokens {
11
+ @layer quickcharts.tokens {
12
12
  [data-qc-theme="light"] {
13
13
  --qc-canvas-background: #ffffff;
14
14
  --qc-canvas-paneBorder: #ebebeb;
@@ -39,6 +39,14 @@
39
39
  --qc-illustration-ink: #1e222d;
40
40
  --qc-motion-durationBase: 150ms;
41
41
  --qc-motion-durationFast: 90ms;
42
+ --qc-motion-durationModerate: 250ms;
43
+ --qc-motion-durationSlow: 350ms;
44
+ --qc-motion-durationSlower: 500ms;
45
+ --qc-motion-easingLinear: linear;
46
+ --qc-motion-easingOut: ease-out;
47
+ --qc-motion-easingSpring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
48
+ --qc-motion-easingStandard: ease;
49
+ --qc-motion-scaleEnter: 0.97;
42
50
  --qc-overlay-scrim: rgba(0, 0, 0, 0.35);
43
51
  --qc-overlay-separator: #ebebeb;
44
52
  --qc-overlay-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
@@ -122,6 +130,14 @@
122
130
  --qc-illustration-ink: #d1d4dc;
123
131
  --qc-motion-durationBase: 150ms;
124
132
  --qc-motion-durationFast: 90ms;
133
+ --qc-motion-durationModerate: 250ms;
134
+ --qc-motion-durationSlow: 350ms;
135
+ --qc-motion-durationSlower: 500ms;
136
+ --qc-motion-easingLinear: linear;
137
+ --qc-motion-easingOut: ease-out;
138
+ --qc-motion-easingSpring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
139
+ --qc-motion-easingStandard: ease;
140
+ --qc-motion-scaleEnter: 0.97;
125
141
  --qc-overlay-scrim: rgba(0, 0, 0, 0.5);
126
142
  --qc-overlay-separator: #4a4a4a;
127
143
  --qc-overlay-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
@@ -174,9 +190,19 @@
174
190
  --qc-text-primary: #dbdbdb;
175
191
  --qc-text-secondary: #b8b8b8;
176
192
  }
193
+
194
+ @media (prefers-reduced-motion: reduce) {
195
+ [data-qc-theme] {
196
+ --qc-motion-durationBase: 0ms !important;
197
+ --qc-motion-durationFast: 0ms !important;
198
+ --qc-motion-durationModerate: 0ms !important;
199
+ --qc-motion-durationSlow: 0ms !important;
200
+ --qc-motion-durationSlower: 0ms !important;
201
+ }
202
+ }
177
203
  }
178
204
 
179
- @layer trdrs.chart {
205
+ @layer quickcharts.chart {
180
206
  /* Quick Charts component recipes.
181
207
  *
182
208
  * Every rule is scoped to the widget's own root element, which carries `data-qc-theme`. Nothing
@@ -249,7 +275,7 @@
249
275
  border: 1px solid var(--qc-chrome-border);
250
276
  border-radius: var(--qc-chrome-radius);
251
277
  cursor: pointer;
252
- transition: background-color var(--qc-motion-durationFast) linear, border-color var(--qc-motion-durationFast) linear;
278
+ transition: background-color var(--qc-motion-durationFast) var(--qc-motion-easingLinear), border-color var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
253
279
  }
254
280
 
255
281
  [data-qc-theme] .qc-button:hover {
@@ -260,8 +286,8 @@
260
286
  background: var(--qc-state-pressed);
261
287
  }
262
288
 
263
- /* A held button wears the neutral held fill in the primary ink, the held state the toolbars and the
264
- * rail show too. */
289
+ /* A held button wears the neutral held fill in the primary ink, the held state the top bar, the
290
+ * bottom bar and the drawing toolbar show too. */
265
291
  [data-qc-theme] .qc-button[aria-pressed='true'],
266
292
  [data-qc-theme] .qc-button[data-qc-active='true'] {
267
293
  color: var(--qc-text-primary);
@@ -375,7 +401,7 @@
375
401
  border: 0;
376
402
  border-radius: var(--qc-chrome-radius);
377
403
  cursor: pointer;
378
- transition: background-color var(--qc-motion-durationFast) linear;
404
+ transition: background-color var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
379
405
  }
380
406
 
381
407
  [data-qc-theme] .qc-menu-row:hover {
@@ -430,8 +456,8 @@
430
456
  font-variant-numeric: tabular-nums;
431
457
  }
432
458
 
433
- /* A hidden study keeps its ink and stands the WHOLE row back, controls included, so the row reads
434
- * as switched off rather than as a different kind of row. */
459
+ /* A hidden indicator keeps its ink and stands the WHOLE row back, controls included, so the row
460
+ * reads as switched off rather than as a different kind of row. */
435
461
  [data-qc-theme] .qc-legend-row[data-qc-hidden='true'] {
436
462
  opacity: 0.5;
437
463
  }
@@ -544,8 +570,8 @@
544
570
  display: contents;
545
571
  }
546
572
 
547
- /* An external rail's flyout stands here, over anything the page stacks beside the widget and under
548
- * the widget's own dialogs. */
573
+ /* An external drawing toolbar's flyout stands here, over anything the page stacks beside the widget
574
+ * and under the widget's own dialogs. */
549
575
  [data-qc-theme].qc-layer > .qc-drawing-popover {
550
576
  position: fixed;
551
577
  z-index: 2147483001;
@@ -651,7 +677,7 @@
651
677
  }
652
678
 
653
679
  /* The market and its facts stand as one 24px band, in the legend's ink at a size up from the
654
- * chrome's: the mark, the name 4px past it, then the interval and the venue, each in a 12px cell
680
+ * chrome's: the mark, the name 4px past it, then the timeframe and the venue, each in a 12px cell
655
681
  * that carries its separating dot. The reading beside it wraps whole to its own line, so the two
656
682
  * are separate hover targets and only the band under the pointer takes the chip. */
657
683
  [data-qc-theme] .qc-legend-identity {
@@ -721,7 +747,8 @@
721
747
  background: var(--qc-state-pressed);
722
748
  }
723
749
 
724
- /* The interval and the venue, each behind its own separator dot, in the name's own ink and size. */
750
+ /* The timeframe and the venue, each behind its own separator dot, in the name's own ink and
751
+ * size. */
725
752
  [data-qc-theme] .qc-legend-fact {
726
753
  white-space: nowrap;
727
754
  }
@@ -784,8 +811,8 @@
784
811
 
785
812
  /* Step 3: a slim pane sheds the venue and its separator, in the header and in every market row
786
813
  * under it — one answer for the whole legend, because a row that kept its venue while the header
787
- * above it dropped one would read as two different markets. The interval stays, because one chart
788
- * of a layout has nowhere else to say what interval it is on. */
814
+ * above it dropped one would read as two different markets. The timeframe stays, because one chart
815
+ * of a layout has nowhere else to say what timeframe it is on. */
789
816
  [data-qc-theme] .qc-legend[data-qc-slim='true'] [data-role='legend-exchange'],
790
817
  [data-qc-theme] .qc-legend[data-qc-slim='true'] [data-role='legend-exchange-sep'],
791
818
  [data-qc-theme] .qc-legend[data-qc-slim='true'] .qc-legend-row-venue {
@@ -857,7 +884,7 @@
857
884
  opacity: 1;
858
885
  }
859
886
 
860
- /* A hidden study says so whether or not the pointer is on it, so its eye stands on its own. */
887
+ /* A hidden indicator says so whether or not the pointer is on it, so its eye stands on its own. */
861
888
  [data-qc-theme] .qc-legend-row[data-qc-hidden='true'] .qc-legend-eye {
862
889
  opacity: 1;
863
890
  }
@@ -876,8 +903,8 @@
876
903
  margin-inline: -4px;
877
904
  padding-inline: 4px;
878
905
  color: var(--qc-text-primary);
879
- /* The study rows are their own stack over the plot, not part of the header band, so they take the
880
- * ordinary weight rather than the header's. */
906
+ /* The indicator rows are their own stack over the plot, not part of the header band, so they take
907
+ * the ordinary weight rather than the header's. */
881
908
  font-weight: 400;
882
909
  border-radius: 4px;
883
910
  pointer-events: auto;
@@ -971,7 +998,7 @@
971
998
  height: 14px;
972
999
  }
973
1000
 
974
- /* A compare's own name is a door to symbol search, so it is a button. It reads as text and takes
1001
+ /* A comparison's own name is a door to symbol search, so it is a button. It reads as text and takes
975
1002
  * the same wash box the market's name does, never a rule under the words. */
976
1003
  [data-qc-theme] .qc-legend-title {
977
1004
  width: auto;
@@ -991,7 +1018,7 @@
991
1018
  height: 18px;
992
1019
  }
993
1020
 
994
- /* The rows' own toggler, standing under the stack. It carries the study/compare rows away and
1021
+ /* The rows' own toggler, standing under the stack. It carries the indicator/compare rows away and
995
1022
  * leaves the identity and the reading in place. Its box is set here, AFTER the shared action
996
1023
  * recipe, because it is the one action that is not a row control and does not take that geometry. */
997
1024
  [data-qc-theme] .qc-legend-collapse {
@@ -1038,7 +1065,7 @@
1038
1065
  /* The drawing toolbar, the selected drawing's surfaces and their fields are recipes of their own
1039
1066
  * under styles/components/drawings-*.css, which the build concatenates after this file. */
1040
1067
 
1041
- /* Level menu ----------------------------------------------------------------------------------- */
1068
+ /* Context menu --------------------------------------------------------------------------------- */
1042
1069
 
1043
1070
  [data-qc-theme] .qc-menu-backdrop {
1044
1071
  position: fixed;
@@ -1058,7 +1085,7 @@
1058
1085
  pointer-events: auto;
1059
1086
  }
1060
1087
 
1061
- /* The level menu's rows restate the row rhythm: 32px tall, square-cornered and running edge to
1088
+ /* The context menu's rows restate the row rhythm: 32px tall, square-cornered and running edge to
1062
1089
  * edge of the box (the surface's clip rounds them off), the glyph 6px from the label and 20px of
1063
1090
  * room at the end for a chord. */
1064
1091
  [data-qc-theme] .qc-menu .qc-menu-row {
@@ -1139,13 +1166,8 @@
1139
1166
 
1140
1167
  /* Accessibility --------------------------------------------------------------------------------- */
1141
1168
 
1142
- @media (prefers-reduced-motion: reduce) {
1143
- [data-qc-theme] * {
1144
- transition-duration: 1ms !important;
1145
- animation-duration: 1ms !important;
1146
- animation-iteration-count: 1 !important;
1147
- }
1148
- }
1169
+ /* Every transition reads a motion duration role, and the generated tokens resolve each of them to
1170
+ * zero under a reduced-motion preference, so no recipe here repeats that rule. */
1149
1171
 
1150
1172
  @media (forced-colors: active) {
1151
1173
  [data-qc-theme] .qc-surface,
@@ -1219,6 +1241,17 @@
1219
1241
  font-variant-numeric: tabular-nums lining-nums;
1220
1242
  }
1221
1243
 
1244
+ /* With one zone offered the clock stands alone, in the trigger's own cell and inset. */
1245
+ [data-qc-theme] .qc-bottombar .qc-tz-clock {
1246
+ display: inline-flex;
1247
+ align-items: center;
1248
+ gap: 4px;
1249
+ height: 38px;
1250
+ padding: 0 6px;
1251
+ white-space: nowrap;
1252
+ font-variant-numeric: tabular-nums lining-nums;
1253
+ }
1254
+
1222
1255
  [data-qc-theme] .qc-clock {
1223
1256
  font-variant-numeric: tabular-nums;
1224
1257
  }
@@ -1304,7 +1337,7 @@
1304
1337
  transform: translateX(-50%);
1305
1338
  opacity: 0;
1306
1339
  pointer-events: auto;
1307
- transition: opacity var(--qc-motion-durationBase) linear;
1340
+ transition: opacity var(--qc-motion-durationBase) var(--qc-motion-easingLinear);
1308
1341
  }
1309
1342
 
1310
1343
  [data-qc-theme] .qc-nav[data-qc-near],
@@ -1357,11 +1390,11 @@
1357
1390
  * ancestor with a transform, a filter or containment changes nothing: a panel is positioned in the
1358
1391
  * root's own coordinates.
1359
1392
  *
1360
- * The chrome's stacking ladder, all inside the root: legend and rail 3, navigation 4,
1393
+ * The chrome's stacking ladder, all inside the root: legend and drawing toolbar 3, navigation 4,
1361
1394
  * the chart chrome layer 5, notices 6, the overlay layer 20, a menu panel 21, a dialog scrim 22.
1362
1395
  * The replay transport takes no rung: it is an in-flow row of the root's column, not a float.
1363
1396
  * The chart chrome layer is a stacking context of its own, and the drawing surfaces inside it
1364
- * keep their own rungs: the toolbar on the rail's 3, the floating bars 7, the inline text
1397
+ * keep their own rungs: the drawing toolbar on 3, the floating bars 7, the inline text
1365
1398
  * editor 8, a flyout or palette 9, a drawing dialog's scrim 10.
1366
1399
  * A host that must stack something above the widget gives its own element a stacking context
1367
1400
  * above the root; nothing here reaches the top of the integer range. */
@@ -1438,7 +1471,7 @@
1438
1471
  inset: 2px;
1439
1472
  z-index: -1;
1440
1473
  border-radius: var(--qc-chrome-radius);
1441
- transition: background-color var(--qc-motion-durationFast) linear;
1474
+ transition: background-color var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
1442
1475
  }
1443
1476
 
1444
1477
  [data-qc-theme] .qc-toolbar-button:hover {
@@ -1450,8 +1483,8 @@
1450
1483
  background: var(--qc-state-hover);
1451
1484
  }
1452
1485
 
1453
- /* A chosen interval or a held toggle takes the pressed fill, a step past hover; a door whose menu is
1454
- * open fills its whole cell, square, in the hover fill. */
1486
+ /* A chosen timeframe or a held toggle takes the pressed fill, a step past hover; a door whose menu
1487
+ * is open fills its whole cell, square, in the hover fill. */
1455
1488
  [data-qc-theme] .qc-toolbar-button[aria-pressed='true'],
1456
1489
  [data-qc-theme] .qc-toolbar-button[aria-expanded='true'],
1457
1490
  [data-qc-theme] .qc-toolbar-button[data-qc-active='true'] {
@@ -1475,7 +1508,7 @@
1475
1508
  }
1476
1509
 
1477
1510
  /* A HELD MODE is not a chosen option. A chip chosen among its siblings takes the quiet pressed
1478
- * wash above; a mode the chart is IN until the trader leaves it says so the way this product says
1511
+ * wash above; a mode the chart is IN until the viewer leaves it says so the way this product says
1479
1512
  * "on" everywhere else, in the emphasis fill with the ink cut out of it. */
1480
1513
  [data-qc-theme] .qc-toolbar-button[data-qc-mode='held'][aria-pressed='true'] {
1481
1514
  color: var(--qc-text-inverse);
@@ -1499,11 +1532,11 @@
1499
1532
  * and neither bends the other, and each answers to its OWN button: a caret nested inside some other
1500
1533
  * open thing is not the thing that opened. */
1501
1534
  [data-qc-theme] .qc-caret {
1502
- transition: translate 350ms ease;
1535
+ transition: translate var(--qc-motion-durationSlow) var(--qc-motion-easingStandard);
1503
1536
  }
1504
1537
 
1505
1538
  [data-qc-theme] .qc-caret > svg {
1506
- transition: rotate 350ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
1539
+ transition: rotate var(--qc-motion-durationSlow) var(--qc-motion-easingSpring);
1507
1540
  }
1508
1541
 
1509
1542
  [data-qc-theme] .qc-toolbar-button:not([aria-expanded='true']):hover > .qc-caret {
@@ -1626,7 +1659,7 @@
1626
1659
  height: 14px;
1627
1660
  background: var(--qc-control-mark);
1628
1661
  border-radius: 50%;
1629
- transition: inset-inline-start 250ms ease-out;
1662
+ transition: inset-inline-start var(--qc-motion-durationModerate) var(--qc-motion-easingOut);
1630
1663
  }
1631
1664
 
1632
1665
  [data-qc-theme] .qc-switch[aria-checked='true'] .qc-switch-knob,
@@ -1650,7 +1683,7 @@
1650
1683
  border: 1px solid var(--qc-control-on);
1651
1684
  border-radius: 3px;
1652
1685
  cursor: pointer;
1653
- transition: background-color 350ms, border-color 350ms;
1686
+ transition: background-color var(--qc-motion-durationSlow) var(--qc-motion-easingStandard), border-color var(--qc-motion-durationSlow) var(--qc-motion-easingStandard);
1654
1687
  }
1655
1688
 
1656
1689
  [data-qc-theme] .qc-checkbox:checked {
@@ -1970,7 +2003,7 @@
1970
2003
 
1971
2004
  /* The settings field primitives: rows, checkbox rows, selects, number fields with their steppers,
1972
2005
  * swatches and the palette, the custom color panel, the opacity slider, line-end pickers, the
1973
- * dialog tab strip and the interval-visibility rows. Every color a control paints with is either
2006
+ * dialog tab strip and the timeframe-visibility rows. Every color a control paints with is either
1974
2007
  * a generated custom property or the drawing's own value, carried in `--qcd-swatch`. */
1975
2008
 
1976
2009
  [data-qc-theme] .qc-drawing-row {
@@ -2413,7 +2446,7 @@
2413
2446
  }
2414
2447
 
2415
2448
  /* The readout is a FIELD beside the track: outlined rather than washed, because it is a number a
2416
- * trader types over and not a chip the panel is showing them. */
2449
+ * viewer types over and not a chip the panel is showing them. */
2417
2450
  [data-qc-theme] .qc-drawing-opacity-field {
2418
2451
  position: relative;
2419
2452
  flex: 0 0 auto;
@@ -2755,7 +2788,7 @@
2755
2788
  border-radius: var(--qc-chrome-radius);
2756
2789
  content: '';
2757
2790
  pointer-events: none;
2758
- transition: background-color var(--qc-motion-durationFast) linear;
2791
+ transition: background-color var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
2759
2792
  }
2760
2793
 
2761
2794
  [data-qc-theme] .qc-drawing-bar-wide {
@@ -2817,7 +2850,7 @@
2817
2850
  }
2818
2851
 
2819
2852
  /* The bar's menus: a 4px-padded column of 34px rows, sized by content, or 240px wide for the
2820
- * templates, More and interval lists, or 176px for the stacking moves. */
2853
+ * templates, More and timeframe lists, or 176px for the stacking moves. */
2821
2854
  [data-qc-theme] .qc-drawing-bar-menu {
2822
2855
  min-width: 0;
2823
2856
  width: max-content;
@@ -2973,7 +3006,7 @@
2973
3006
 
2974
3007
  [data-qc-theme] .qc-drawing-caret {
2975
3008
  display: flex;
2976
- transition: transform var(--qc-motion-durationFast) linear;
3009
+ transition: transform var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
2977
3010
  }
2978
3011
 
2979
3012
  [data-qc-theme] .qc-drawing-template-button[aria-expanded='true'] .qc-drawing-caret {
@@ -2996,12 +3029,12 @@
2996
3029
  white-space: nowrap;
2997
3030
  }
2998
3031
 
2999
- /* The drawing toolbar: the rail down the chart's inline-start edge, its split cells, its flyouts
3032
+ /* The drawing toolbar: the column down the chart's inline-start edge, its split cells, its flyouts
3000
3033
  * and menus, and the favorites bar. Every rule is scoped to the widget root like the rest of the
3001
3034
  * package stylesheet, every value comes from a generated custom property, and geometry is stated
3002
- * with logical properties so the rail flips with the reading direction.
3035
+ * with logical properties so the toolbar flips with the reading direction.
3003
3036
  *
3004
- * The chrome layer is inert. The rail is a surface the pointer must stop at, so it opts in as a
3037
+ * The chrome layer is inert. The toolbar is a surface the pointer must stop at, so it opts in as a
3005
3038
  * whole; the gaps between its buttons must not let a drag through to the canvas underneath. */
3006
3039
 
3007
3040
  [data-qc-theme].qc-drawing-toolbar-host {
@@ -3030,7 +3063,7 @@
3030
3063
  pointer-events: auto;
3031
3064
  }
3032
3065
 
3033
- /* The chart and its overlays share a reserved content box. Only the rail reaches back into the
3066
+ /* The chart and its overlays share a reserved content box. Only the toolbar reaches back into the
3034
3067
  * leading column, so axis labels and drawing coordinates never pass underneath its buttons. */
3035
3068
  [data-qc-theme] .qc-chrome[data-qc-drawing-toolbar='true'] .qc-drawing-toolbar {
3036
3069
  inset-inline-start: -52px;
@@ -3070,7 +3103,7 @@
3070
3103
  width: 100%;
3071
3104
  }
3072
3105
 
3073
- [data-qc-theme] .qc-drawing-rail-button {
3106
+ [data-qc-theme] .qc-drawing-toolbar-button {
3074
3107
  position: relative;
3075
3108
  z-index: 0;
3076
3109
  display: flex;
@@ -3085,8 +3118,8 @@
3085
3118
  border-radius: var(--qc-chrome-radius);
3086
3119
  }
3087
3120
 
3088
- /* Keep the full rail as the hit area; the inset square is only its visual feedback. */
3089
- [data-qc-theme] .qc-drawing-rail-button::before {
3121
+ /* Keep the full toolbar width as the hit area; the inset square is only its visual feedback. */
3122
+ [data-qc-theme] .qc-drawing-toolbar-button::before {
3090
3123
  position: absolute;
3091
3124
  z-index: -1;
3092
3125
  inset-block-start: 50%;
@@ -3097,67 +3130,67 @@
3097
3130
  content: '';
3098
3131
  pointer-events: none;
3099
3132
  transform: translate(-50%, -50%);
3100
- transition: background-color var(--qc-motion-durationFast) linear;
3133
+ transition: background-color var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
3101
3134
  }
3102
3135
 
3103
- [data-qc-theme] .qc-drawing-rail-button:hover,
3104
- [data-qc-theme] .qc-drawing-rail-button:active,
3105
- [data-qc-theme] .qc-drawing-rail-button:focus-visible {
3136
+ [data-qc-theme] .qc-drawing-toolbar-button:hover,
3137
+ [data-qc-theme] .qc-drawing-toolbar-button:active,
3138
+ [data-qc-theme] .qc-drawing-toolbar-button:focus-visible {
3106
3139
  color: var(--qc-text-primary);
3107
3140
  background: none;
3108
3141
  }
3109
3142
 
3110
3143
  /* The tool's inset square and the arrow's strip share the hover fill, so where they meet no seam
3111
3144
  * forms. */
3112
- [data-qc-theme] .qc-drawing-rail-button:hover::before,
3113
- [data-qc-theme] .qc-drawing-rail-button:focus-visible::before,
3114
- [data-qc-theme] .qc-drawing-rail-button:active::before {
3145
+ [data-qc-theme] .qc-drawing-toolbar-button:hover::before,
3146
+ [data-qc-theme] .qc-drawing-toolbar-button:focus-visible::before,
3147
+ [data-qc-theme] .qc-drawing-toolbar-button:active::before {
3115
3148
  background: var(--qc-state-hover);
3116
3149
  }
3117
3150
 
3118
- [data-qc-theme] .qc-drawing-rail-button[data-qc-active='true'] {
3151
+ [data-qc-theme] .qc-drawing-toolbar-button[data-qc-active='true'] {
3119
3152
  color: var(--qc-text-primary);
3120
3153
  background: none;
3121
3154
  }
3122
3155
 
3123
- /* The armed tool wears a NEUTRAL inset wash and the primary ink, the pinned rail recipe. The
3124
- * accent-tinted selected role belongs to a chosen row, not to a tool the rail is holding. */
3125
- [data-qc-theme] .qc-drawing-rail-button[data-qc-active='true']::before {
3156
+ /* The armed tool wears a NEUTRAL inset wash and the primary ink, the pinned toolbar recipe. The
3157
+ * accent-tinted selected role belongs to a chosen row, not to a tool the toolbar is holding. */
3158
+ [data-qc-theme] .qc-drawing-toolbar-button[data-qc-active='true']::before {
3126
3159
  background: var(--qc-state-pressed);
3127
3160
  }
3128
3161
 
3129
- [data-qc-theme] .qc-drawing-rail-button[data-qc-active='true']:hover::before {
3162
+ [data-qc-theme] .qc-drawing-toolbar-button[data-qc-active='true']:hover::before {
3130
3163
  background: var(--qc-state-pressedHover);
3131
3164
  }
3132
3165
 
3133
- /* A mode the rail holds, staying in drawing mode or showing the favorites bar, inverts: the on fill
3134
- * behind the inverse ink, a step apart under the pointer. */
3135
- [data-qc-theme] .qc-drawing-rail-mode[data-qc-active='true'] {
3166
+ /* A mode the toolbar holds, staying in drawing mode or showing the favorites bar, inverts: the on
3167
+ * fill behind the inverse ink, a step apart under the pointer. */
3168
+ [data-qc-theme] .qc-drawing-toolbar-mode[data-qc-active='true'] {
3136
3169
  color: var(--qc-text-inverse);
3137
3170
  }
3138
3171
 
3139
- [data-qc-theme] .qc-drawing-rail-mode[data-qc-active='true']::before {
3172
+ [data-qc-theme] .qc-drawing-toolbar-mode[data-qc-active='true']::before {
3140
3173
  background: var(--qc-control-on);
3141
3174
  }
3142
3175
 
3143
- [data-qc-theme] .qc-drawing-rail-mode[data-qc-active='true']:hover::before {
3176
+ [data-qc-theme] .qc-drawing-toolbar-mode[data-qc-active='true']:hover::before {
3144
3177
  background: var(--qc-control-onHover);
3145
3178
  }
3146
3179
 
3147
- [data-qc-theme] .qc-drawing-rail-button:focus-visible {
3180
+ [data-qc-theme] .qc-drawing-toolbar-button:focus-visible {
3148
3181
  outline-offset: -3px;
3149
3182
  }
3150
3183
 
3151
- [data-qc-theme] .qc-drawing-rail-button[disabled] {
3184
+ [data-qc-theme] .qc-drawing-toolbar-button[disabled] {
3152
3185
  color: var(--qc-text-disabled);
3153
3186
  background: none;
3154
3187
  }
3155
3188
 
3156
- [data-qc-theme] .qc-drawing-rail-button[disabled]::before {
3189
+ [data-qc-theme] .qc-drawing-toolbar-button[disabled]::before {
3157
3190
  background: none;
3158
3191
  }
3159
3192
 
3160
- [data-qc-theme] .qc-drawing-rail-arrow {
3193
+ [data-qc-theme] .qc-drawing-toolbar-arrow {
3161
3194
  position: absolute;
3162
3195
  inset-block: 2px;
3163
3196
  inset-inline-end: 0;
@@ -3170,51 +3203,51 @@
3170
3203
  color: var(--qc-chrome-caret);
3171
3204
  background: none;
3172
3205
  border: 0;
3173
- /* Rounded on the inboard side only. The strip ends flush against the rail's own edge, so a
3206
+ /* Rounded on the inboard side only. The strip ends flush against the toolbar's own edge, so a
3174
3207
  * radius there would round a corner that has nothing to round away from. */
3175
3208
  border-start-start-radius: 4px;
3176
3209
  border-end-start-radius: 4px;
3177
3210
  border-start-end-radius: 0;
3178
3211
  border-end-end-radius: 0;
3179
3212
  opacity: 0;
3180
- transition: opacity var(--qc-motion-durationFast) linear;
3213
+ transition: opacity var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
3181
3214
  }
3182
3215
 
3183
3216
  /* The chevron turns to face the panel: pointing out at where the flyout will appear while closed,
3184
- * back at the rail once it is open. */
3185
- [data-qc-theme] .qc-drawing-rail-arrow svg {
3186
- transition: transform 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
3217
+ * back at the toolbar once it is open. */
3218
+ [data-qc-theme] .qc-drawing-toolbar-arrow svg {
3219
+ transition: transform var(--qc-motion-durationSlower) var(--qc-motion-easingSpring);
3187
3220
  }
3188
3221
 
3189
- [data-qc-theme] .qc-drawing-rail-arrow[aria-expanded='true'] svg {
3222
+ [data-qc-theme] .qc-drawing-toolbar-arrow[aria-expanded='true'] svg {
3190
3223
  transform: rotate(180deg);
3191
3224
  }
3192
3225
 
3193
- [data-qc-theme] [dir='rtl'] .qc-drawing-rail-arrow svg,
3194
- [data-qc-theme][dir='rtl'] .qc-drawing-rail-arrow svg {
3226
+ [data-qc-theme] [dir='rtl'] .qc-drawing-toolbar-arrow svg,
3227
+ [data-qc-theme][dir='rtl'] .qc-drawing-toolbar-arrow svg {
3195
3228
  transform: scaleX(-1);
3196
3229
  }
3197
3230
 
3198
- [data-qc-theme] [dir='rtl'] .qc-drawing-rail-arrow[aria-expanded='true'] svg,
3199
- [data-qc-theme][dir='rtl'] .qc-drawing-rail-arrow[aria-expanded='true'] svg {
3231
+ [data-qc-theme] [dir='rtl'] .qc-drawing-toolbar-arrow[aria-expanded='true'] svg,
3232
+ [data-qc-theme][dir='rtl'] .qc-drawing-toolbar-arrow[aria-expanded='true'] svg {
3200
3233
  transform: scaleX(-1) rotate(180deg);
3201
3234
  }
3202
3235
 
3203
- [data-qc-theme] .qc-drawing-cell:hover .qc-drawing-rail-arrow,
3204
- [data-qc-theme] .qc-drawing-rail-arrow:focus-visible,
3205
- [data-qc-theme] .qc-drawing-rail-arrow[aria-expanded='true'] {
3236
+ [data-qc-theme] .qc-drawing-cell:hover .qc-drawing-toolbar-arrow,
3237
+ [data-qc-theme] .qc-drawing-toolbar-arrow:focus-visible,
3238
+ [data-qc-theme] .qc-drawing-toolbar-arrow[aria-expanded='true'] {
3206
3239
  opacity: 1;
3207
3240
  }
3208
3241
 
3209
3242
  /* The arrow keeps its caret ink; its strip takes the hover fill under the pointer and while its
3210
3243
  * flyout is open. */
3211
- [data-qc-theme] .qc-drawing-rail-arrow:hover,
3212
- [data-qc-theme] .qc-drawing-rail-arrow[aria-expanded='true'] {
3244
+ [data-qc-theme] .qc-drawing-toolbar-arrow:hover,
3245
+ [data-qc-theme] .qc-drawing-toolbar-arrow[aria-expanded='true'] {
3213
3246
  background: var(--qc-state-hover);
3214
3247
  }
3215
3248
 
3216
- /* Three rules, three recipes. The RAIL's spans 36px of the rail with 6px above and below. A tool
3217
- * flyout's section rule and a menu's rule span the content area inside the panel's 6px side
3249
+ /* Three rules, three recipes. The TOOLBAR's spans 36px of the toolbar with 6px above and below. A
3250
+ * tool flyout's section rule and a menu's rule span the content area inside the panel's 6px side
3218
3251
  * padding, with 6px above and below. */
3219
3252
  [data-qc-theme] .qc-drawing-divider {
3220
3253
  flex: 0 0 auto;
@@ -3294,10 +3327,6 @@
3294
3327
  cursor: default;
3295
3328
  }
3296
3329
 
3297
- [data-qc-theme] .qc-drawing-menu-note {
3298
- padding: 8px 12px;
3299
- }
3300
-
3301
3330
  [data-qc-theme] .qc-drawing-menu .qc-separator {
3302
3331
  margin: 6px 0;
3303
3332
  }
@@ -3360,7 +3389,7 @@
3360
3389
  border-radius: 4px;
3361
3390
  cursor: pointer;
3362
3391
  opacity: 0;
3363
- transition: opacity var(--qc-motion-durationFast) linear;
3392
+ transition: opacity var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
3364
3393
  }
3365
3394
 
3366
3395
  [data-qc-theme] .qc-drawing-flyout-row:hover .qc-drawing-star,
@@ -3457,7 +3486,7 @@
3457
3486
  border-radius: 2px;
3458
3487
  content: '';
3459
3488
  pointer-events: none;
3460
- transition: background-color var(--qc-motion-durationFast) linear;
3489
+ transition: background-color var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
3461
3490
  }
3462
3491
 
3463
3492
  [data-qc-theme] .qc-drawing-favorite:hover,
@@ -3507,14 +3536,14 @@
3507
3536
  cursor: grabbing;
3508
3537
  }
3509
3538
 
3510
- /* Forced colors: a row or tab the trader has chosen reads as the system highlight, since the
3539
+ /* Forced colors: a row or tab the viewer has chosen reads as the system highlight, since the
3511
3540
  * accent fill it wears otherwise is discarded. */
3512
3541
  @media (forced-colors: active) {
3513
- [data-qc-theme] .qc-drawing-rail-button[data-qc-active='true'] {
3542
+ [data-qc-theme] .qc-drawing-toolbar-button[data-qc-active='true'] {
3514
3543
  color: HighlightText;
3515
3544
  }
3516
3545
 
3517
- [data-qc-theme] .qc-drawing-rail-button[data-qc-active='true']::before,
3546
+ [data-qc-theme] .qc-drawing-toolbar-button[data-qc-active='true']::before,
3518
3547
  [data-qc-theme] .qc-drawing-favorite[data-qc-active='true']::before {
3519
3548
  background: Highlight;
3520
3549
  forced-color-adjust: none;
@@ -3537,7 +3566,7 @@
3537
3566
  }
3538
3567
  }
3539
3568
 
3540
- /* The historical indicator browser, rendered by the product with product tokens. */
3569
+ /* The indicator picker, drawn with the chart's own tokens. */
3541
3570
  [data-qc-theme] .qc-picker-dialog {
3542
3571
  height: 638px;
3543
3572
  max-height: min(85vh, calc(100% - 32px));
@@ -3805,7 +3834,7 @@
3805
3834
  So the rail lies DOWN. It becomes a row of chips above the list, scrolling sideways the way every
3806
3835
  other run of choices on a phone does, and the table sheds the columns a phone has no room to
3807
3836
  spend: the author and the count go, the star and the actions stay, and the name takes what is
3808
- left. The GROUP headings go with the rail's column — "Personal" over "Community" reads as
3837
+ left. The GROUP headings go with the rail's column — "Saved" over "Shared" reads as
3809
3838
  structure in a list and as noise in a row, and the chips say what they are. */
3810
3839
  @media (max-width: 560px) {
3811
3840
  [data-qc-theme] .qc-picker-body {
@@ -4403,8 +4432,12 @@
4403
4432
  text-transform: uppercase;
4404
4433
  }
4405
4434
 
4435
+ /* The line a list shows in place of rows (empty, loading, failed): the rows' own size in the muted
4436
+ * ink, on a row's height, its words 8px in where a row's label starts. */
4406
4437
  [data-qc-theme] .qc-menu-note {
4407
- padding: 6px 12px;
4438
+ padding: 6px 8px;
4439
+ color: var(--qc-text-muted);
4440
+ line-height: 20px;
4408
4441
  }
4409
4442
 
4410
4443
  [data-qc-theme] .qc-menu-panel .qc-separator {
@@ -4417,8 +4450,8 @@
4417
4450
  * scrim left every surface beside it live: a press on the page's own header landed on that header
4418
4451
  * instead of dismissing the dialog, so the one gesture every modal answers to did nothing over most
4419
4452
  * of the screen. Fixed, a press anywhere outside the box closes it, which is what `aria-modal` on
4420
- * the box already promises. The z-index is the level-menu's, for the same reason it is: nothing the
4421
- * host stacks above its own page may paint over a surface that has taken the keyboard. */
4453
+ * the box already promises. The z-index is the context menu's, for the same reason it is: nothing
4454
+ * the host stacks above its own page may paint over a surface that has taken the keyboard. */
4422
4455
  [data-qc-theme] .qc-dialog-scrim {
4423
4456
  position: fixed;
4424
4457
  inset: 0;
@@ -4438,6 +4471,34 @@
4438
4471
  font-size: var(--qc-text-fontSizeBase);
4439
4472
  }
4440
4473
 
4474
+ /* The modal motion, which every modal dialog opens and closes with (its scrim carries `data-state`):
4475
+ * the backdrop fades in, and the box fades in and grows from the entrance scale, over one duration.
4476
+ * Closing runs the same motion in reverse. Under a reduced-motion preference the duration is zero,
4477
+ * so both are instant. */
4478
+ [data-qc-theme] .qc-dialog-scrim[data-state] {
4479
+ opacity: 1;
4480
+ transition: opacity var(--qc-motion-durationBase) var(--qc-motion-easingOut);
4481
+ }
4482
+
4483
+ [data-qc-theme] .qc-dialog-scrim[data-state] > .qc-dialog {
4484
+ opacity: 1;
4485
+ scale: none;
4486
+ transition:
4487
+ opacity var(--qc-motion-durationBase) var(--qc-motion-easingStandard),
4488
+ scale var(--qc-motion-durationBase) var(--qc-motion-easingStandard);
4489
+ }
4490
+
4491
+ [data-qc-theme] .qc-dialog-scrim[data-state='opening'],
4492
+ [data-qc-theme] .qc-dialog-scrim[data-state='closing'] {
4493
+ opacity: 0;
4494
+ }
4495
+
4496
+ [data-qc-theme] .qc-dialog-scrim[data-state='opening'] > .qc-dialog,
4497
+ [data-qc-theme] .qc-dialog-scrim[data-state='closing'] > .qc-dialog {
4498
+ opacity: 0;
4499
+ scale: var(--qc-motion-scaleEnter);
4500
+ }
4501
+
4441
4502
  /* In place of rows: the drawing over the line that says nothing matched, centred where the rows
4442
4503
  * would have stood. */
4443
4504
  [data-qc-theme] .qc-empty {
@@ -4612,7 +4673,7 @@
4612
4673
  *
4613
4674
  * The row is in the root's own flow and positions nothing: it reserves 49px of the column between
4614
4675
  * the charts grid and the bottom range and timezone band (a 48px row under the pane's own hairline),
4615
- * so the plot and the time axis stay unobscured and the drawing rail keeps its column beside it.
4676
+ * so the plot and the time axis stay unobscured and the drawing toolbar keeps its column beside it.
4616
4677
  * Entry reserves that height and exit returns it. Everything inside is placed by the strip's logical
4617
4678
  * grid, so a right-to-left chart mirrors without a transform, and a long translation scrolls the
4618
4679
  * strip rather than overlapping a neighbour. */
@@ -4640,14 +4701,15 @@
4640
4701
  transform: translateY(0);
4641
4702
  clip-path: inset(0);
4642
4703
  transition:
4643
- flex-basis 220ms cubic-bezier(0.22, 1, 0.36, 1),
4644
- max-height 220ms cubic-bezier(0.22, 1, 0.36, 1),
4645
- opacity 140ms linear,
4646
- transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
4647
- clip-path 220ms cubic-bezier(0.22, 1, 0.36, 1);
4704
+ flex-basis var(--qc-motion-durationBase) var(--qc-motion-easingStandard),
4705
+ max-height var(--qc-motion-durationBase) var(--qc-motion-easingStandard),
4706
+ opacity var(--qc-motion-durationBase) var(--qc-motion-easingStandard),
4707
+ transform var(--qc-motion-durationBase) var(--qc-motion-easingStandard),
4708
+ clip-path var(--qc-motion-durationBase) var(--qc-motion-easingStandard);
4648
4709
  }
4649
4710
 
4650
- /* The row itself animates from zero to 49px and back. max-height clamps the fixed-height band while
4711
+ /* The row itself animates from zero to 49px and back, on the modal motion's duration and timing,
4712
+ * and closing runs the opening in reverse. max-height clamps the fixed-height band while
4651
4713
  * flex-basis gives the chart space up at the same pace, so the chart and controls move together.
4652
4714
  * The state is driven by CSS transitions because some embedded hosts omit Element.animate(). */
4653
4715
  [data-qc-theme] .qc-replay[data-state='opening'],
@@ -4659,11 +4721,6 @@
4659
4721
  clip-path: inset(100% 0 0);
4660
4722
  }
4661
4723
 
4662
- [data-qc-theme] .qc-replay[data-state='closing'] {
4663
- transition-duration: 170ms, 170ms, 170ms, 170ms, 170ms;
4664
- transition-timing-function: cubic-bezier(0.4, 0, 1, 1), cubic-bezier(0.4, 0, 1, 1), linear, cubic-bezier(0.4, 0, 1, 1), cubic-bezier(0.4, 0, 1, 1);
4665
- }
4666
-
4667
4724
  [data-qc-theme] .qc-replay::-webkit-scrollbar {
4668
4725
  display: none;
4669
4726
  }
@@ -4709,7 +4766,7 @@
4709
4766
  }
4710
4767
 
4711
4768
  [data-qc-theme] .qc-replay-speed,
4712
- [data-qc-theme] .qc-replay-interval {
4769
+ [data-qc-theme] .qc-replay-timeframe {
4713
4770
  justify-content: center;
4714
4771
  min-width: 38px;
4715
4772
  font-variant-numeric: tabular-nums;
@@ -4777,8 +4834,8 @@
4777
4834
  padding-inline: 12px 10px;
4778
4835
  }
4779
4836
 
4780
- /* The starting points carry the same 28-grid marks the rail does, so the gutter is the mark's own
4781
- * width; a list whose rows carry no mark keeps no gutter for one. */
4837
+ /* The starting points carry the same 28-grid marks the drawing toolbar does, so the gutter is the
4838
+ * mark's own width; a list whose rows carry no mark keeps no gutter for one. */
4782
4839
  [data-qc-theme] .qc-replay-menu .qc-menu-icon {
4783
4840
  flex: 0 0 28px;
4784
4841
  width: 28px;
@@ -5028,40 +5085,8 @@
5028
5085
 
5029
5086
  /* The symbol search dialog and its compare family: the heading, the field with its operators, the
5030
5087
  * class strip, and the result list. */
5031
- [data-qc-theme] .qc-search-dialog-scrim {
5032
- opacity: 1;
5033
- transition: opacity 160ms linear;
5034
- }
5035
-
5036
5088
  [data-qc-theme] .qc-search-dialog {
5037
5089
  height: min(85vh, 680px);
5038
- opacity: 1;
5039
- transform: translateY(0) scale(1);
5040
- transform-origin: center 42%;
5041
- transition:
5042
- opacity 150ms ease-out,
5043
- transform 190ms cubic-bezier(0.16, 1, 0.3, 1);
5044
- }
5045
-
5046
- [data-qc-theme] .qc-search-dialog-scrim[data-state='opening'] {
5047
- opacity: 0;
5048
- }
5049
-
5050
- [data-qc-theme] .qc-search-dialog-scrim[data-state='opening'] .qc-search-dialog {
5051
- opacity: 0;
5052
- transform: translateY(8px) scale(0.985);
5053
- }
5054
-
5055
- [data-qc-theme] .qc-search-dialog-scrim[data-state='closing'] {
5056
- opacity: 0;
5057
- transition-duration: 140ms;
5058
- }
5059
-
5060
- [data-qc-theme] .qc-search-dialog-scrim[data-state='closing'] .qc-search-dialog {
5061
- opacity: 0;
5062
- transform: translateY(6px) scale(0.985);
5063
- transition-duration: 110ms, 140ms;
5064
- transition-timing-function: ease-in, cubic-bezier(0.4, 0, 1, 1);
5065
5090
  }
5066
5091
 
5067
5092
  [data-qc-theme] .qc-search-dialog--compare {
@@ -5205,6 +5230,12 @@
5205
5230
  display: none;
5206
5231
  }
5207
5232
 
5233
+ /* A selected class's narrower classes: a second strip of the same tabs, standing directly under the
5234
+ * strip above so the two rows read as one filter. */
5235
+ [data-qc-theme] .qc-search-classes + .qc-search-subclasses {
5236
+ padding-top: 0;
5237
+ }
5238
+
5208
5239
  [data-qc-theme] .qc-search-scope {
5209
5240
  display: inline-flex;
5210
5241
  flex: 0 0 auto;
@@ -5330,8 +5361,8 @@
5330
5361
  white-space: nowrap;
5331
5362
  }
5332
5363
 
5333
- /* The source cell: what kind of market a row is and where its data comes from, then the venue's
5334
- * mark, set against the row's end. */
5364
+ /* The source cell: what kind of market a row is and where its data comes from, then the mark of
5365
+ * the venue or the data source, set against the row's end. */
5335
5366
  [data-qc-theme] .qc-search-source {
5336
5367
  display: inline-flex;
5337
5368
  flex: 0 0 auto;
@@ -5340,7 +5371,7 @@
5340
5371
  padding-inline-end: 20px;
5341
5372
  }
5342
5373
 
5343
- [data-qc-theme] .qc-search-venue {
5374
+ [data-qc-theme] .qc-search-source-name {
5344
5375
  color: var(--qc-text-primary);
5345
5376
  font-size: var(--qc-text-fontSizeBase);
5346
5377
  line-height: 21px;
@@ -5354,8 +5385,8 @@
5354
5385
  }
5355
5386
 
5356
5387
  /* The source's mark: an 18px disc in a 20px cell. The package ships no brand artwork and fetches
5357
- * none: a host paints the venue's own mark, or a provider's, and without one the source is written
5358
- * in the one letter it is known by on the neutral fill. */
5388
+ * none: a host paints the venue's own mark, or a data source's, and without one the source is
5389
+ * written in the one letter it is known by on the neutral fill. */
5359
5390
  [data-qc-theme] .qc-search-mark {
5360
5391
  display: inline-flex;
5361
5392
  flex: 0 0 auto;
@@ -5372,8 +5403,8 @@
5372
5403
  border-radius: 50%;
5373
5404
  }
5374
5405
 
5375
- /* A host's venue or provider mark IS the disc: the package's ground stands down under it, and the
5376
- * artwork fills the round box. */
5406
+ /* A host's venue or data source mark IS the disc: the package's ground stands down under it, and
5407
+ * the artwork fills the round box. */
5377
5408
  [data-qc-theme] .qc-search-mark[data-qc-host='true'] {
5378
5409
  background: none;
5379
5410
  }
@@ -5431,11 +5462,11 @@
5431
5462
  line-height: 21px;
5432
5463
  }
5433
5464
 
5434
- [data-qc-theme] .qc-search-table .qc-search-venue {
5465
+ [data-qc-theme] .qc-search-table .qc-search-source-name {
5435
5466
  margin-inline-end: 8px;
5436
5467
  }
5437
5468
 
5438
- /* COMPARE stacks the ticker over its description and the venue over the kind, on 52px rows, and
5469
+ /* COMPARE stacks the ticker over its description and the source over the kind, on 52px rows, and
5439
5470
  * keeps 6px of air at the list's two ends. */
5440
5471
  [data-qc-theme] .qc-search-dialog--compare .qc-search-row {
5441
5472
  height: 52px;
@@ -5604,13 +5635,8 @@
5604
5635
  font-size: var(--qc-text-fontSizeSmall);
5605
5636
  }
5606
5637
 
5607
- /* Chart settings follows the same centered, two-column layout as TradingView: a fixed title and
5608
- * footer around a section rail and one roomy settings page. */
5609
- [data-qc-theme] .qc-chart-settings-scrim {
5610
- opacity: 1;
5611
- transition: opacity 160ms linear;
5612
- }
5613
-
5638
+ /* Chart settings is a centered, two-column dialog: a fixed title and footer around a section rail
5639
+ * and one roomy settings page. */
5614
5640
  [data-qc-theme] .qc-chart-settings-dialog {
5615
5641
  box-sizing: border-box;
5616
5642
  height: min(612px, calc(100vh - 32px));
@@ -5620,32 +5646,6 @@
5620
5646
  border: 0;
5621
5647
  border-radius: 6px;
5622
5648
  box-shadow: var(--qc-overlay-shadow);
5623
- opacity: 1;
5624
- transform: translateY(0) scale(1);
5625
- transform-origin: center 42%;
5626
- transition:
5627
- opacity 150ms ease-out,
5628
- transform 190ms cubic-bezier(0.16, 1, 0.3, 1);
5629
- }
5630
-
5631
- [data-qc-theme] .qc-chart-settings-scrim[data-state='opening'],
5632
- [data-qc-theme] .qc-chart-settings-scrim[data-state='closing'] {
5633
- opacity: 0;
5634
- }
5635
-
5636
- [data-qc-theme] .qc-chart-settings-scrim[data-state='opening'] .qc-chart-settings-dialog,
5637
- [data-qc-theme] .qc-chart-settings-scrim[data-state='closing'] .qc-chart-settings-dialog {
5638
- opacity: 0;
5639
- transform: translateY(8px) scale(0.985);
5640
- }
5641
-
5642
- [data-qc-theme] .qc-chart-settings-scrim[data-state='closing'] {
5643
- transition-duration: 140ms;
5644
- }
5645
-
5646
- [data-qc-theme] .qc-chart-settings-scrim[data-state='closing'] .qc-chart-settings-dialog {
5647
- transition-duration: 110ms, 140ms;
5648
- transition-timing-function: ease-in, cubic-bezier(0.4, 0, 1, 1);
5649
5649
  }
5650
5650
 
5651
5651
  [data-qc-theme] .qc-chart-settings-dialog .qc-dialog-title {
@@ -5764,8 +5764,8 @@
5764
5764
  border-radius: 4px;
5765
5765
  }
5766
5766
 
5767
- /* TradingView uses compact square checks in this dialog. Keep the existing accessible switch role
5768
- * while painting it as the same control and placing it before the label. */
5767
+ /* This dialog paints its switches as compact square checks before the label, and each keeps the
5768
+ * accessible switch role. */
5769
5769
  [data-qc-theme] .qc-settings-menu .qc-switch-row {
5770
5770
  display: flex;
5771
5771
  flex-direction: row-reverse;
@@ -5807,7 +5807,7 @@
5807
5807
  border-radius: 0;
5808
5808
  opacity: 0;
5809
5809
  transform: rotate(45deg);
5810
- transition: opacity var(--qc-motion-durationFast) linear;
5810
+ transition: opacity var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
5811
5811
  }
5812
5812
 
5813
5813
  [data-qc-theme] .qc-settings-menu .qc-switch[aria-checked='true'] .qc-switch-knob {
@@ -5943,13 +5943,6 @@
5943
5943
  }
5944
5944
  }
5945
5945
 
5946
- @media (prefers-reduced-motion: reduce) {
5947
- [data-qc-theme] .qc-chart-settings-scrim,
5948
- [data-qc-theme] .qc-chart-settings-dialog {
5949
- transition-duration: 0ms;
5950
- }
5951
- }
5952
-
5953
5946
  /* The market-status control on the legend and its popup. */
5954
5947
  [data-qc-theme] .qc-legend-status {
5955
5948
  display: inline-flex;
@@ -6347,7 +6340,7 @@
6347
6340
  [data-qc-theme] .qc-tf-unit-caret {
6348
6341
  flex: 0 0 auto;
6349
6342
  color: var(--qc-text-muted);
6350
- transition: transform var(--qc-motion-durationFast) linear;
6343
+ transition: transform var(--qc-motion-durationFast) var(--qc-motion-easingLinear);
6351
6344
  transform: rotate(180deg);
6352
6345
  }
6353
6346
 
@@ -6401,6 +6394,26 @@
6401
6394
  cursor: not-allowed;
6402
6395
  }
6403
6396
 
6397
+ /* The same list with no drop-down around it, for a page that holds the picker in a box of its own:
6398
+ * a phone's card, where the card IS the picker. It fills that box, the rows scroll inside it, and the
6399
+ * composer stays pinned below them. The box is the page's, so the card paints no surface of its own. */
6400
+ [data-qc-theme].qc-tf-card {
6401
+ display: flex;
6402
+ min-height: 0;
6403
+ height: 100%;
6404
+ flex-direction: column;
6405
+ color: var(--qc-text-primary);
6406
+ font-family: var(--qc-text-fontFamily);
6407
+ font-size: var(--qc-text-fontSizeBase);
6408
+ }
6409
+
6410
+ [data-qc-theme].qc-tf-card > .qc-tf-menu {
6411
+ display: flex;
6412
+ flex: 1 1 auto;
6413
+ min-height: 0;
6414
+ flex-direction: column;
6415
+ }
6416
+
6404
6417
  /* The chart's notices, stacked at the bottom of the charts, newest last. The region is the charts
6405
6418
  * grid's next sibling in the root's column and takes no height of its own; the stack inside it is
6406
6419
  * anchored to its top edge and grows upward, over the charts, never over the bottom bar. */