react-open-source-grid 1.7.0 → 1.7.3

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.
@@ -1 +1 @@
1
- export * from './index-Ds2EPIvF.js';
1
+ export * from './index-C0q2L2oR.js';
@@ -1 +1 @@
1
- import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./index-Ds2EPIvF.js";export{e as createPreset};
1
+ import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"./index-C0q2L2oR.js";export{e as createPreset};
package/dist/index.html CHANGED
@@ -70,8 +70,8 @@
70
70
  }
71
71
  })();
72
72
  </script>
73
- <script type="module" crossorigin src="/assets/index-Ds2EPIvF.js"></script>
74
- <link rel="stylesheet" crossorigin href="/assets/index-90D-dENa.css">
73
+ <script type="module" crossorigin src="/assets/index-C0q2L2oR.js"></script>
74
+ <link rel="stylesheet" crossorigin href="/assets/index-B400HUc-.css">
75
75
  </head>
76
76
  <body>
77
77
  <!-- SEO Content Section -->
@@ -6,6 +6,12 @@ import type { ChartConfig, GridCellRange, NormalizedRange, RangeToChartOptions }
6
6
  * Normalize a grid cell range so that start is always top-left and end is bottom-right
7
7
  */
8
8
  export declare function normalizeRange(range: GridCellRange): NormalizedRange;
9
+ /**
10
+ * Get default colors for chart series
11
+ * Using a vibrant, distinct color palette that works well for all chart types
12
+ * Colors are chosen for maximum visual distinction, especially in pie charts
13
+ */
14
+ export declare const DEFAULT_COLORS: string[];
9
15
  /**
10
16
  * Build a chart configuration from a grid cell range
11
17
  *
@@ -458,8 +458,10 @@ export interface ContextMenuConfig {
458
458
  showExport?: boolean;
459
459
  showColumnOptions?: boolean;
460
460
  showFilterByValue?: boolean;
461
+ showChartOptions?: boolean;
461
462
  customItems?: ContextMenuItem[];
462
463
  onBeforeShow?: (event: ContextMenuEvent) => ContextMenuItem[] | null;
464
+ onCreateChart?: (chartType: 'line' | 'bar' | 'area' | 'pie', selectedRows: Set<string | number>, row?: Row, column?: Column) => void;
463
465
  }
464
466
  export interface ContextMenuEvent {
465
467
  type: 'cell' | 'header' | 'row';
@@ -5724,6 +5724,7 @@ var ContextMenu = ({
5724
5724
  onClose
5725
5725
  }) => {
5726
5726
  const menuRef = (0, import_react15.useRef)(null);
5727
+ const [openSubmenu, setOpenSubmenu] = import_react15.default.useState(null);
5727
5728
  (0, import_react15.useEffect)(() => {
5728
5729
  const handleClickOutside = (event) => {
5729
5730
  if (menuRef.current && !menuRef.current.contains(event.target)) {
@@ -5778,16 +5779,18 @@ var ContextMenu = ({
5778
5779
  }
5779
5780
  }, [x, y]);
5780
5781
  const handleItemClick = (0, import_react15.useCallback)((item) => {
5781
- if (item.disabled || item.type === "separator") {
5782
+ if (item.disabled) {
5783
+ return;
5784
+ }
5785
+ if (item.submenu) {
5786
+ setOpenSubmenu(openSubmenu === item.id ? null : item.id || null);
5782
5787
  return;
5783
5788
  }
5784
5789
  if (item.onClick) {
5785
5790
  item.onClick();
5786
5791
  }
5787
- if (!item.submenu) {
5788
- onClose();
5789
- }
5790
- }, [onClose]);
5792
+ onClose();
5793
+ }, [onClose, openSubmenu]);
5791
5794
  const renderMenuItem = (item, index) => {
5792
5795
  if (item.type === "separator") {
5793
5796
  return /* @__PURE__ */ import_react15.default.createElement(
@@ -5799,11 +5802,10 @@ var ContextMenu = ({
5799
5802
  }
5800
5803
  );
5801
5804
  }
