Thang6822 commited on
Commit
b9f5987
Β·
1 Parent(s): 162d2be

Update Frontend: Replace backgrounds with AIBG.png and update index.html

Browse files
frontend/{Dark_BG.png β†’ AIBG.png} RENAMED
File without changes
frontend/Light_BG.png DELETED

Git LFS Details

  • SHA256: 3ce39c757d5a7c2fb922e4da10bc49bec01908d6933bf8e99d974d6fc15d7f06
  • Pointer size: 132 Bytes
  • Size of remote file: 1.69 MB
frontend/index.html CHANGED
@@ -88,9 +88,15 @@
88
  --logo-primary: #2e8dff;
89
  --logo-secondary: #5dd4ff;
90
  --logo-glow: rgba(46, 141, 255, 0.36);
 
 
 
91
 
92
- --light-bg-image: url("Light_BG.png");
93
- --dark-bg-image: url("Dark_BG.png");
 
 
 
94
 
95
  color-scheme: light;
96
  }
@@ -168,15 +174,26 @@
168
  body::before {
169
  content: "";
170
  position: fixed;
171
- inset: 0;
172
- z-index: -1;
173
- background: var(--bg-base) var(--light-bg-image) no-repeat center/cover;
174
- opacity: 1;
175
- transition: background 0.4s ease, opacity 0.4s ease;
 
 
 
 
 
 
176
  }
177
 
178
  body.dark-theme::before {
179
- background: var(--bg-base) var(--dark-bg-image) no-repeat center/cover;
 
 
 
 
 
180
  }
181
 
182
  /* ═══════════════════════════════════════════════
@@ -314,6 +331,7 @@
314
  align-items: center;
315
  gap: 10px;
316
  flex: 1;
 
317
  justify-content: flex-end;
318
  flex-wrap: nowrap;
319
  /* Keep tight, but handle overflow via media queries */
@@ -389,6 +407,12 @@
389
  background: rgba(255, 255, 255, 0.08);
390
  }
391
 
 
 
 
 
 
 
392
  .search-item .sym {
393
  font-family: var(--ff-mono);
394
  font-weight: 700;
@@ -445,6 +469,7 @@
445
  display: flex;
446
  flex-direction: column;
447
  gap: 3px;
 
448
  }
449
 
450
  .ctrl-label {
@@ -525,6 +550,7 @@
525
  /* primary button */
526
  .btn-primary {
527
  height: var(--ctrl-h);
 
528
  padding: 0 18px;
529
  background: var(--accent-lo);
530
  border: 1px solid var(--bdr-accent);
@@ -562,6 +588,7 @@
562
  .btn-icon {
563
  height: var(--ctrl-h);
564
  width: var(--ctrl-h);
 
565
  display: flex;
566
  align-items: center;
567
  justify-content: center;
@@ -584,6 +611,8 @@
584
  border-color: var(--bdr-muted);
585
  background: var(--bg-control-hov);
586
  color: var(--txt-bright);
 
 
587
  }
588
 
589
  .btn-icon:active {
@@ -715,12 +744,24 @@
715
  flex: 1;
716
  display: flex;
717
  flex-direction: column;
 
 
718
  overflow-x: hidden;
719
  overflow-y: auto;
720
  min-height: 0;
721
  overscroll-behavior: contain;
722
  }
723
 
 
 
 
 
 
 
 
 
 
 
724
  /* ── TOP: 3 Big Gauges Row ── */
725
  .dash-gauges-hero {
726
  display: flex;
@@ -829,7 +870,10 @@
829
  /* Theme Toggle Button */
830
  .btn-theme {
831
  height: var(--ctrl-h);
832
- padding: 0 12px;
 
 
 
833
  background: var(--bg-control);
834
  border: 1px solid var(--bdr-base);
835
  color: var(--txt-primary);
@@ -849,6 +893,11 @@
849
  .btn-theme svg {
850
  width: 16px;
851
  height: 16px;
 
 
 
 
 
852
  }
853
 
854
  .gauge-hero-signal {
@@ -1139,13 +1188,41 @@
1139
  opacity: 0.35;
1140
  text-transform: uppercase;
1141
  white-space: nowrap;
1142
- transition: opacity 0.3s ease;
 
1143
  }
1144
 
1145
  body.dark-theme .chart-logo-overlay {
1146
  opacity: 0.55;
1147
  }
1148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1149
  /* ── Terminal Loader Overlay (Strict Isolation) ── */
1150
  .terminal-loader-overlay {
1151
  position: absolute;
@@ -1389,6 +1466,57 @@
1389
  }
1390
  }
1391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1392
  @media (max-width: 1024px) {
1393
  .omnibox {
1394
  width: 200px;
@@ -1398,12 +1526,16 @@
1398
  display: none;
1399
  }
1400
 
 
 
 
 
1401
  /* Hide labels to save space */
1402
  }
1403
 
1404
  @media (max-width: 680px) {
1405
  .hdr {
1406
- padding: 0 10px;
1407
  gap: 6px;
1408
  }
1409
 
@@ -1415,21 +1547,61 @@
1415
  font-size: 1.1rem;
1416
  }
1417
 
1418
- #symbolSelect {
1419
- width: 120px;
 
 
 
 
1420
  }
1421
 
1422
- #timeframeSelect {
1423
- width: 55px;
 
1424
  }
1425
 
1426
- #horizonInput {
1427
- width: 50px;
 
 
1428
  }
1429
 
1430
  .btn-primary {
1431
- padding: 0 10px;
1432
- font-size: 0.7rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1433
  }
1434
  }
1435
 
@@ -1498,7 +1670,7 @@
1498
  }
1499
 
1500
  .compact-gauge-card {
1501
- background: var(--bg-glass-light);
1502
  backdrop-filter: blur(12px) saturate(180%);
1503
  -webkit-backdrop-filter: blur(12px) saturate(180%);
1504
  border: 1px solid var(--bdr-dim);
@@ -1509,17 +1681,17 @@
1509
  align-items: center;
1510
  gap: 6px;
1511
  min-width: 105px;
1512
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(255, 255, 255, 0.05);
1513
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1514
  pointer-events: auto;
1515
  cursor: default;
1516
  }
1517
 
1518
  .compact-gauge-card:hover {
1519
- transform: translateY(-2px);
1520
- background: var(--bg-glass);
1521
  border-color: var(--bdr-accent);
1522
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.18), 0 0 10px var(--accent-lo);
1523
  }
1524
 
1525
  .compact-gauge-title {
@@ -1749,7 +1921,7 @@
1749
  content: "";
1750
  position: fixed;
1751
  inset: 0;
1752
- z-index: -1;
1753
  pointer-events: none;
1754
  background:
1755
  linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
@@ -1766,44 +1938,76 @@
1766
  z-index: 1;
1767
  }
1768
 
1769
- .liquid-orb {
1770
  position: fixed;
1771
  border-radius: 999px;
1772
  pointer-events: none;
1773
- filter: blur(18px);
1774
  mix-blend-mode: screen;
1775
- opacity: 0.55;
1776
  z-index: 0;
1777
- animation: orb-float 16s ease-in-out infinite;
 
 
1778
  }
1779
 
1780
- .liquid-orb.orb-a {
1781
- top: 78px;
1782
- left: 42px;
1783
- width: 220px;
1784
- height: 220px;
1785
- background: radial-gradient(circle at 30% 30%, rgba(129, 211, 255, 0.75), rgba(129, 211, 255, 0.12) 55%, transparent 75%);
1786
  }
1787
 
1788
- .liquid-orb.orb-b {
1789
- top: 92px;
1790
- right: 120px;
1791
- width: 280px;
1792
- height: 280px;
1793
- background: radial-gradient(circle at 50% 50%, rgba(255, 144, 203, 0.42), rgba(255, 144, 203, 0.1) 58%, transparent 76%);
1794
- animation-duration: 19s;
 
1795
  }
1796
 
1797
- .liquid-orb.orb-c {
1798
- bottom: 66px;
1799
- right: 22%;
1800
- width: 240px;
1801
- height: 240px;
1802
- background: radial-gradient(circle at 50% 50%, rgba(54, 255, 204, 0.24), rgba(54, 255, 204, 0.08) 58%, transparent 78%);
1803
- animation-duration: 22s;
 
1804
  }
1805
 
1806
- @keyframes orb-float {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1807
 
1808
  0%,
1809
  100% {
@@ -1811,97 +2015,62 @@
1811
  }
1812
 
1813
  50% {
1814
- transform: translate3d(18px, -14px, 0) scale(1.06);
 
 
 
 
 
 
 
 
 
 
1815
  }
1816
  }
1817
 
1818
- .cursor-aura,
1819
- .cursor-dot {
1820
  position: fixed;
1821
- top: 0;
1822
- left: 0;
 
1823
  pointer-events: none;
1824
- z-index: 9999;
1825
- transform: translate3d(-50%, -50%, 0);
1826
- transition: opacity 0.25s ease, transform 0.25s ease, width 0.25s ease, height 0.25s ease, background 0.25s ease;
1827
  opacity: 0;
1828
- }
1829
-
1830
- .cursor-aura {
1831
- width: 92px;
1832
- height: 92px;
1833
- border-radius: 50%;
1834
- background: radial-gradient(circle, rgba(200, 242, 255, 0.84) 0%, rgba(143, 219, 255, 0.54) 34%, rgba(90, 189, 255, 0.24) 58%, rgba(90, 189, 255, 0.08) 72%, transparent 80%);
1835
- filter: blur(12px);
1836
  mix-blend-mode: screen;
1837
  }
1838
 
1839
- .cursor-dot {
1840
- width: 30px;
1841
- height: 30px;
1842
- display: flex;
1843
- align-items: center;
1844
- justify-content: center;
1845
  border-radius: 999px;
1846
- font-family: var(--ff-display);
1847
- font-size: 0.76rem;
1848
- font-weight: 800;
1849
- letter-spacing: 0.12em;
1850
- color: #127ed4;
1851
- text-shadow: 0 0 14px rgba(255, 255, 255, 0.9);
1852
- background: radial-gradient(circle, rgba(255, 255, 255, 0.96) 0%, rgba(216, 243, 255, 0.9) 58%, rgba(111, 202, 255, 0.28) 78%, transparent 82%);
1853
- border: 1px solid rgba(86, 176, 255, 0.4);
1854
- box-shadow: 0 0 26px rgba(71, 184, 255, 0.3);
1855
- }
1856
-
1857
- body.dark-theme .cursor-aura {
1858
- width: 220px;
1859
- height: 220px;
1860
- background: radial-gradient(circle, rgba(202, 245, 255, 0.28) 0%, rgba(133, 225, 255, 0.18) 24%, rgba(76, 201, 255, 0.08) 44%, rgba(24, 96, 130, 0.03) 62%, transparent 74%);
1861
- filter: blur(14px);
1862
- mix-blend-mode: screen;
1863
- }
1864
-
1865
- body.dark-theme .cursor-dot {
1866
- width: 30px;
1867
- height: 30px;
1868
- color: #f4fdff;
1869
- text-shadow: 0 0 18px rgba(114, 226, 255, 0.95);
1870
- background: radial-gradient(circle, rgba(255, 255, 255, 1) 0%, rgba(180, 239, 255, 0.96) 36%, rgba(86, 214, 255, 0.3) 70%, transparent 82%);
1871
- border-color: rgba(133, 224, 255, 0.56);
1872
- box-shadow: 0 0 26px rgba(76, 213, 255, 0.72);
1873
  }
1874
 
1875
- body.cursor-active .cursor-aura,
1876
- body.cursor-active .cursor-dot {
1877
  opacity: 1;
1878
  }
1879
 
1880
- body.cursor-press .cursor-aura {
1881
- width: 120px;
1882
- height: 120px;
1883
- opacity: 0.8;
1884
  }
1885
 
1886
- body.dark-theme.cursor-press .cursor-aura {
1887
- width: 250px;
1888
- height: 250px;
1889
- }
1890
-
1891
- body.cursor-press .cursor-dot {
1892
- transform: translate3d(-50%, -50%, 0) scale(0.82);
1893
- }
1894
-
1895
- body.cursor-hover .cursor-aura {
1896
- width: 112px;
1897
- height: 112px;
1898
- background: radial-gradient(circle, rgba(214, 246, 255, 0.9) 0%, rgba(163, 227, 255, 0.58) 34%, rgba(97, 188, 255, 0.24) 58%, rgba(97, 188, 255, 0.08) 74%, transparent 82%);
1899
- }
1900
-
1901
- body.dark-theme.cursor-hover .cursor-aura {
1902
- width: 250px;
1903
- height: 250px;
1904
- background: radial-gradient(circle, rgba(220, 247, 255, 0.32) 0%, rgba(144, 231, 255, 0.2) 26%, rgba(86, 214, 255, 0.09) 48%, rgba(24, 96, 130, 0.03) 66%, transparent 76%);
1905
  }
1906
 
1907
  .hdr,
@@ -2017,6 +2186,21 @@
2017
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.84), 0 18px 34px rgba(64, 104, 176, 0.12), 0 0 0 6px rgba(78, 156, 255, 0.06);
2018
  }
2019
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2020
  .btn-primary {
2021
  background: linear-gradient(135deg, rgba(18, 120, 255, 0.98) 0%, rgba(72, 173, 255, 0.88) 55%, rgba(111, 223, 255, 0.86) 100%);
2022
  color: #f7fbff;
@@ -2031,6 +2215,18 @@
2031
  filter: saturate(1.08);
2032
  }
2033
 
 
 
 
 
 
 
 
 
 
 
 
 
2034
  .btn-icon::before,
2035
  .btn-theme::before,
2036
  .btn-primary::before,
@@ -2058,22 +2254,56 @@
2058
  background:
2059
  radial-gradient(circle at top left, rgba(255, 255, 255, 0.3), transparent 30%),
2060
  linear-gradient(180deg, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0.12) 100%);
2061
- box-shadow: 0 36px 90px rgba(31, 57, 102, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.78);
2062
  backdrop-filter: blur(22px) saturate(180%);
2063
  -webkit-backdrop-filter: blur(22px) saturate(180%);
2064
  isolation: isolate;
2065
  }
2066
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2067
  body.dark-theme .main {
2068
  border-color: rgba(124, 179, 255, 0.1);
2069
  background:
2070
  radial-gradient(circle at top left, rgba(130, 177, 255, 0.08), transparent 30%),
2071
  linear-gradient(180deg, rgba(9, 16, 34, 0.52) 0%, rgba(7, 14, 29, 0.32) 100%);
2072
- box-shadow: 0 38px 100px rgba(1, 8, 20, 0.5), inset 0 1px 0 rgba(179, 224, 255, 0.08);
 
 
 
 
 
 
2073
  }
2074
 