5802
- return /* @__PURE__ */ import_react15.default.createElement(
5805
+ return /* @__PURE__ */ import_react15.default.createElement("div", { key: item.id || index, className: "context-menu-item-wrapper" }, /* @__PURE__ */ import_react15.default.createElement(
5803
5806
  "div",
5804
5807
  {
5805
- key: item.id || index,
5806
- className: `context-menu-item ${item.disabled ? "disabled" : ""} ${item.danger ? "danger" : ""}`,
5808
+ className: `context-menu-item ${item.disabled ? "disabled" : ""} ${item.danger ? "danger" : ""} ${item.submenu ? "has-submenu" : ""}`,
5807
5809
  onClick: () => handleItemClick(item),
5808
5810
  role: "menuitem",
5809
5811
  "aria-disabled": item.disabled,
@@ -5813,7 +5815,7 @@ var ContextMenu = ({
5813
5815
  /* @__PURE__ */ import_react15.default.createElement("span", { className: "context-menu-label" }, item.label),
5814
5816
  item.shortcut && /* @__PURE__ */ import_react15.default.createElement("span", { className: "context-menu-shortcut" }, item.shortcut),
5815
5817
  item.submenu && /* @__PURE__ */ import_react15.default.createElement("span", { className: "context-menu-arrow" }, "\u25B6")
5816
- );
5818
+ ), item.submenu && openSubmenu === item.id && /* @__PURE__ */ import_react15.default.createElement("div", { className: "context-menu-submenu" }, item.submenu.map((subItem, subIndex) => renderMenuItem(subItem, subIndex))));
5817
5819
  };
5818
5820
  return /* @__PURE__ */ import_react15.default.createElement(
5819
5821
  "div",
@@ -5981,16 +5983,20 @@ var useContextMenu = ({
5981
5983
  showExport: (config == null ? void 0 : config.showExport) !== false,
5982
5984
  showColumnOptions: (config == null ? void 0 : config.showColumnOptions) !== false,
5983
5985
  showFilterByValue: (config == null ? void 0 : config.showFilterByValue) !== false,
5986
+ showChartOptions: (config == null ? void 0 : config.showChartOptions) !== false,
5984
5987
  customItems: (config == null ? void 0 : config.customItems) || [],
5985
- onBeforeShow: config == null ? void 0 : config.onBeforeShow
5988
+ onBeforeShow: config == null ? void 0 : config.onBeforeShow,
5989
+ onCreateChart: config == null ? void 0 : config.onCreateChart
5986
5990
  }), [
5987
5991
  config == null ? void 0 : config.enabled,
5988
5992
  config == null ? void 0 : config.showCopy,
5989
5993
  config == null ? void 0 : config.showExport,
5990
5994
  config == null ? void 0 : config.showColumnOptions,
5991
5995
  config == null ? void 0 : config.showFilterByValue,
5996
+ config == null ? void 0 : config.showChartOptions,
5992
5997
  config == null ? void 0 : config.customItems,
5993
- config == null ? void 0 : config.onBeforeShow
5998
+ config == null ? void 0 : config.onBeforeShow,
5999
+ config == null ? void 0 : config.onCreateChart
5994
6000
  ]);
5995
6001
  const buildCellMenuItems = (0, import_react16.useCallback)((row, column) => {
5996
6002
  const items = [];
@@ -6076,6 +6082,58 @@ var useContextMenu = ({
6076
6082
  disabled: cellValue == null
6077
6083
  });
6078
6084
  }
6085
+ if (menuConfig.showChartOptions !== false && hasSelection) {
6086
+ if (items.length > 0) {
6087
+ items.push({ type: "separator" });
6088
+ }
6089
+ items.push({
6090
+ id: "create-chart",
6091
+ label: "Create Chart",
6092
+ icon: "\u{1F4CA}",
6093
+ submenu: [
6094
+ {
6095
+ id: "chart-line",
6096
+ label: "Line Chart",
6097
+ icon: "\u{1F4C8}",
6098
+ onClick: () => {
6099
+ if (menuConfig.onCreateChart) {
6100
+ menuConfig.onCreateChart("line", selectedRows, row, column);
6101
+ }
6102
+ }
6103
+ },
6104
+ {
6105
+ id: "chart-bar",
6106
+ label: "Bar Chart",
6107
+ icon: "\u{1F4CA}",
6108
+ onClick: () => {
6109
+ if (menuConfig.onCreateChart) {
6110
+ menuConfig.onCreateChart("bar", selectedRows, row, column);
6111
+ }
6112
+ }
6113
+ },
6114
+ {
6115
+ id: "chart-area",
6116
+ label: "Area Chart",
6117
+ icon: "\u{1F4C9}",
6118
+ onClick: () => {
6119
+ if (menuConfig.onCreateChart) {
6120
+ menuConfig.onCreateChart("area", selectedRows, row, column);
6121
+ }
6122
+ }
6123
+ },
6124
+ {
6125
+ id: "chart-pie",
6126
+ label: "Pie Chart",
6127
+ icon: "\u{1F967}",
6128
+ onClick: () => {
6129
+ if (menuConfig.onCreateChart) {
6130
+ menuConfig.onCreateChart("pie", selectedRows, row, column);
6131
+ }
6132
+ }
6133
+ }
6134
+ ]
6135
+ });
6136
+ }
6079
6137
  if (menuConfig.customItems.length > 0) {
6080
6138
  if (items.length > 0) {
6081
6139
  items.push({ type: "separator" });
@@ -13969,22 +14027,30 @@ function generateChartId() {
13969
14027
  return `chart-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
13970
14028
  }
13971
14029
  var DEFAULT_COLORS = [
13972
- "#8884d8",
13973
- // blue
13974
- "#82ca9d",
13975
- // green
13976
- "#ffc658",
13977
- // yellow
13978
- "#ff7c7c",
13979
- // red
13980
- "#a28fd0",
14030
+ "#2563eb",
14031
+ // vibrant blue
14032
+ "#10b981",
14033
+ // emerald green
14034
+ "#f59e0b",
14035
+ // amber/orange
14036
+ "#ef4444",
14037
+ // bright red
14038
+ "#8b5cf6",
13981
14039
  // purple
13982
- "#ff9f40",
14040
+ "#ec4899",
14041
+ // pink
14042
+ "#06b6d4",
14043
+ // cyan
14044
+ "#f97316",
13983
14045
  // orange
13984
- "#4bc0c0",
14046
+ "#14b8a6",
13985
14047
  // teal
13986
- "#ff6384"
13987
- // pink
14048
+ "#a855f7",
14049
+ // violet
14050
+ "#84cc16",
14051
+ // lime
14052
+ "#f43f5e"
14053
+ // rose
13988
14054
  ];
13989
14055
  function buildChartConfigFromRange(options) {
13990
14056
  const {
@@ -14234,16 +14300,13 @@ var QuickChart = ({
14234
14300
  fill: "#8884d8",
14235
14301
  dataKey: "value"
14236
14302
  },
14237
- pieData.map((_, index) => {
14238
- var _a;
14239
- return /* @__PURE__ */ import_react40.default.createElement(
14240
- import_recharts.Cell,
14241
- {
14242
- key: `cell-${index}`,
14243
- fill: ((_a = config.series[0]) == null ? void 0 : _a.color) || ["#8884d8", "#82ca9d", "#ffc658", "#ff7c7c", "#a28fd0"][index % 5]
14244
- }
14245
- );
14246
- })
14303
+ pieData.map((_, index) => /* @__PURE__ */ import_react40.default.createElement(
14304
+ import_recharts.Cell,
14305
+ {
14306
+ key: `cell-${index}`,
14307
+ fill: DEFAULT_COLORS[index % DEFAULT_COLORS.length]
14308
+ }
14309
+ ))
14247
14310
  ), /* @__PURE__ */ import_react40.default.createElement(
14248
14311
  import_recharts.Tooltip,
14249
14312
  {
@@ -214,6 +214,36 @@ button {
214
214
  background-color: var(--context-menu-separator, #e0e0e0);
215
215
  margin: 4px 0;
216
216
  }
217
+ .context-menu-item-wrapper {
218
+ position: relative;
219
+ }
220
+ .context-menu-submenu {
221
+ position: absolute;
222
+ left: 100%;
223
+ top: 0;
224
+ background: var(--context-menu-bg, #ffffff);
225
+ border: 1px solid var(--context-menu-border, #d0d0d0);
226
+ border-radius: 6px;
227
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
228
+ min-width: 180px;
229
+ padding: 4px 0;
230
+ z-index: 10001;
231
+ animation: submenuFadeIn 0.15s ease-out;
232
+ margin-left: -4px;
233
+ }
234
+ @keyframes submenuFadeIn {
235
+ from {
236
+ opacity: 0;
237
+ transform: translateX(-8px);
238
+ }
239
+ to {
240
+ opacity: 1;
241
+ transform: translateX(0);
242
+ }
243
+ }
244
+ .context-menu-item.has-submenu {
245
+ padding-right: 24px;
246
+ }
217
247
  @media (prefers-color-scheme: dark) {
218
248
  .context-menu {
219
249
  --context-menu-bg: #2a2a2a;
package/dist/lib/index.js CHANGED
@@ -5302,6 +5302,7 @@ var ContextMenu = ({
5302
5302
  onClose
5303
5303
  }) => {
5304
5304
  const menuRef = useRef6(null);
5305
+ const [openSubmenu, setOpenSubmenu] = React15.useState(null);
5305
5306
  useEffect6(() => {
5306
5307
  const handleClickOutside = (event) => {
5307
5308
  if (menuRef.current && !menuRef.current.contains(event.target)) {
@@ -5356,16 +5357,18 @@ var ContextMenu = ({
5356
5357
  }
5357
5358
  }, [x, y]);
5358
5359
  const handleItemClick = useCallback3((item) => {
5359
- if (item.disabled || item.type === "separator") {
5360
+ if (item.disabled) {
5361
+ return;
5362
+ }
5363
+ if (item.submenu) {
5364
+ setOpenSubmenu(openSubmenu === item.id ? null : item.id || null);
5360
5365
  return;
5361
5366
  }
5362
5367
  if (item.onClick) {
5363
5368
  item.onClick();
5364
5369
  }
5365
- if (!item.submenu) {
5366
- onClose();
5367
- }
5368
- }, [onClose]);
5370
+ onClose();
5371
+ }, [onClose, openSubmenu]);
5369
5372
  const renderMenuItem = (item, index) => {
5370
5373
  if (item.type === "separator") {
5371
5374
  return /* @__PURE__ */ React15.createElement(
@@ -5377,11 +5380,10 @@ var ContextMenu = ({
5377
5380
  }
5378
5381
  );
5379
5382
  }
5380
- return /* @__PURE__ */ React15.createElement(
5383
+ return /* @__PURE__ */ React15.createElement("div", { key: item.id || index, className: "context-menu-item-wrapper" }, /* @__PURE__ */ React15.createElement(
5381
5384
  "div",
5382
5385
  {
5383
- key: item.id || index,
5384
- className: `context-menu-item ${item.disabled ? "disabled" : ""} ${item.danger ? "danger" : ""}`,
5386
+ className: `context-menu-item ${item.disabled ? "disabled" : ""} ${item.danger ? "danger" : ""} ${item.submenu ? "has-submenu" : ""}`,
5385
5387
  onClick: () => handleItemClick(item),
5386
5388
  role: "menuitem",
5387
5389
  "aria-disabled": item.disabled,
@@ -5391,7 +5393,7 @@ var ContextMenu = ({
5391
5393
  /* @__PURE__ */ React15.createElement("span", { className: "context-menu-label" }, item.label),
5392
5394
  item.shortcut && /* @__PURE__ */ React15.createElement("span", { className: "context-menu-shortcut" }, item.shortcut),
5393
5395
  item.submenu && /* @__PURE__ */ React15.createElement("span", { className: "context-menu-arrow" }, "\u25B6")
5394
- );
5396
+ ), item.submenu && openSubmenu === item.id && /* @__PURE__ */ React15.createElement("div", { className: "context-menu-submenu" }, item.submenu.map((subItem, subIndex) => renderMenuItem(subItem, subIndex))));
5395
5397
  };
5396
5398
  return /* @__PURE__ */ React15.createElement(
5397
5399
  "div",
@@ -5559,16 +5561,20 @@ var useContextMenu = ({
5559
5561
  showExport: (config == null ? void 0 : config.showExport) !== false,
5560
5562
  showColumnOptions: (config == null ? void 0 : config.showColumnOptions) !== false,
5561
5563
  showFilterByValue: (config == null ? void 0 : config.showFilterByValue) !== false,
5564
+ showChartOptions: (config == null ? void 0 : config.showChartOptions) !== false,
5562
5565
  customItems: (config == null ? void 0 : config.customItems) || [],
5563
- onBeforeShow: config == null ? void 0 : config.onBeforeShow
5566
+ onBeforeShow: config == null ? void 0 : config.onBeforeShow,
5567
+ onCreateChart: config == null ? void 0 : config.onCreateChart
5564
5568
  }), [
5565
5569
  config == null ? void 0 : config.enabled,
5566
5570
  config == null ? void 0 : config.showCopy,
5567
5571
  config == null ? void 0 : config.showExport,
5568
5572
  config == null ? void 0 : config.showColumnOptions,
5569
5573
  config == null ? void 0 : config.showFilterByValue,
5574
+ config == null ? void 0 : config.showChartOptions,
5570
5575
  config == null ? void 0 : config.customItems,
5571
- config == null ? void 0 : config.onBeforeShow
5576
+ config == null ? void 0 : config.onBeforeShow,
5577
+ config == null ? void 0 : config.onCreateChart
5572
5578
  ]);
5573
5579
  const buildCellMenuItems = useCallback4((row, column) => {
5574
5580
  const items = [];
@@ -5654,6 +5660,58 @@ var useContextMenu = ({
5654
5660
  disabled: cellValue == null
5655
5661
  });
5656
5662
  }
5663
+ if (menuConfig.showChartOptions !== false && hasSelection) {
5664
+ if (items.length > 0) {
5665
+ items.push({ type: "separator" });
5666
+ }
5667
+ items.push({
5668
+ id: "create-chart",
5669
+ label: "Create Chart",
5670
+ icon: "\u{1F4CA}",
5671
+ submenu: [
5672
+ {
5673
+ id: "chart-line",
5674
+ label: "Line Chart",
5675
+ icon: "\u{1F4C8}",
5676
+ onClick: () => {
5677
+ if (menuConfig.onCreateChart) {
5678
+ menuConfig.onCreateChart("line", selectedRows, row, column);
5679
+ }
5680
+ }
5681
+ },
5682
+ {
5683
+ id: "chart-bar",
5684
+ label: "Bar Chart",
5685
+ icon: "\u{1F4CA}",
5686
+ onClick: () => {
5687
+ if (menuConfig.onCreateChart) {
5688
+ menuConfig.onCreateChart("bar", selectedRows, row, column);
5689
+ }
5690
+ }
5691
+ },
5692
+ {
5693
+ id: "chart-area",
5694
+ label: "Area Chart",
5695
+ icon: "\u{1F4C9}",
5696
+ onClick: () => {
5697
+ if (menuConfig.onCreateChart) {
5698
+ menuConfig.onCreateChart("area", selectedRows, row, column);
5699
+ }
5700
+ }
5701
+ },
5702
+ {
5703
+ id: "chart-pie",
5704
+ label: "Pie Chart",
5705
+ icon: "\u{1F967}",
5706
+ onClick: () => {
5707
+ if (menuConfig.onCreateChart) {
5708
+ menuConfig.onCreateChart("pie", selectedRows, row, column);
5709
+ }
5710
+ }
5711
+ }
5712
+ ]
5713
+ });
5714
+ }
5657
5715
  if (menuConfig.customItems.length > 0) {
5658
5716
  if (items.length > 0) {
5659
5717
  items.push({ type: "separator" });
@@ -13541,22 +13599,30 @@ function generateChartId() {
13541
13599
  return `chart-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
13542
13600
  }
13543
13601
  var DEFAULT_COLORS = [
13544
- "#8884d8",
13545
- // blue
13546
- "#82ca9d",
13547
- // green
13548
- "#ffc658",
13549
- // yellow
13550
- "#ff7c7c",
13551
- // red
13552
- "#a28fd0",
13602
+ "#2563eb",
13603
+ // vibrant blue
13604
+ "#10b981",
13605
+ // emerald green
13606
+ "#f59e0b",
13607
+ // amber/orange
13608
+ "#ef4444",
13609
+ // bright red
13610
+ "#8b5cf6",
13553
13611
  // purple
13554
- "#ff9f40",
13612
+ "#ec4899",
13613
+ // pink
13614
+ "#06b6d4",
13615
+ // cyan
13616
+ "#f97316",
13555
13617
  // orange
13556
- "#4bc0c0",
13618
+ "#14b8a6",
13557
13619
  // teal
13558
- "#ff6384"
13559
- // pink
13620
+ "#a855f7",
13621
+ // violet
13622
+ "#84cc16",
13623
+ // lime
13624
+ "#f43f5e"
13625
+ // rose
13560
13626
  ];
13561
13627
  function buildChartConfigFromRange(options) {
13562
13628
  const {
@@ -13822,16 +13888,13 @@ var QuickChart = ({
13822
13888
  fill: "#8884d8",
13823
13889
  dataKey: "value"
13824
13890
  },
13825
- pieData.map((_, index) => {
13826
- var _a;
13827
- return /* @__PURE__ */ React35.createElement(
13828
- Cell,
13829
- {
13830
- key: `cell-${index}`,
13831
- fill: ((_a = config.series[0]) == null ? void 0 : _a.color) || ["#8884d8", "#82ca9d", "#ffc658", "#ff7c7c", "#a28fd0"][index % 5]
13832
- }
13833
- );
13834
- })
13891
+ pieData.map((_, index) => /* @__PURE__ */ React35.createElement(
13892
+ Cell,
13893
+ {
13894
+ key: `cell-${index}`,
13895
+ fill: DEFAULT_COLORS[index % DEFAULT_COLORS.length]
13896
+ }
13897
+ ))
13835
13898
  ), /* @__PURE__ */ React35.createElement(
13836
13899
  Tooltip2,
13837
13900
  {
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "react-open-source-grid",
3
3
  "private": false,
4
- "version": "1.7.0",
4
+ "version": "1.7.3",
5
5
  "type": "module",
6
- "description": "A high-performance React DataGrid component with advanced features like virtual scrolling, infinite scrolling, tree data, market data mode, integrated charts, and more",
6
+ "description": "A high-performance React DataGrid component with advanced features like virtual scrolling, infinite scrolling, tree data, market data mode, integrated charts with context menu, and more",
7
7
  "main": "./dist/lib/index.cjs",
8
8
  "module": "./dist/lib/index.js",
9
9
  "types": "./dist/lib/index.d.ts",
@@ -1 +0,0 @@
1
- *{box-sizing:border-box;margin:0;padding:0}html,body,#root{width:100%;height:100%}body{color:#333;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#fafafa;margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;line-height:1.6}input,button,textarea,select{font-family:inherit;font-size:inherit}button{cursor:pointer;background:0 0;border:none;margin:0;padding:0}:root{--color-primary:#06c;--color-primary-light:#e8f0ff;--color-primary-dark:#004ca3;--color-neutral-dark:#1a1a1a;--color-neutral-light:#f5f5f5;--color-border:#d9d9d9;--color-border-light:#efefef;--color-bg-hover:#f0f0f0;--color-text-primary:#262626;--color-text-secondary:#666;--grid-border:#e5e7eb;--grid-border-width:1px;--grid-border-radius:6px;--grid-bg:#fff;--grid-bg-alt:#f9fafb;--grid-header-bg:#f3f4f6;--grid-footer-bg:#f9fafb;--grid-text:#111827;--grid-text-secondary:#6b7280;--grid-text-muted:#9ca3af;--grid-header-text:#374151;--grid-primary:#3b82f6;--grid-selected:#3b82f614;--grid-hover:#f9fafb;--grid-active:#eff6ff;--grid-cell-padding:10px 12px;--grid-header-padding:10px 12px;--grid-font-size:13px;--grid-font-size-sm:12px;--grid-header-font-weight:600;--grid-shadow-light:0 1px 3px 0 #00000014;--grid-text-inverse:#fff}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#a1a1a1}.virtual-scroller-container{scrollbar-width:thin;scrollbar-color:#c1c1c1 #f1f1f1}.virtual-scroller-container::-webkit-scrollbar{-webkit-appearance:none;width:12px;height:12px}.virtual-scroller-container::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0}.virtual-scroller-container::-webkit-scrollbar-thumb{background:#c1c1c1;border:2px solid #f1f1f1;border-radius:6px}.virtual-scroller-container::-webkit-scrollbar-thumb:hover{background:#a1a1a1}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.context-menu{background:var(--context-menu-bg,#fff);border:1px solid var(--context-menu-border,#d0d0d0);z-index:10000;min-width:200px;max-width:320px;color:var(--context-menu-text,#333);-webkit-user-select:none;user-select:none;border-radius:6px;padding:4px 0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:1.5;animation:.12s ease-out contextMenuFadeIn;position:fixed;box-shadow:0 4px 16px #00000026}@keyframes contextMenuFadeIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.context-menu-item{cursor:pointer;align-items:center;gap:8px;padding:8px 12px;transition:background-color .1s;display:flex;position:relative}.context-menu-item:hover:not(.disabled){background-color:var(--context-menu-hover-bg,#f0f0f0)}.context-menu-item:active:not(.disabled){background-color:var(--context-menu-active-bg,#e5e5e5)}.context-menu-item.disabled{opacity:.4;cursor:not-allowed}.context-menu-item.danger{color:var(--context-menu-danger,#dc3545)}.context-menu-item.danger:hover:not(.disabled){background-color:var(--context-menu-danger-hover-bg,#fff0f0)}.context-menu-icon{flex-shrink:0;justify-content:center;align-items:center;width:20px;font-size:16px;display:flex}.context-menu-label{white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.context-menu-shortcut{color:var(--context-menu-shortcut,#888);margin-left:auto;padding-left:16px;font-size:12px}.context-menu-arrow{color:var(--context-menu-arrow,#888);margin-left:auto;font-size:10px}.context-menu-separator{background-color:var(--context-menu-separator,#e0e0e0);height:1px;margin:4px 0}@media (prefers-color-scheme:dark){.context-menu{--context-menu-bg:#2a2a2a;--context-menu-border:#404040;--context-menu-text:#e0e0e0;--context-menu-hover-bg:#3a3a3a;--context-menu-active-bg:#4a4a4a;--context-menu-separator:#404040;--context-menu-shortcut:#999;--context-menu-arrow:#999;--context-menu-danger:#ff6b6b;--context-menu-danger-hover-bg:#3a2a2a}}.data-grid.theme-quartz .context-menu{--context-menu-bg:#fff;--context-menu-border:#c5c5c5;--context-menu-text:#000;--context-menu-hover-bg:#e6f2ff;--context-menu-active-bg:#cce5ff}.data-grid.theme-alpine .context-menu{--context-menu-bg:#f8f9fa;--context-menu-border:#dee2e6;--context-menu-text:#212529;--context-menu-hover-bg:#e9ecef;--context-menu-active-bg:#dee2e6}.data-grid.theme-balham .context-menu{--context-menu-bg:#fff;--context-menu-border:#bdc3c7;--context-menu-text:#2c3e50;--context-menu-hover-bg:#ecf0f1;--context-menu-active-bg:#d5dbdb}.data-grid.theme-material .context-menu{--context-menu-bg:#fff;--context-menu-border:#e0e0e0;--context-menu-text:#212121;--context-menu-hover-bg:#f5f5f5;--context-menu-active-bg:#eee;border-radius:4px;box-shadow:0 2px 4px #0003}.context-menu-item:focus{outline:2px solid var(--context-menu-focus,#06c);outline-offset:-2px}.context-menu-item:focus:not(:focus-visible){outline:none}.market-data-grid{background:#fff;border:1px solid #e0e0e0;width:100%;height:100%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;font-size:13px;overflow:auto}.market-grid-header{z-index:10;background:#f5f5f5;border-bottom:2px solid #d0d0d0;position:sticky;top:0}.market-grid-header-row{min-width:100%;display:flex}.market-grid-header-cell{color:#333;white-space:nowrap;text-overflow:ellipsis;-webkit-user-select:none;user-select:none;border-right:1px solid #e0e0e0;padding:10px 12px;font-weight:600;overflow:hidden}.market-grid-header-cell:last-child{border-right:none}.market-grid-body{min-width:100%}.market-grid-row{cursor:pointer;border-bottom:1px solid #f0f0f0;transition:background-color .1s;display:flex}.market-grid-row:hover{background-color:#f9f9f9}.market-grid-row:active{background-color:#f0f0f0}.market-grid-cell{white-space:nowrap;text-overflow:ellipsis;border-right:1px solid #f5f5f5;align-items:center;padding:8px 12px;display:flex;position:relative;overflow:hidden}.market-grid-cell:last-child{border-right:none}.numeric-cell{font-variant-numeric:tabular-nums;justify-content:flex-end;font-family:Monaco,Menlo,Consolas,monospace}@keyframes flashUp{0%{background-color:#4caf5000}20%{background-color:#4caf5066}to{background-color:#4caf5000}}@keyframes flashDown{0%{background-color:#f4433600}20%{background-color:#f4433666}to{background-color:#f4433600}}.cell-flash-up{animation:.5s ease-out flashUp}.cell-flash-down{animation:.5s ease-out flashDown}.change-positive{color:#4caf50;font-weight:600}.change-negative{color:#f44336;font-weight:600}.market-grid-cell[data-field=bid]{color:#2196f3;font-weight:500}.market-grid-cell[data-field=ask]{color:#ff5722;font-weight:500}.market-grid-cell[data-field=price]{font-size:14px;font-weight:700}.market-grid-cell[data-field=volume],.market-grid-cell[data-field=size]{color:#666;font-size:12px}.market-grid-cell[data-field=symbol],.market-grid-cell[data-field=id]{color:#1976d2;font-family:Monaco,Menlo,Consolas,monospace;font-weight:700}.density-compact .market-grid-header-cell{padding:6px 8px;font-size:12px}.density-compact .market-grid-cell{padding:4px 8px;font-size:12px}.density-compact .market-grid-cell[data-field=price]{font-size:13px}.density-compact .market-grid-row{min-height:28px}.market-grid-cell[data-field=high]{color:#4caf50}.market-grid-cell[data-field=low]{color:#f44336}.market-data-grid.loading{opacity:.6;pointer-events:none}.market-data-grid.loading:after{content:"";border:4px solid #f3f3f3;border-top-color:#2196f3;border-radius:50%;width:40px;height:40px;animation:1s linear infinite spin;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}@keyframes spin{0%{transform:translate(-50%,-50%)rotate(0)}to{transform:translate(-50%,-50%)rotate(360deg)}}.market-data-grid.paused{border:2px solid #ff9800}.market-data-grid.paused:before{content:"PAUSED";color:#fff;z-index:1000;letter-spacing:1px;background:#ff9800;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:700;position:absolute;top:10px;right:10px}.market-data-grid.throttled{border:2px solid #f44336}.market-data-grid.throttled:before{content:"THROTTLED";color:#fff;z-index:1000;letter-spacing:1px;background:#f44336;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:700;position:absolute;top:10px;right:10px}.market-data-grid::-webkit-scrollbar{width:12px;height:12px}.market-data-grid::-webkit-scrollbar-track{background:#f5f5f5}.market-data-grid::-webkit-scrollbar-thumb{background:#ccc;border-radius:6px}.market-data-grid::-webkit-scrollbar-thumb:hover{background:#999}.market-data-wrapper{width:100%;height:100%;position:relative}.market-metrics-overlay{color:#0f0;z-index:1000;pointer-events:none;background:#000000bf;border-radius:4px;padding:8px 12px;font-family:Monaco,Menlo,Consolas,monospace;font-size:11px;line-height:1.6;position:absolute;top:10px;left:10px}.market-metrics-overlay .metric{justify-content:space-between;gap:12px;display:flex}.market-metrics-overlay .metric-label{color:#888}.market-metrics-overlay .metric-value{color:#0f0;font-weight:700}.market-metrics-overlay .metric-value.warning{color:#ff9800}.market-metrics-overlay .metric-value.critical{color:#f44336}.connection-status{z-index:1000;letter-spacing:.5px;border-radius:12px;padding:4px 10px;font-size:11px;font-weight:700;position:absolute;top:10px;right:120px}.connection-status.connected{color:#fff;background:#4caf50}.connection-status.connecting{color:#fff;background:#ff9800}.connection-status.disconnected{color:#fff;background:#f44336}.connection-status.reconnecting{color:#fff;background:#ff9800;animation:1s ease-in-out infinite pulse}@media (max-width:768px){.market-data-grid{font-size:11px}.market-grid-cell{padding:6px 8px}.market-grid-header-cell{padding:8px}}.live-market-demo{background:#fafafa;flex-direction:column;max-width:100%;height:100vh;padding:20px;display:flex}.demo-header{margin-bottom:20px}.demo-header h1{color:#1976d2;margin:0 0 8px;font-size:28px;font-weight:700}.demo-description{color:#666;margin:0;font-size:14px}.demo-controls{background:#fff;border-radius:8px;justify-content:space-between;align-items:center;gap:16px;margin-bottom:16px;padding:16px;display:flex;box-shadow:0 2px 4px #0000001a}.control-group{flex-wrap:wrap;gap:12px;display:flex}.control-btn{cursor:pointer;white-space:nowrap;background:#fff;border:2px solid #e0e0e0;border-radius:6px;padding:10px 20px;font-size:14px;font-weight:600;transition:all .2s}.control-btn:hover{background:#f5f9ff;border-color:#2196f3}.control-btn.active{color:#fff;background:#2196f3;border-color:#2196f3}.control-btn.paused{color:#fff;background:#ff9800;border-color:#ff9800}.connection-info{align-items:center;gap:12px;display:flex}.status-badge{letter-spacing:.5px;border-radius:16px;padding:6px 14px;font-size:11px;font-weight:700}.status-badge.connected{color:#fff;background:#4caf50}.status-badge.connecting{color:#fff;background:#ff9800}.status-badge.disconnected{color:#fff;background:#f44336}.status-badge.reconnecting{color:#fff;background:#ff9800;animation:1s ease-in-out infinite pulse-badge}@keyframes pulse-badge{0%,to{opacity:1}50%{opacity:.6}}.metric-badge{color:#1976d2;background:#e3f2fd;border-radius:4px;padding:6px 12px;font-size:13px;font-weight:600}.metrics-panel{background:#000000d9;border-radius:6px;flex-wrap:wrap;gap:20px;margin-bottom:16px;padding:12px 16px;display:flex}.metric-item{align-items:center;gap:8px;display:flex}.metric-label{color:#888;font-size:13px;font-weight:500}.metric-value{color:#0f0;font-family:Monaco,Menlo,Consolas,monospace;font-size:14px;font-weight:700}.metric-value.warning{color:#ff9800}.metric-value.critical{color:#f44336}.metric-item.warning{background:#ff980033;border-radius:4px;padding:4px 12px}.grid-container{background:#fff;border-radius:8px;flex:1;min-height:600px;position:relative;overflow:hidden;box-shadow:0 2px 8px #0000001a}.grid-container.paused{border:3px solid #ff9800}.grid-container.throttled{border:3px solid #f44336}.grid-container.paused:before{content:"PAUSED";color:#fff;z-index:1000;letter-spacing:1px;background:#ff9800;border-radius:6px;padding:8px 16px;font-size:12px;font-weight:700;position:absolute;top:16px;right:16px;box-shadow:0 2px 6px #0003}.grid-container.throttled:after{content:"CPU THROTTLED";color:#fff;z-index:1000;letter-spacing:1px;background:#f44336;border-radius:6px;padding:8px 16px;font-size:12px;font-weight:700;animation:1s ease-in-out infinite pulse-warning;position:absolute;top:56px;right:16px;box-shadow:0 2px 6px #0003}@keyframes pulse-warning{0%,to{opacity:1}50%{opacity:.7}}.demo-footer{background:#fff;border-radius:8px;margin-top:16px;padding:16px;box-shadow:0 2px 4px #0000001a}.demo-footer p{color:#666;margin:0;font-size:13px;line-height:1.6}.demo-footer strong{color:#333}@media (max-width:1024px){.demo-controls{flex-direction:column;align-items:stretch}.connection-info,.metrics-panel{justify-content:center}}@media (max-width:768px){.live-market-demo{padding:12px}.demo-header h1{font-size:22px}.control-btn{padding:8px 16px;font-size:13px}.metrics-panel{font-size:12px}}.editor-container{width:100%;color:var(--text-color,#333);background:var(--bg-color,#fff);z-index:1000;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;position:relative}.editor-input-wrapper{border:2px solid var(--primary-color,#06c);background:var(--bg-color,#fff);border-radius:4px;align-items:center;display:flex;position:relative;overflow:hidden}.editor-input-wrapper:focus-within{border-color:var(--primary-color,#06c);box-shadow:0 0 0 3px #0066cc1a}.editor-input{color:var(--text-color,#333);background:0 0;border:none;outline:none;flex:1;padding:8px 12px;font-family:inherit;font-size:14px}.editor-input::placeholder{color:var(--text-muted,#999)}.editor-dropdown-icon,.editor-calendar-icon{color:var(--text-muted,#999);pointer-events:none;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;padding:0 8px;display:flex}.editor-input-actions{align-items:center;gap:4px;padding-right:8px;display:flex}.editor-clear-btn{background:var(--bg-hover,#f0f0f0);cursor:pointer;width:20px;height:20px;color:var(--text-muted,#999);border:none;border-radius:50%;justify-content:center;align-items:center;padding:0;font-size:18px;line-height:1;transition:all .2s;display:flex}.editor-clear-btn:hover{background:var(--bg-active,#e0e0e0);color:var(--text-color,#333)}.editor-dropdown{background:var(--bg-color,#fff);border:1px solid var(--border-color,#ddd);z-index:10000;border-radius:4px;max-height:300px;margin-top:4px;position:fixed;overflow-y:auto;box-shadow:0 4px 12px #00000026}.editor-dropdown-empty{text-align:center;color:var(--text-muted,#999);padding:16px;font-style:italic}.editor-dropdown-option{cursor:pointer;border-bottom:1px solid var(--border-light,#f0f0f0);align-items:center;padding:10px 12px;transition:background-color .15s;display:flex}.editor-dropdown-option:last-child{border-bottom:none}.editor-dropdown-option:hover:not(.disabled){background:var(--bg-hover,#f5f5f5)}.editor-dropdown-option.focused:not(.disabled){background:var(--bg-hover,#f0f0f0)}.editor-dropdown-option.selected{background:var(--primary-light,#e6f2ff);color:var(--primary-color,#06c)}.editor-dropdown-option.disabled{opacity:.5;cursor:not-allowed}.editor-option-content{flex:1;align-items:center;gap:8px;display:flex}.editor-option-icon{align-items:center;font-size:16px;display:flex}.editor-option-text{flex:1}.editor-option-label{font-weight:500}.editor-option-description{color:var(--text-muted,#999);margin-top:2px;font-size:12px}.editor-richselect-container{min-width:200px}.editor-richselect-input{min-width:150px}.editor-date-container{min-width:250px}.editor-calendar{min-width:280px;padding:12px}.editor-calendar-header{border-bottom:1px solid var(--border-color,#ddd);justify-content:space-between;align-items:center;margin-bottom:12px;padding-bottom:8px;display:flex}.editor-calendar-title{font-size:15px;font-weight:600}.editor-calendar-nav{cursor:pointer;width:32px;height:32px;color:var(--text-color,#333);background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;font-size:20px;transition:background-color .15s;display:flex}.editor-calendar-nav:hover{background:var(--bg-hover,#f0f0f0)}.editor-calendar-weekdays{grid-template-columns:repeat(7,1fr);gap:4px;margin-bottom:4px;display:grid}.editor-calendar-weekday{text-align:center;color:var(--text-muted,#999);padding:4px;font-size:12px;font-weight:600}.editor-calendar-days{grid-template-columns:repeat(7,1fr);gap:2px;display:grid}.editor-calendar-day{aspect-ratio:1;cursor:pointer;color:var(--text-color,#333);background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;font-size:14px;transition:all .15s;display:flex}.editor-calendar-day:hover:not(:disabled){background:var(--bg-hover,#f0f0f0)}.editor-calendar-day.today{color:var(--primary-color,#06c);font-weight:700}.editor-calendar-day.selected{background:var(--primary-color,#06c);color:#fff;font-weight:600}.editor-calendar-day.other-month{color:var(--text-muted,#ccc)}.editor-calendar-day:disabled{opacity:.3;cursor:not-allowed}.editor-calendar-time{border-top:1px solid var(--border-color,#ddd);margin-top:12px;padding-top:12px}.editor-time-input{border:1px solid var(--border-color,#ddd);border-radius:4px;width:100%;padding:8px;font-family:inherit;font-size:14px}.editor-numeric-container{min-width:150px}.editor-numeric-input{text-align:right;padding-right:4px}.editor-numeric-prefix,.editor-numeric-suffix{color:var(--text-muted,#999);-webkit-user-select:none;user-select:none;padding:0 8px;font-weight:500}.editor-numeric-steppers{border-left:1px solid var(--border-color,#ddd);flex-direction:column;display:flex}.editor-numeric-stepper{cursor:pointer;width:24px;height:50%;color:var(--text-color,#333);background:0 0;border:none;justify-content:center;align-items:center;padding:0;font-size:10px;transition:background-color .15s;display:flex}.editor-numeric-stepper:hover:not(:disabled){background:var(--bg-hover,#f0f0f0)}.editor-numeric-stepper:disabled{opacity:.3;cursor:not-allowed}.editor-numeric-increment{border-bottom:1px solid var(--border-color,#ddd)}.editor-numeric-range{color:var(--text-muted,#999);justify-content:space-between;margin-top:4px;padding:4px 8px;font-size:11px;display:flex}.editor-multiselect-container{min-width:250px}.editor-multiselect-wrapper{flex-wrap:wrap;gap:4px;padding:6px}.editor-multiselect-tags{flex-wrap:wrap;flex:1;gap:4px;min-width:0;display:flex}.editor-tag{background:var(--primary-light,#e6f2ff);color:var(--primary-color,#06c);white-space:nowrap;border-radius:12px;align-items:center;gap:4px;max-width:150px;padding:4px 8px;font-size:12px;display:inline-flex}.editor-tag-icon{font-size:14px}.editor-tag-label{text-overflow:ellipsis;overflow:hidden}.editor-tag-remove{cursor:pointer;color:currentColor;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:16px;line-height:1;transition:background-color .15s;display:flex}.editor-tag-remove:hover{background:#0000001a}.editor-tag-collapsed{background:var(--bg-hover,#f0f0f0);color:var(--text-muted,#666);font-weight:500}.editor-multiselect-input{flex:1;min-width:80px;padding:4px}.editor-multiselect-option{gap:8px}.editor-multiselect-checkbox{cursor:pointer;width:16px;height:16px;margin:0}.editor-markdown-container{background:var(--bg-color,#fff);border:2px solid var(--primary-color,#06c);border-radius:4px;flex-direction:column;min-width:400px;max-width:800px;display:flex;overflow:hidden}.editor-markdown-toolbar{border-bottom:1px solid var(--border-color,#ddd);background:var(--bg-light,#f9f9f9);justify-content:space-between;padding:8px;display:flex}.editor-markdown-toolbar-group{gap:4px;display:flex}.editor-toolbar-btn{border:1px solid var(--border-color,#ddd);background:var(--bg-color,#fff);cursor:pointer;border-radius:4px;justify-content:center;align-items:center;width:32px;height:32px;font-size:14px;transition:all .15s;display:flex}.editor-toolbar-btn:hover{background:var(--bg-hover,#f0f0f0);border-color:var(--primary-color,#06c)}.editor-toolbar-btn.active{background:var(--primary-color,#06c);color:#fff;border-color:var(--primary-color,#06c)}.editor-markdown-content{flex:1;display:flex;overflow:hidden}.editor-markdown-content.split .editor-markdown-editor{border-right:1px solid var(--border-color,#ddd);width:50%}.editor-markdown-content.split .editor-markdown-preview{width:50%}.editor-markdown-editor{flex-direction:column;flex:1;display:flex;position:relative}.editor-textarea{resize:none;width:100%;color:var(--text-color,#333);background:var(--bg-color,#fff);border:none;outline:none;flex:1;padding:12px;font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:13px;line-height:1.6}.editor-markdown-char-count{background:var(--bg-light,#f9f9f9);color:var(--text-muted,#999);pointer-events:none;border-radius:4px;padding:4px 8px;font-size:11px;position:absolute;bottom:8px;right:8px}.editor-markdown-char-count.warning{color:var(--danger-color,#d32f2f);font-weight:600}.editor-markdown-preview{background:var(--bg-light,#fafafa);flex-direction:column;display:flex;overflow:hidden}.editor-markdown-preview-label{text-transform:uppercase;color:var(--text-muted,#999);border-bottom:1px solid var(--border-color,#ddd);letter-spacing:.5px;padding:8px 12px;font-size:11px;font-weight:600}.editor-markdown-preview-content{flex:1;padding:12px;line-height:1.6;overflow-y:auto}.editor-markdown-preview-content h1{color:var(--text-color,#333);margin:16px 0 8px;font-size:24px}.editor-markdown-preview-content h2{color:var(--text-color,#333);margin:14px 0 7px;font-size:20px}.editor-markdown-preview-content h3{color:var(--text-color,#333);margin:12px 0 6px;font-size:16px}.editor-markdown-preview-content p{margin:8px 0}.editor-markdown-preview-content code{background:var(--bg-hover,#f0f0f0);border-radius:3px;padding:2px 6px;font-family:Monaco,Menlo,monospace;font-size:.9em}.editor-markdown-preview-content a{color:var(--primary-color,#06c);text-decoration:none}.editor-markdown-preview-content a:hover{text-decoration:underline}.editor-markdown-preview-content ul{margin:8px 0;padding-left:24px}.editor-markdown-preview-content li{margin:4px 0}.editor-markdown-empty{color:var(--text-muted,#999);font-style:italic}.editor-markdown-footer{border-top:1px solid var(--border-color,#ddd);background:var(--bg-light,#f9f9f9);justify-content:space-between;align-items:center;padding:8px 12px;display:flex}.editor-markdown-hint{color:var(--text-muted,#999);font-size:12px}.editor-markdown-hint kbd{background:var(--bg-color,#fff);border:1px solid var(--border-color,#ddd);border-radius:3px;padding:2px 6px;font-family:inherit;font-size:11px;font-weight:600}.editor-markdown-actions{gap:8px;display:flex}.editor-btn{border:1px solid var(--border-color,#ddd);background:var(--bg-color,#fff);color:var(--text-color,#333);cursor:pointer;border-radius:4px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .15s}.editor-btn:hover{background:var(--bg-hover,#f0f0f0)}.editor-btn-primary{background:var(--primary-color,#06c);color:#fff;border-color:var(--primary-color,#06c)}.editor-btn-primary:hover{background:var(--primary-dark,#0052a3);border-color:var(--primary-dark,#0052a3)}.editor-btn-secondary{background:0 0}.editor-btn-secondary:hover{background:var(--bg-hover,#f0f0f0)}@media (max-width:768px){.editor-markdown-container{min-width:300px;max-width:100%}.editor-markdown-content.split{flex-direction:column}.editor-markdown-content.split .editor-markdown-editor,.editor-markdown-content.split .editor-markdown-preview{border-right:none;width:100%}.editor-markdown-content.split .editor-markdown-editor{border-bottom:1px solid var(--border-color,#ddd)}}.dark-theme .editor-container{--text-color:#e0e0e0;--text-muted:#999;--bg-color:#1e1e1e;--bg-light:#252525;--bg-hover:#2a2a2a;--bg-active:#333;--border-color:#3a3a3a;--border-light:#2a2a2a;--primary-color:#4a9eff;--primary-light:#4a9eff33;--primary-dark:#3a8eef;--danger-color:#f44336}.editor-container button:focus-visible,.editor-input:focus-visible,.editor-textarea:focus-visible{outline:2px solid var(--primary-color,#06c);outline-offset:2px}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.quick-chart{background:#fff;border-radius:8px;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;display:flex;overflow:hidden;box-shadow:0 4px 16px #0000001a}.quick-chart--dark{color:#fff;background:#1a1a1a;box-shadow:0 4px 16px #00000080}.quick-chart__header{background:#f5f5f5;border-bottom:1px solid #e0e0e0;justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.quick-chart--dark .quick-chart__header{background:#252525;border-bottom-color:#333}.quick-chart__title{color:#333;margin:0;font-size:16px;font-weight:600}.quick-chart--dark .quick-chart__title{color:#fff}.quick-chart__controls{align-items:center;gap:8px;display:flex}.quick-chart__type-selector{background:#fff;border:1px solid #ddd;border-radius:6px;gap:4px;padding:4px;display:flex}.quick-chart--dark .quick-chart__type-selector{background:#2a2a2a;border-color:#444}.quick-chart__type-btn{cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;width:32px;height:32px;padding:0;font-size:16px;transition:background-color .2s;display:flex}.quick-chart__type-btn:hover{background:#f0f0f0}.quick-chart--dark .quick-chart__type-btn:hover{background:#3a3a3a}.quick-chart__type-btn--active{background:#e3f2fd}.quick-chart--dark .quick-chart__type-btn--active{background:#1e3a5f}.quick-chart__btn{cursor:pointer;background:#fff;border:1px solid #ddd;border-radius:4px;justify-content:center;align-items:center;width:32px;height:32px;padding:0;font-size:16px;transition:all .2s;display:flex}.quick-chart__btn:hover{background:#f0f0f0;border-color:#999}.quick-chart--dark .quick-chart__btn{color:#fff;background:#2a2a2a;border-color:#444}.quick-chart--dark .quick-chart__btn:hover{background:#3a3a3a;border-color:#666}.quick-chart__close{color:#666;font-size:24px;line-height:1}.quick-chart__close:hover{color:#d32f2f;background:#ffebee}.quick-chart--dark .quick-chart__close{color:#aaa}.quick-chart--dark .quick-chart__close:hover{color:#ff5252;background:#3a1f1f}.quick-chart__body{flex:1;min-height:0;padding:16px}@media (max-width:768px){.quick-chart__header{flex-direction:column;align-items:flex-start;gap:8px}.quick-chart__controls{justify-content:flex-end;width:100%}}.chart-overlay{z-index:9999;pointer-events:none;position:fixed;inset:0}.chart-overlay__backdrop{pointer-events:all;background:#0000004d;animation:.2s ease-out fadeIn;position:absolute;inset:0}.chart-overlay__container{pointer-events:all;transition:box-shadow .2s;animation:.3s ease-out slideIn;position:absolute}.chart-overlay__container--draggable{cursor:move}.chart-overlay__container--dragging{cursor:grabbing;transition:none;box-shadow:0 8px 32px #0003!important}.chart-overlay__container--draggable .quick-chart__header{cursor:move}.chart-overlay__container--dragging .quick-chart__header{cursor:grabbing}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{opacity:0;transform:scale(.95)translateY(10px)}to{opacity:1;transform:scale(1)translateY(0)}}@media (max-width:768px){.chart-overlay__container{transform:translateY(-50%);width:calc(100% - 20px)!important;height:400px!important;top:50%!important;left:10px!important}}.charts-demo{max-width:1400px;margin:0 auto;padding:20px}.charts-demo__header{margin-bottom:24px}.charts-demo__title{color:#1a1a1a;margin:0 0 12px;font-size:32px;font-weight:700}.charts-demo__description{color:#666;margin:0;font-size:16px;line-height:1.6}.charts-demo__instructions{background:#f5f5f5;border-left:4px solid #2196f3;border-radius:8px;margin-bottom:24px;padding:20px}.charts-demo__instructions h2{color:#1a1a1a;margin:0 0 12px;font-size:18px}.charts-demo__instructions ol{margin:0;padding-left:24px}.charts-demo__instructions li{color:#444;margin-bottom:8px;line-height:1.6}.charts-demo__toolbar{background:#fff;border-radius:8px;flex-wrap:wrap;align-items:center;gap:12px;margin-bottom:20px;padding:16px;display:flex;box-shadow:0 2px 8px #00000014}.charts-demo__btn{cursor:pointer;background:#fff;border:1px solid #ddd;border-radius:6px;align-items:center;gap:6px;padding:10px 18px;font-size:14px;font-weight:500;transition:all .2s;display:flex}.charts-demo__btn:hover:not(:disabled){background:#f5f5f5;border-color:#999;transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.charts-demo__btn:disabled{opacity:.5;cursor:not-allowed}.charts-demo__btn--primary{color:#fff;background:#2196f3;border-color:#2196f3}.charts-demo__btn--primary:hover:not(:disabled){background:#1976d2;border-color:#1976d2}.charts-demo__selection-info{color:#1565c0;background:#e3f2fd;border-radius:4px;margin-left:auto;padding:8px 12px;font-size:13px;font-weight:500}.charts-demo__grid-container{border-radius:8px;margin-bottom:40px;overflow:hidden;box-shadow:0 2px 8px #00000014}.charts-demo__code-section{margin-bottom:40px}.charts-demo__code-section h2{color:#1a1a1a;margin-bottom:16px;font-size:24px}.charts-demo__features{margin-top:40px}.charts-demo__features h2{color:#1a1a1a;margin-bottom:20px;font-size:24px}.charts-demo__feature-grid{grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:20px;display:grid}.charts-demo__feature{background:#fff;border-radius:8px;padding:24px;transition:transform .2s,box-shadow .2s;box-shadow:0 2px 8px #00000014}.charts-demo__feature:hover{transform:translateY(-2px);box-shadow:0 4px 16px #0000001f}.charts-demo__feature h3{color:#1a1a1a;margin:0 0 8px;font-size:18px}.charts-demo__feature p{color:#666;margin:0;line-height:1.6}.profit-positive{color:#2e7d32;font-weight:600}.profit-negative{color:#c62828;font-weight:600}@media (max-width:768px){.charts-demo{padding:16px}.charts-demo__title{font-size:24px}.charts-demo__toolbar{flex-direction:column;align-items:stretch}.charts-demo__btn{justify-content:center;width:100%}.charts-demo__selection-info{text-align:center;margin-left:0}.charts-demo__feature-grid{grid-template-columns:1fr}}#root{width:100%;height:100%}.btn-primary{color:#fff;cursor:pointer;background-color:#06c;border:none;border-radius:4px;padding:8px 16px;font-size:14px;font-weight:500;transition:all .2s}.btn-primary:hover{background-color:#0052a3;box-shadow:0 2px 8px #06c3}.btn-primary:active{background-color:#003d7a;transform:translateY(1px)}.btn-secondary{color:#262626;cursor:pointer;background-color:#fff;border:1px solid #d9d9d9;border-radius:4px;padding:8px 16px;font-size:14px;font-weight:500;transition:all .2s}.btn-secondary:hover{background-color:#f5f5f5;border-color:#bfbfbf}.datagrid-container{background-color:#fff;border:1px solid #d9d9d9;border-radius:4px;overflow:hidden;box-shadow:0 1px 3px #00000014}.datagrid-toolbar{background-color:#fafafa;border-bottom:1px solid #efefef;justify-content:space-between;align-items:center;gap:12px;padding:12px 16px;display:flex}.datagrid-toolbar-title{color:#262626;font-size:14px;font-weight:600}.filter-input{border:1px solid #d9d9d9;border-radius:4px;padding:6px 12px;font-size:14px;transition:all .2s}.filter-input:focus{border-color:#06c;outline:none;box-shadow:0 0 0 3px #0066cc1a}.loading-state{color:#8c8c8c;justify-content:center;align-items:center;height:400px;font-size:14px;display:flex}@media (max-width:768px){.datagrid-toolbar{flex-direction:column;align-items:flex-start}}