2075
  .chart-bg-overlay {
 
2076
  inset: 0;
 
2077
  opacity: 1;
2078
  background-image:
2079
  linear-gradient(90deg, rgba(237, 244, 255, 0.94) 0%, rgba(237, 244, 255, 0.82) 24%, rgba(237, 244, 255, 0.42) 54%, rgba(237, 244, 255, 0.18) 100%),
@@ -2092,51 +2322,64 @@
2092
  position: absolute;
2093
  inset: 0;
2094
  pointer-events: none;
2095
- background: var(--light-bg-image) no-repeat left center/cover;
2096
- opacity: 0.22;
2097
- mix-blend-mode: multiply;
2098
- animation: hologram-drift 20s ease-in-out infinite;
 
2099
  }
2100
 
2101
  .chart-bg-overlay::after {
2102
  background:
2103
  linear-gradient(180deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.02) 38%, rgba(113, 225, 255, 0.04) 100%),
 
2104
  radial-gradient(circle at 46% 58%, rgba(82, 221, 255, 0.12), transparent 7%),
2105
  radial-gradient(circle at 72% 46%, rgba(126, 168, 255, 0.08), transparent 10%),
2106
  repeating-linear-gradient(90deg, rgba(96, 182, 255, 0.06) 0 1px, transparent 1px 110px),
2107
  repeating-linear-gradient(180deg, rgba(96, 182, 255, 0.04) 0 1px, transparent 1px 78px);
2108
- opacity: 0.34;
2109
  mask-image: linear-gradient(to right, rgba(0, 0, 0, 0.92) 0%, rgba(0, 0, 0, 0.6) 64%, transparent 100%);
2110
  -webkit-mask-image: linear-gradient(to right, rgba(0, 0, 0, 0.92) 0%, rgba(0, 0, 0, 0.6) 64%, transparent 100%);
2111
- animation: data-grid-drift 18s linear infinite, scan-sweep 8s ease-in-out infinite;
2112
  }
2113
 
2114
  body.dark-theme .chart-bg-overlay {
2115
  background-image:
2116
  linear-gradient(90deg, rgba(7, 15, 32, 0.76) 0%, rgba(7, 15, 32, 0.44) 28%, rgba(7, 15, 32, 0.14) 56%, rgba(7, 15, 32, 0.04) 100%),
2117
  radial-gradient(circle at 22% 58%, rgba(71, 196, 255, 0.18), transparent 24%),
2118
- radial-gradient(circle at 74% 16%, rgba(110, 146, 255, 0.12), transparent 18%),
2119
- var(--dark-bg-image);
2120
- background-size: auto, auto, auto, cover;
2121
- background-position: center, 22% 58%, 74% 16%, left center;
2122
  }
2123
 
2124
  body.dark-theme .chart-bg-overlay::before {
2125
- background:
2126
- linear-gradient(90deg, rgba(18, 32, 64, 0.24) 0%, rgba(18, 32, 64, 0.12) 35%, rgba(18, 32, 64, 0.04) 62%, transparent 100%),
2127
- radial-gradient(circle at 31% 65%, rgba(92, 212, 255, 0.16), transparent 16%),
2128
- radial-gradient(circle at 29% 34%, rgba(107, 173, 255, 0.12), transparent 18%),
2129
- linear-gradient(90deg, transparent 0%, rgba(79, 179, 255, 0.08) 18%, transparent 36%, transparent 100%),
2130
- var(--dark-bg-image);
2131
- background-size: auto, auto, auto, auto, cover;
2132
- background-position: center, 31% 65%, 29% 34%, center, left center;
2133
- background-repeat: no-repeat;
2134
- opacity: 0.76;
2135
- animation: hologram-drift 20s ease-in-out infinite;
2136
  }
2137
 
2138
  body.dark-theme .chart-bg-overlay::after {
2139
- opacity: 0.28;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2140
  }
2141
 
2142
  @keyframes hologram-drift {
@@ -2452,7 +2695,11 @@
2452
 
2453
  .cursor-aura,
2454
  .cursor-dot,
2455
- .liquid-orb {
 
 
 
 
2456
  display: none;
2457
  }
2458
 
@@ -2485,15 +2732,80 @@
2485
  top: 68px;
2486
  }
2487
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2488
  </style>
2489
  </head>
2490
 
2491
  <body>
2492
- <div class="liquid-orb orb-a" aria-hidden="true"></div>
2493
- <div class="liquid-orb orb-b" aria-hidden="true"></div>
2494
- <div class="liquid-orb orb-c" aria-hidden="true"></div>
2495
- <div class="cursor-aura" id="cursorAura" aria-hidden="true"></div>
2496
- <div class="cursor-dot" id="cursorDot" aria-hidden="true">AI</div>
 
 
2497
  <div id="app">
2498
 
2499
  <!-- ── HEADER ───────────────────────────────── -->
@@ -2761,8 +3073,9 @@
2761
  const analysisPanel = document.getElementById('analysisPanel');
2762
  const marketStatusBar = document.getElementById('marketStatusBar');
2763
  const indicatorSelect = document.getElementById('indicatorSelect');
2764
- const cursorAura = document.getElementById('cursorAura');
2765
- const cursorDot = document.getElementById('cursorDot');
 
2766
 
2767
  /* ── State ─────────────────────────────────── */
2768
  let currentSymbol = 'XAUUSD';
@@ -2777,32 +3090,156 @@
2777
 
2778
  /* ── Indicator Calculation Helpers ────────── */
2779
  /* ── WebSocket Management ────────────────────── */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2780
  (() => {
2781
- if (!cursorAura || !cursorDot || window.matchMedia('(pointer: coarse)').matches) return;
 
 
 
2782
 
2783
- let mouseX = window.innerWidth / 2;
2784
- let mouseY = window.innerHeight / 2;
2785
- let auraX = mouseX;
2786
- let auraY = mouseY;
2787
- let rafId = 0;
2788
  const interactiveSelector = 'button, input, select, .search-item, .compact-gauge-card, .explorer-symbol-card, .explorer-cat-item, .dash-close, .dash-col';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2789
 
2790
- function renderCursor() {
2791
- auraX += (mouseX - auraX) * 0.14;
2792
- auraY += (mouseY - auraY) * 0.14;
2793
- cursorAura.style.transform = `translate3d(${auraX}px, ${auraY}px, 0) translate(-50%, -50%)`;
2794
- cursorDot.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0) translate(-50%, -50%)`;
2795
- rafId = requestAnimationFrame(renderCursor);
 
 
 
 
 
2796
  }
2797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2798
  document.addEventListener('mousemove', (event) => {
2799
- mouseX = event.clientX;
2800
- mouseY = event.clientY;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2801
  document.body.classList.add('cursor-active');
2802
- if (!rafId) rafId = requestAnimationFrame(renderCursor);
2803
  }, { passive: true });
2804
 
2805
  document.addEventListener('mouseleave', () => {
 
 
2806
  document.body.classList.remove('cursor-active');
2807
  });
2808
 
@@ -3306,7 +3743,7 @@
3306
  </div>
3307
 
3308
  <!-- Dashboard Body Scaler -->
3309
- <div class="dash-body-scaler" style="flex:1; overflow-y:auto; overflow-x:hidden; display:flex; flex-direction:column;">
3310
  <div class="dash-body" style="transform-origin: top center; transition: transform 0.2s ease;">
3311
 
3312
  <!-- TOP ROW: 3 Big Gauges -->
@@ -3824,15 +4261,14 @@
3824
 
3825
  let scaleW = windowWidth / targetWidth;
3826
  let scaleH = (windowHeight - 80) / targetHeight; // 80px for header
3827
- let scale = Math.min(scaleW, scaleH);
3828
 
3829
- // Clamp scale
3830
- if (scale > 1.1) scale = 1.1;
3831
- if (scale < 0.45) scale = 0.45;
3832
 
3833
  body.style.transform = `scale(${scale})`;
3834
- body.style.width = `${100 / scale}%`;
3835
- // body.style.height = `${100 / scale}%`;
 
3836
  }
3837
 
3838
  /* ── Resize handler ────────────────────────── */
@@ -3850,6 +4286,11 @@
3850
  function applyTheme(theme) {
3851
  const isDark = theme === 'dark';
3852
  document.body.classList.toggle('dark-theme', isDark);
 
 
 
 
 
3853
 
3854
  if (chart) {
3855
  chart.applyOptions({
 
88
  --logo-primary: #2e8dff;
89
  --logo-secondary: #5dd4ff;
90
  --logo-glow: rgba(46, 141, 255, 0.36);
91
+ --panel-shadow: 0 36px 90px rgba(31, 57, 102, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.78);
92
+ --panel-shadow-dark: 0 38px 100px rgba(1, 8, 20, 0.5), inset 0 1px 0 rgba(179, 224, 255, 0.08);
93
+ --focus-ring: 0 0 0 3px rgba(78, 156, 255, 0.12), 0 0 0 6px rgba(78, 156, 255, 0.08);
94
 
95
+ --ai-bg-image: url("AIBG.png");
96
+ --ai-bg-opacity: 0.3;
97
+ --ai-bg-height: clamp(360px, 68vh, 820px);
98
+ --ai-bg-position-x: clamp(18px, 2vw, 34px);
99
+ --ai-bg-position-y: clamp(18px, 2vw, 28px);
100
 
101
  color-scheme: light;
102
  }
 
174
  body::before {
175
  content: "";
176
  position: fixed;
177
+ inset: -14%;
178
+ z-index: 0;
179
+ pointer-events: none;
180
+ background:
181
+ radial-gradient(circle at 14% 18%, rgba(108, 198, 255, 0.24), transparent 18%),
182
+ radial-gradient(circle at 82% 14%, rgba(125, 230, 255, 0.18), transparent 20%),
183
+ radial-gradient(circle at 28% 78%, rgba(255, 152, 214, 0.16), transparent 18%),
184
+ conic-gradient(from 160deg at 50% 50%, rgba(75, 184, 255, 0.08), rgba(255, 255, 255, 0.02), rgba(106, 240, 255, 0.12), rgba(75, 184, 255, 0.08));
185
+ filter: blur(58px) saturate(135%);
186
+ opacity: 0.95;
187
+ animation: ambient-pan 24s ease-in-out infinite alternate;
188
  }
189
 
190
  body.dark-theme::before {
191
+ background:
192
+ radial-gradient(circle at 16% 18%, rgba(44, 170, 255, 0.26), transparent 18%),
193
+ radial-gradient(circle at 82% 12%, rgba(52, 235, 255, 0.18), transparent 20%),
194
+ radial-gradient(circle at 32% 82%, rgba(23, 112, 201, 0.16), transparent 22%),
195
+ conic-gradient(from 140deg at 50% 50%, rgba(21, 85, 160, 0.1), rgba(3, 12, 28, 0.02), rgba(24, 193, 255, 0.1), rgba(21, 85, 160, 0.1));
196
+ opacity: 1;
197
  }
198
 
199
  /* ═══════════════════════════════════════════════
 
331
  align-items: center;
332
  gap: 10px;
333
  flex: 1;
334
+ min-width: 0;
335
  justify-content: flex-end;
336
  flex-wrap: nowrap;
337
  /* Keep tight, but handle overflow via media queries */
 
407
  background: rgba(255, 255, 255, 0.08);
408
  }
409
 
410
+ .search-item:focus-visible {
411
+ outline: none;
412
+ background: rgba(102, 176, 255, 0.1);
413
+ box-shadow: inset 0 0 0 1px rgba(98, 172, 255, 0.34);
414
+ }
415
+
416
  .search-item .sym {
417
  font-family: var(--ff-mono);
418
  font-weight: 700;
 
469
  display: flex;
470
  flex-direction: column;
471
  gap: 3px;
472
+ min-width: 0;
473
  }
474
 
475
  .ctrl-label {
 
550
  /* primary button */
551
  .btn-primary {
552
  height: var(--ctrl-h);
553
+ min-width: 126px;
554
  padding: 0 18px;
555
  background: var(--accent-lo);
556
  border: 1px solid var(--bdr-accent);
 
588
  .btn-icon {
589
  height: var(--ctrl-h);
590
  width: var(--ctrl-h);
591
+ flex-shrink: 0;
592
  display: flex;
593
  align-items: center;
594
  justify-content: center;
 
611
  border-color: var(--bdr-muted);
612
  background: var(--bg-control-hov);
613
  color: var(--txt-bright);
614
+ transform: translateY(-1px);
615
+ box-shadow: 0 12px 24px rgba(58, 92, 146, 0.12);
616
  }
617
 
618
  .btn-icon:active {
 
744
  flex: 1;
745
  display: flex;
746
  flex-direction: column;
747
+ width: 100%;
748
+ max-height: 100%;
749
  overflow-x: hidden;
750
  overflow-y: auto;
751
  min-height: 0;
752
  overscroll-behavior: contain;
753
  }
754
 
755
+ .dash-body-scaler {
756
+ flex: 1;
757
+ overflow: hidden;
758
+ overflow-x: hidden;
759
+ display: flex;
760
+ justify-content: center;
761
+ align-items: flex-start;
762
+ padding-bottom: 12px;
763
+ }
764
+
765
  /* ── TOP: 3 Big Gauges Row ── */
766
  .dash-gauges-hero {
767
  display: flex;
 
870
  /* Theme Toggle Button */
871
  .btn-theme {
872
  height: var(--ctrl-h);
873
+ width: var(--ctrl-h);
874
+ flex-shrink: 0;
875
+ justify-content: center;
876
+ padding: 0;
877
  background: var(--bg-control);
878
  border: 1px solid var(--bdr-base);
879
  color: var(--txt-primary);
 
893
  .btn-theme svg {
894
  width: 16px;
895
  height: 16px;
896
+ transition: transform 0.25s ease;
897
+ }
898
+
899
+ .btn-theme:hover svg {
900
+ transform: rotate(12deg) scale(1.04);
901
  }
902
 
903
  .gauge-hero-signal {
 
1188
  opacity: 0.35;
1189
  text-transform: uppercase;
1190
  white-space: nowrap;
1191
+ transition: opacity 0.3s ease, transform 0.3s ease;
1192
+ animation: logo-float 8s ease-in-out infinite;
1193
  }
1194
 
1195
  body.dark-theme .chart-logo-overlay {
1196
  opacity: 0.55;
1197
  }
1198
 
1199
+ @keyframes logo-float {
1200
+
1201
+ 0%,
1202
+ 100% {
1203
+ transform: translate3d(0, 0, 0);
1204
+ }
1205
+
1206
+ 50% {
1207
+ transform: translate3d(0, -6px, 0);
1208
+ }
1209
+ }
1210
+
1211
+ @keyframes ambient-pan {
1212
+
1213
+ 0% {
1214
+ transform: translate3d(-2%, -1%, 0) scale(1);
1215
+ }
1216
+
1217
+ 50% {
1218
+ transform: translate3d(2%, 2%, 0) scale(1.04);
1219
+ }
1220
+
1221
+ 100% {
1222
+ transform: translate3d(-1%, 4%, 0) scale(1.08);
1223
+ }
1224
+ }
1225
+
1226
  /* ── Terminal Loader Overlay (Strict Isolation) ── */
1227
  .terminal-loader-overlay {
1228
  position: absolute;
 
1466
  }
1467
  }
1468
 
1469
+ @media (max-width: 1280px) {
1470
+ .hdr {
1471
+ gap: 12px;
1472
+ }
1473
+
1474
+ .market-status-bar {
1475
+ gap: 12px;
1476
+ margin-right: 8px;
1477
+ }
1478
+
1479
+ .omnibox {
1480
+ width: clamp(180px, 20vw, 240px);
1481
+ }
1482
+
1483
+ #symbolSelect {
1484
+ width: 240px;
1485
+ }
1486
+ }
1487
+
1488
+ @media (max-width: 1120px) {
1489
+ .hdr {
1490
+ height: auto;
1491
+ flex-wrap: wrap;
1492
+ align-items: flex-start;
1493
+ padding: 14px 16px;
1494
+ }
1495
+
1496
+ .hdr-divider {
1497
+ display: none;
1498
+ }
1499
+
1500
+ .market-status-bar {
1501
+ order: 3;
1502
+ width: 100%;
1503
+ margin-right: 0;
1504
+ padding: 6px 10px;
1505
+ justify-content: flex-start;
1506
+ flex-wrap: wrap;
1507
+ }
1508
+
1509
+ .ctrls {
1510
+ width: 100%;
1511
+ justify-content: flex-start;
1512
+ flex-wrap: wrap;
1513
+ }
1514
+
1515
+ .ctrl-unit {
1516
+ min-width: fit-content;
1517
+ }
1518
+ }
1519
+
1520
  @media (max-width: 1024px) {
1521
  .omnibox {
1522
  width: 200px;
 
1526
  display: none;
1527
  }
1528
 
1529
+ #symbolSelect {
1530
+ width: 200px;
1531
+ }
1532
+
1533
  /* Hide labels to save space */
1534
  }
1535
 
1536
  @media (max-width: 680px) {
1537
  .hdr {
1538
+ padding: 12px 10px;
1539
  gap: 6px;
1540
  }
1541
 
 
1547
  font-size: 1.1rem;
1548
  }
1549
 
1550
+ .ctrls {
1551
+ gap: 8px;
1552
+ }
1553
+
1554
+ .ctrl-unit {
1555
+ width: calc(50% - 4px);
1556
  }
1557
 
1558
+ .omnibox,
1559
+ .ctrl-unit:first-of-type {
1560
+ width: 100%;
1561
  }
1562
 
1563
+ #timeframeSelect,
1564
+ #horizonInput,
1565
+ #indicatorSelect {
1566
+ width: 100% !important;
1567
  }
1568
 
1569
  .btn-primary {
1570
+ min-width: 0;
1571
+ flex: 1 1 140px;
1572
+ padding: 0 14px;
1573
+ font-size: 0.8rem;
1574
+ }
1575
+
1576
+ .btn-icon,
1577
+ .btn-theme {
1578
+ flex: 0 0 var(--ctrl-h);
1579
+ }
1580
+ }
1581
+
1582
+ @media (max-width: 560px) {
1583
+ .hdr {
1584
+ margin: 8px 8px 0;
1585
+ padding: 12px;
1586
+ border-radius: 20px;
1587
+ }
1588
+
1589
+ .logo-mark {
1590
+ width: 42px;
1591
+ height: 42px;
1592
+ }
1593
+
1594
+ .logo-name {
1595
+ font-size: 1rem;
1596
+ }
1597
+
1598
+ .market-status-bar {
1599
+ gap: 10px;
1600
+ font-size: 0.68rem;
1601
+ }
1602
+
1603
+ .ctrl-unit {
1604
+ width: 100%;
1605
  }
1606
  }
1607
 
 
1670
  }
1671
 
1672
  .compact-gauge-card {
1673
+ background: linear-gradient(180deg, color-mix(in srgb, var(--bg-glass-light) 88%, white 12%) 0%, var(--bg-glass-light) 100%);
1674
  backdrop-filter: blur(12px) saturate(180%);
1675
  -webkit-backdrop-filter: blur(12px) saturate(180%);
1676
  border: 1px solid var(--bdr-dim);
 
1681
  align-items: center;
1682
  gap: 6px;
1683
  min-width: 105px;
1684
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.22);
1685
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1686
  pointer-events: auto;
1687
  cursor: default;
1688
  }
1689
 
1690
  .compact-gauge-card:hover {
1691
+ transform: translateY(-4px) scale(1.01);
1692
+ background: linear-gradient(180deg, color-mix(in srgb, var(--bg-glass) 82%, white 18%) 0%, var(--bg-glass) 100%);
1693
  border-color: var(--bdr-accent);
1694
+ box-shadow: 0 16px 32px rgba(0, 0, 0, 0.16), 0 0 0 8px rgba(90, 165, 255, 0.05), 0 0 16px var(--accent-lo);
1695
  }
1696
 
1697
  .compact-gauge-title {
 
1921
  content: "";
1922
  position: fixed;
1923
  inset: 0;
1924
+ z-index: 0;
1925
  pointer-events: none;
1926
  background:
1927
  linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
 
1938
  z-index: 1;
1939
  }
1940
 
1941
+ .ambient-orb {
1942
  position: fixed;
1943
  border-radius: 999px;
1944
  pointer-events: none;
 
1945
  mix-blend-mode: screen;
 
1946
  z-index: 0;
1947
+ opacity: 0.72;
1948
+ filter: blur(20px);
1949
+ animation: orb-drift 18s ease-in-out infinite;
1950
  }
1951
 
1952
+ .ambient-orb.orb-a {
1953
+ top: 88px;
1954
+ left: 48px;
1955
+ width: 260px;
1956
+ height: 260px;
1957
+ background: radial-gradient(circle at 30% 30%, rgba(136, 226, 255, 0.7), rgba(136, 226, 255, 0.18) 52%, transparent 74%);
1958
  }
1959
 
1960
+ .ambient-orb.orb-b {
1961
+ top: 120px;
1962
+ right: 7vw;
1963
+ width: 340px;
1964
+ height: 340px;
1965
+ background: radial-gradient(circle at 50% 50%, rgba(92, 178, 255, 0.4), rgba(92, 178, 255, 0.12) 58%, transparent 76%);
1966
+ animation-duration: 22s;
1967
+ animation-delay: -6s;
1968
  }
1969
 
1970
+ .ambient-orb.orb-c {
1971
+ bottom: 5vh;
1972
+ left: 28%;
1973
+ width: 420px;
1974
+ height: 420px;
1975
+ background: radial-gradient(circle at 50% 50%, rgba(116, 255, 233, 0.22), rgba(116, 255, 233, 0.08) 58%, transparent 78%);
1976
+ animation-duration: 26s;
1977
+ animation-delay: -11s;
1978
  }
1979
 
1980
+ .ambient-beam {
1981
+ position: fixed;
1982
+ pointer-events: none;
1983
+ z-index: 0;
1984
+ border-radius: 999px;
1985
+ opacity: 0.52;
1986
+ filter: blur(28px);
1987
+ transform-origin: center;
1988
+ animation: beam-sweep 20s ease-in-out infinite alternate;
1989
+ mix-blend-mode: screen;
1990
+ }
1991
+
1992
+ .ambient-beam.beam-a {
1993
+ top: 10vh;
1994
+ left: 18vw;
1995
+ width: 42vw;
1996
+ height: 14vh;
1997
+ background: linear-gradient(90deg, transparent, rgba(99, 203, 255, 0.2), rgba(99, 203, 255, 0.04), transparent);
1998
+ }
1999
+
2000
+ .ambient-beam.beam-b {
2001
+ bottom: 16vh;
2002
+ right: 6vw;
2003
+ width: 36vw;
2004
+ height: 12vh;
2005
+ background: linear-gradient(90deg, transparent, rgba(78, 244, 255, 0.16), rgba(78, 244, 255, 0.04), transparent);
2006
+ animation-duration: 24s;
2007
+ animation-delay: -8s;
2008
+ }
2009
+
2010
+ @keyframes orb-drift {
2011
 
2012
  0%,
2013
  100% {
 
2015
  }
2016
 
2017
  50% {
2018
+ transform: translate3d(22px, -18px, 0) scale(1.08);
2019
+ }
2020
+ }
2021
+
2022
+ @keyframes beam-sweep {
2023
+ 0% {
2024
+ transform: translate3d(-3vw, -1vh, 0) rotate(-8deg) scaleX(0.92);
2025
+ }
2026
+
2027
+ 100% {
2028
+ transform: translate3d(4vw, 3vh, 0) rotate(7deg) scaleX(1.08);
2029
  }
2030
  }
2031
 
2032
+ .cursor-trail-canvas {
 
2033
  position: fixed;
2034
+ inset: 0;
2035
+ width: 100%;
2036
+ height: 100%;
2037
  pointer-events: none;
2038
+ z-index: 9998;
 
 
2039
  opacity: 0;
2040
+ transition: opacity 0.16s ease;
 
 
 
 
 
 
 
2041
  mix-blend-mode: screen;
2042
  }
2043
 
2044
+ .cursor-core {
2045
+ position: fixed;
2046
+ top: 0;
2047
+ left: 0;
2048
+ width: 18px;
2049
+ height: 18px;
2050
  border-radius: 999px;
2051
+ pointer-events: none;
2052
+ z-index: 9999;
2053
+ transform: translate3d(-50%, -50%, 0);
2054
+ opacity: 0;
2055
+ background:
2056
+ radial-gradient(circle, rgba(255, 255, 255, 0.98) 0%, rgba(162, 245, 255, 0.88) 34%, rgba(72, 213, 255, 0.42) 62%, rgba(72, 213, 255, 0) 78%);
2057
+ box-shadow: 0 0 22px rgba(72, 213, 255, 0.54), 0 0 48px rgba(72, 213, 255, 0.22);
2058
+ transition: opacity 0.16s ease, width 0.16s ease, height 0.16s ease;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2059
  }
2060
 
2061
+ body.cursor-active .cursor-trail-canvas,
2062
+ body.cursor-active .cursor-core {
2063
  opacity: 1;
2064
  }
2065
 
2066
+ body.cursor-hover .cursor-core {
2067
+ width: 24px;
2068
+ height: 24px;
 
2069
  }
2070
 
2071
+ body.cursor-press .cursor-core {
2072
+ width: 14px;
2073
+ height: 14px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2074
  }
2075
 
2076
  .hdr,
 
2186
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.84), 0 18px 34px rgba(64, 104, 176, 0.12), 0 0 0 6px rgba(78, 156, 255, 0.06);
2187
  }
2188
 
2189
+ .omnibox input:focus-visible,
2190
+ .k-select:focus-visible,
2191
+ .k-input:focus-visible,
2192
+ .btn-icon:focus-visible,
2193
+ .btn-theme:focus-visible,
2194
+ .btn-primary:focus-visible,
2195
+ .dash-close:focus-visible,
2196
+ .explorer-search input:focus-visible,
2197
+ .explorer-cat-item:focus-visible,
2198
+ .explorer-symbol-card:focus-visible {
2199
+ outline: none;
2200
+ border-color: rgba(88, 170, 255, 0.72);
2201
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.88), var(--focus-ring);
2202
+ }
2203
+
2204
  .btn-primary {
2205
  background: linear-gradient(135deg, rgba(18, 120, 255, 0.98) 0%, rgba(72, 173, 255, 0.88) 55%, rgba(111, 223, 255, 0.86) 100%);
2206
  color: #f7fbff;
 
2215
  filter: saturate(1.08);
2216
  }
2217
 
2218
+ button:active,
2219
+ .nav-q-btn:active,
2220
+ .dash-close:active {
2221
+ transform: translateY(1px) scale(0.96);
2222
+ box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(40, 80, 140, 0.14);
2223
+ filter: saturate(0.98);
2224
+ }
2225
+
2226
+ .btn-primary:focus-visible {
2227
+ box-shadow: 0 20px 42px rgba(34, 123, 255, 0.28), 0 0 0 8px rgba(78, 156, 255, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.48);
2228
+ }
2229
+
2230
  .btn-icon::before,
2231
  .btn-theme::before,
2232
  .btn-primary::before,
 
2254
  background:
2255
  radial-gradient(circle at top left, rgba(255, 255, 255, 0.3), transparent 30%),
2256
  linear-gradient(180deg, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0.12) 100%);
2257
+ box-shadow: var(--panel-shadow);
2258
  backdrop-filter: blur(22px) saturate(180%);
2259
  -webkit-backdrop-filter: blur(22px) saturate(180%);
2260
  isolation: isolate;
2261
  }
2262
 
2263
+ .main::before {
2264
+ content: "";
2265
+ position: absolute;
2266
+ inset: 1px;
2267
+ border-radius: inherit;
2268
+ pointer-events: none;
2269
+ z-index: 0;
2270
+ background:
2271
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.28), transparent 28%),
2272
+ radial-gradient(circle at bottom right, rgba(94, 195, 255, 0.1), transparent 26%);
2273
+ opacity: 0.85;
2274
+ }
2275
+
2276
+ .main::after {
2277
+ content: "";
2278
+ position: absolute;
2279
+ inset: 0;
2280
+ border-radius: inherit;
2281
+ pointer-events: none;
2282
+ z-index: 6;
2283
+ border: 1px solid rgba(255, 255, 255, 0.18);
2284
+ mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent 30%, transparent 72%, rgba(0, 0, 0, 0.75));
2285
+ -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent 30%, transparent 72%, rgba(0, 0, 0, 0.75));
2286
+ opacity: 0.9;
2287
+ }
2288
+
2289
  body.dark-theme .main {
2290
  border-color: rgba(124, 179, 255, 0.1);
2291
  background:
2292
  radial-gradient(circle at top left, rgba(130, 177, 255, 0.08), transparent 30%),
2293
  linear-gradient(180deg, rgba(9, 16, 34, 0.52) 0%, rgba(7, 14, 29, 0.32) 100%);
2294
+ box-shadow: var(--panel-shadow-dark);
2295
+ }
2296
+
2297
+ body.dark-theme .main::before {
2298
+ background:
2299
+ radial-gradient(circle at top left, rgba(84, 170, 255, 0.12), transparent 28%),
2300
+ radial-gradient(circle at bottom right, rgba(34, 211, 238, 0.12), transparent 26%);
2301
  }
2302
 
2303
  .chart-bg-overlay {
2304
+ position: absolute;
2305
  inset: 0;
2306
+ z-index: 1;
2307
  opacity: 1;
2308
  background-image:
2309
  linear-gradient(90deg, rgba(237, 244, 255, 0.94) 0%, rgba(237, 244, 255, 0.82) 24%, rgba(237, 244, 255, 0.42) 54%, rgba(237, 244, 255, 0.18) 100%),
 
2322
  position: absolute;
2323
  inset: 0;
2324
  pointer-events: none;
2325
+ background-image: var(--ai-bg-image);
2326
+ background-repeat: no-repeat;
2327
+ background-position: left var(--ai-bg-position-x) bottom var(--ai-bg-position-y);
2328
+ background-size: auto var(--ai-bg-height);
2329
+ opacity: var(--ai-bg-opacity);
2330
  }
2331
 
2332
  .chart-bg-overlay::after {
2333
  background:
2334
  linear-gradient(180deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.02) 38%, rgba(113, 225, 255, 0.04) 100%),
2335
+ linear-gradient(120deg, transparent 18%, rgba(118, 240, 255, 0.1) 42%, transparent 66%),
2336
  radial-gradient(circle at 46% 58%, rgba(82, 221, 255, 0.12), transparent 7%),
2337
  radial-gradient(circle at 72% 46%, rgba(126, 168, 255, 0.08), transparent 10%),
2338
  repeating-linear-gradient(90deg, rgba(96, 182, 255, 0.06) 0 1px, transparent 1px 110px),
2339
  repeating-linear-gradient(180deg, rgba(96, 182, 255, 0.04) 0 1px, transparent 1px 78px);
2340
+ opacity: 0.42;
2341
  mask-image: linear-gradient(to right, rgba(0, 0, 0, 0.92) 0%, rgba(0, 0, 0, 0.6) 64%, transparent 100%);
2342
  -webkit-mask-image: linear-gradient(to right, rgba(0, 0, 0, 0.92) 0%, rgba(0, 0, 0, 0.6) 64%, transparent 100%);
2343
+ animation: data-grid-drift 18s linear infinite, scan-sweep 8s ease-in-out infinite, chart-energy-pulse 11s ease-in-out infinite;
2344
  }
2345
 
2346
  body.dark-theme .chart-bg-overlay {
2347
  background-image:
2348
  linear-gradient(90deg, rgba(7, 15, 32, 0.76) 0%, rgba(7, 15, 32, 0.44) 28%, rgba(7, 15, 32, 0.14) 56%, rgba(7, 15, 32, 0.04) 100%),
2349
  radial-gradient(circle at 22% 58%, rgba(71, 196, 255, 0.18), transparent 24%),
2350
+ radial-gradient(circle at 74% 16%, rgba(110, 146, 255, 0.12), transparent 18%);
2351
+ background-size: auto, auto, auto;
2352
+ background-position: center, 22% 58%, 74% 16%;
 
2353
  }
2354
 
2355
  body.dark-theme .chart-bg-overlay::before {
2356
+ opacity: var(--ai-bg-opacity);
 
 
 
 
 
 
 
 
 
 
2357
  }
2358
 
2359
  body.dark-theme .chart-bg-overlay::after {
2360
+ opacity: 0.34;
2361
+ }
2362
+
2363
+ @keyframes chart-aurora-drift {
2364
+ 0% {
2365
+ transform: translate3d(0, 0, 0) scale(1);
2366
+ }
2367
+
2368
+ 100% {
2369
+ transform: translate3d(-1.5%, 1.2%, 0) scale(1.03);
2370
+ }
2371
+ }
2372
+
2373
+ @keyframes chart-energy-pulse {
2374
+
2375
+ 0%,
2376
+ 100% {
2377
+ opacity: 0.34;
2378
+ }
2379
+
2380
+ 50% {
2381
+ opacity: 0.5;
2382
+ }
2383
  }
2384
 
2385
  @keyframes hologram-drift {
 
2695
 
2696
  .cursor-aura,
2697
  .cursor-dot,
2698
+ .liquid-orb,
2699
+ .cursor-trail-canvas,
2700
+ .cursor-core,
2701
+ .ambient-orb,
2702
+ .ambient-beam {
2703
  display: none;
2704
  }
2705
 
 
2732
  top: 68px;
2733
  }
2734
  }
2735
+
2736
+ @media (max-width: 560px) {
2737
+ .btn-primary,
2738
+ .btn-icon,
2739
+ .btn-theme {
2740
+ height: 40px;
2741
+ }
2742
+
2743
+ .chart-gauges-container {
2744
+ left: 10px;
2745
+ right: 10px;
2746
+ gap: 6px;
2747
+ }
2748
+
2749
+ .compact-gauge-card {
2750
+ min-width: calc(33.333% - 4px);
2751
+ flex: 1 1 calc(33.333% - 4px);
2752
+ padding: 8px 10px;
2753
+ }
2754
+
2755
+ .compact-gauge-svg-wrap {
2756
+ width: 58px;
2757
+ height: 40px;
2758
+ }
2759
+ }
2760
+
2761
+ @media (hover: none), (pointer: coarse) {
2762
+ .cursor-aura,
2763
+ .cursor-dot,
2764
+ .cursor-trail-canvas,
2765
+ .cursor-core {
2766
+ display: none !important;
2767
+ }
2768
+
2769
+ .btn-icon:hover,
2770
+ .btn-theme:hover,
2771
+ .btn-primary:hover,
2772
+ .compact-gauge-card:hover,
2773
+ .explorer-symbol-card:hover {
2774
+ transform: none;
2775
+ }
2776
+ }
2777
+
2778
+ @media (prefers-reduced-motion: reduce) {
2779
+ *,
2780
+ *::before,
2781
+ *::after {
2782
+ animation-duration: 0.01ms !important;
2783
+ animation-iteration-count: 1 !important;
2784
+ transition-duration: 0.01ms !important;
2785
+ scroll-behavior: auto !important;
2786
+ }
2787
+
2788
+ .cursor-aura,
2789
+ .cursor-dot,
2790
+ .liquid-orb,
2791
+ .cursor-trail-canvas,
2792
+ .cursor-core,
2793
+ .ambient-orb,
2794
+ .ambient-beam {
2795
+ display: none !important;
2796
+ }
2797
+ }
2798
  </style>
2799
  </head>
2800
 
2801
  <body>
2802
+ <div class="ambient-orb orb-a" aria-hidden="true"></div>
2803
+ <div class="ambient-orb orb-b" aria-hidden="true"></div>
2804
+ <div class="ambient-orb orb-c" aria-hidden="true"></div>
2805
+ <div class="ambient-beam beam-a" aria-hidden="true"></div>
2806
+ <div class="ambient-beam beam-b" aria-hidden="true"></div>
2807
+ <canvas class="cursor-trail-canvas" id="cursorTrailCanvas" aria-hidden="true"></canvas>
2808
+ <div class="cursor-core" id="cursorCore" aria-hidden="true"></div>
2809
  <div id="app">
2810
 
2811
  <!-- ── HEADER ───────────────────────────────── -->
 
3073
  const analysisPanel = document.getElementById('analysisPanel');
3074
  const marketStatusBar = document.getElementById('marketStatusBar');
3075
  const indicatorSelect = document.getElementById('indicatorSelect');
3076
+ const themeToggleBtn = document.getElementById('themeToggleBtn');
3077
+ const cursorTrailCanvas = document.getElementById('cursorTrailCanvas');
3078
+ const cursorCore = document.getElementById('cursorCore');
3079
 
3080
  /* ── State ─────────────────────────────────── */
3081
  let currentSymbol = 'XAUUSD';
 
3090
 
3091
  /* ── Indicator Calculation Helpers ────────── */
3092
  /* ── WebSocket Management ────────────────────── */
3093
+ const THEME_SUN_ICON = `
3094
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
3095
+ <circle cx="12" cy="12" r="5"></circle>
3096
+ <line x1="12" y1="1" x2="12" y2="3"></line>
3097
+ <line x1="12" y1="21" x2="12" y2="23"></line>
3098
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
3099
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
3100
+ <line x1="1" y1="12" x2="3" y2="12"></line>
3101
+ <line x1="21" y1="12" x2="23" y2="12"></line>
3102
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
3103
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
3104
+ </svg>`;
3105
+ const THEME_MOON_ICON = `
3106
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
3107
+ <path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z"></path>
3108
+ </svg>`;
3109
+
3110
  (() => {
3111
+ if (!cursorTrailCanvas || !cursorCore || window.matchMedia('(pointer: coarse)').matches) return;
3112
+
3113
+ const ctx = cursorTrailCanvas.getContext('2d');
3114
+ if (!ctx) return;
3115
 
 
 
 
 
 
3116
  const interactiveSelector = 'button, input, select, .search-item, .compact-gauge-card, .explorer-symbol-card, .explorer-cat-item, .dash-close, .dash-col';
3117
+ const trail = [];
3118
+ const pointer = {
3119
+ x: window.innerWidth / 2,
3120
+ y: window.innerHeight / 2,
3121
+ lastX: window.innerWidth / 2,
3122
+ lastY: window.innerHeight / 2,
3123
+ velocity: 0,
3124
+ lastMoveTs: 0,
3125
+ };
3126
+ let rafId = 0;
3127
+ let dpr = 1;
3128
+
3129
+ function resizeTrailCanvas() {
3130
+ dpr = Math.max(1, window.devicePixelRatio || 1);
3131
+ cursorTrailCanvas.width = Math.round(window.innerWidth * dpr);
3132
+ cursorTrailCanvas.height = Math.round(window.innerHeight * dpr);
3133
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
3134
+ }
3135
 
3136
+ function spawnEmber(x, y, vx, vy, speed) {
3137
+ trail.push({
3138
+ x,
3139
+ y,
3140
+ vx,
3141
+ vy,
3142
+ speed,
3143
+ life: 1,
3144
+ radius: Math.min(44, 10 + speed * 0.12),
3145
+ stretch: Math.min(3.4, 1 + speed * 0.008),
3146
+ });
3147
  }
3148
 
3149
+ function drawTrail(now) {
3150
+ ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
3151
+
3152
+ const idleMs = now - pointer.lastMoveTs;
3153
+ if (idleMs > 90) {
3154
+ pointer.velocity *= 0.9;
3155
+ }
3156
+
3157
+ for (let i = trail.length - 1; i >= 0; i -= 1) {
3158
+ const ember = trail[i];
3159
+ ember.life -= 0.055;
3160
+ ember.x += ember.vx;
3161
+ ember.y += ember.vy;
3162
+ ember.radius *= 0.985;
3163
+ ember.vx *= 0.94;
3164
+ ember.vy *= 0.94;
3165
+
3166
+ if (ember.life <= 0.02 || ember.radius <= 1.5) {
3167
+ trail.splice(i, 1);
3168
+ continue;
3169
+ }
3170
+
3171
+ const alpha = ember.life * 0.85;
3172
+ const angle = Math.atan2(ember.vy, ember.vx || 0.0001);
3173
+ ctx.save();
3174
+ ctx.translate(ember.x, ember.y);
3175
+ ctx.rotate(angle);
3176
+ ctx.scale(ember.stretch, 1);
3177
+
3178
+ const gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, ember.radius);
3179
+ gradient.addColorStop(0, `rgba(235, 255, 255, ${alpha})`);
3180
+ gradient.addColorStop(0.22, `rgba(124, 246, 255, ${alpha * 0.95})`);
3181
+ gradient.addColorStop(0.5, `rgba(38, 196, 255, ${alpha * 0.48})`);
3182
+ gradient.addColorStop(1, 'rgba(38, 196, 255, 0)');
3183
+ ctx.fillStyle = gradient;
3184
+ ctx.beginPath();
3185
+ ctx.arc(0, 0, ember.radius, 0, Math.PI * 2);
3186
+ ctx.fill();
3187
+ ctx.restore();
3188
+ }
3189
+
3190
+ if (trail.length > 0 || pointer.velocity > 0.12) {
3191
+ rafId = requestAnimationFrame(drawTrail);
3192
+ } else {
3193
+ rafId = 0;
3194
+ document.body.classList.remove('cursor-active');
3195
+ }
3196
+ }
3197
+
3198
+ function ensureTrailLoop() {
3199
+ if (!rafId) {
3200
+ rafId = requestAnimationFrame(drawTrail);
3201
+ }
3202
+ }
3203
+
3204
+ resizeTrailCanvas();
3205
+ window.addEventListener('resize', resizeTrailCanvas);
3206
+
3207
  document.addEventListener('mousemove', (event) => {
3208
+ const now = performance.now();
3209
+ const dx = event.clientX - pointer.lastX;
3210
+ const dy = event.clientY - pointer.lastY;
3211
+ const dt = Math.max(16, now - (pointer.lastMoveTs || now));
3212
+ const speed = Math.sqrt(dx * dx + dy * dy) / dt * 26;
3213
+
3214
+ pointer.x = event.clientX;
3215
+ pointer.y = event.clientY;
3216
+ pointer.lastMoveTs = now;
3217
+ pointer.lastX = event.clientX;
3218
+ pointer.lastY = event.clientY;
3219
+ pointer.velocity = pointer.velocity * 0.35 + speed * 0.65;
3220
+
3221
+ const emberCount = Math.max(1, Math.min(7, Math.round(pointer.velocity / 3.2)));
3222
+ for (let i = 0; i < emberCount; i += 1) {
3223
+ const ratio = i / emberCount;
3224
+ const jitterX = (Math.random() - 0.5) * 8;
3225
+ const jitterY = (Math.random() - 0.5) * 8;
3226
+ spawnEmber(
3227
+ event.clientX - dx * ratio + jitterX,
3228
+ event.clientY - dy * ratio + jitterY,
3229
+ -dx * 0.08 * (0.5 + Math.random()),
3230
+ -dy * 0.08 * (0.5 + Math.random()),
3231
+ pointer.velocity
3232
+ );
3233
+ }
3234
+
3235
+ cursorCore.style.transform = `translate3d(${pointer.x}px, ${pointer.y}px, 0) translate(-50%, -50%)`;
3236
  document.body.classList.add('cursor-active');
3237
+ ensureTrailLoop();
3238
  }, { passive: true });
3239
 
3240
  document.addEventListener('mouseleave', () => {
3241
+ trail.length = 0;
3242
+ pointer.velocity = 0;
3243
  document.body.classList.remove('cursor-active');
3244
  });
3245
 
 
3743
  </div>
3744
 
3745
  <!-- Dashboard Body Scaler -->
3746
+ <div class="dash-body-scaler">
3747
  <div class="dash-body" style="transform-origin: top center; transition: transform 0.2s ease;">
3748
 
3749
  <!-- TOP ROW: 3 Big Gauges -->
 
4261
 
4262
  let scaleW = windowWidth / targetWidth;
4263
  let scaleH = (windowHeight - 80) / targetHeight; // 80px for header
4264
+ let scale = Math.min(1, scaleW, scaleH);
4265
 
4266
+ if (scale < 0.62) scale = 0.62;
 
 
4267
 
4268
  body.style.transform = `scale(${scale})`;
4269
+ body.style.width = scale < 1 ? `${targetWidth}px` : '100%';
4270
+ body.style.maxWidth = `${targetWidth}px`;
4271
+ body.style.margin = '0 auto';
4272
  }
4273
 
4274
  /* ── Resize handler ────────────────────────── */
 
4286
  function applyTheme(theme) {
4287
  const isDark = theme === 'dark';
4288
  document.body.classList.toggle('dark-theme', isDark);
4289
+ if (themeToggleBtn) {
4290
+ themeToggleBtn.innerHTML = isDark ? THEME_MOON_ICON : THEME_SUN_ICON;
4291
+ themeToggleBtn.setAttribute('aria-label', isDark ? 'ChαΊΏ Δ‘α»™ tα»‘i' : 'ChαΊΏ Δ‘α»™ sΓ‘ng');
4292
+ themeToggleBtn.title = isDark ? 'Đang ở Dark mode' : 'Đang ở Light mode';
4293
+ }
4294
 
4295
  if (chart) {
4296
  chart.applyOptions({