web-mojo 2.2.101 → 2.2.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/CHANGELOG.md +596 -0
  2. package/README.md +2 -2
  3. package/dist/admin-models.cjs.js +2 -0
  4. package/dist/admin-models.cjs.js.map +1 -0
  5. package/dist/admin-models.es.js +2 -0
  6. package/dist/admin-models.es.js.map +1 -0
  7. package/dist/admin.cjs.js +1 -1
  8. package/dist/admin.css +42 -0
  9. package/dist/admin.es.js +1 -1
  10. package/dist/auth.cjs.js +1 -1
  11. package/dist/auth.es.js +1 -1
  12. package/dist/charts.cjs.js +1 -1
  13. package/dist/charts.cjs.js.map +1 -1
  14. package/dist/charts.css +897 -1
  15. package/dist/charts.es.js +1 -1
  16. package/dist/charts.es.js.map +1 -1
  17. package/dist/chat.css +96 -0
  18. package/dist/chunks/AssistantPanelView-CMRTtoqS.js +2 -0
  19. package/dist/chunks/AssistantPanelView-CMRTtoqS.js.map +1 -0
  20. package/dist/chunks/AssistantPanelView-CaVkWhVD.js +2 -0
  21. package/dist/chunks/AssistantPanelView-CaVkWhVD.js.map +1 -0
  22. package/dist/chunks/ChatView-B73uox2v.js +2 -0
  23. package/dist/chunks/ChatView-B73uox2v.js.map +1 -0
  24. package/dist/chunks/ChatView-W8daOwIo.js +2 -0
  25. package/dist/chunks/ChatView-W8daOwIo.js.map +1 -0
  26. package/dist/chunks/Collection-BZlmtcuL.js +2 -0
  27. package/dist/chunks/Collection-BZlmtcuL.js.map +1 -0
  28. package/dist/chunks/Collection-Bwoq6muu.js +2 -0
  29. package/dist/chunks/Collection-Bwoq6muu.js.map +1 -0
  30. package/dist/chunks/ContextMenu-BPPtuqKk.js +2 -0
  31. package/dist/chunks/ContextMenu-BPPtuqKk.js.map +1 -0
  32. package/dist/chunks/ContextMenu-q76hjQb6.js +2 -0
  33. package/dist/chunks/ContextMenu-q76hjQb6.js.map +1 -0
  34. package/dist/chunks/DataView-BbrwHMV4.js +2 -0
  35. package/dist/chunks/{DataView-BFx2glFg.js.map → DataView-BbrwHMV4.js.map} +1 -1
  36. package/dist/chunks/DataView-k-7wmk5_.js +2 -0
  37. package/dist/chunks/{DataView-D5C_lDdg.js.map → DataView-k-7wmk5_.js.map} +1 -1
  38. package/dist/chunks/FormView-DPSuwWMq.js +3 -0
  39. package/dist/chunks/{FormView-e-PeRx1s.js.map → FormView-DPSuwWMq.js.map} +1 -1
  40. package/dist/chunks/FormView-Dcy7XOtC.js +3 -0
  41. package/dist/chunks/{FormView-Cu4iPfvU.js.map → FormView-Dcy7XOtC.js.map} +1 -1
  42. package/dist/chunks/ListView-DHC-yBIw.js +2 -0
  43. package/dist/chunks/ListView-DHC-yBIw.js.map +1 -0
  44. package/dist/chunks/ListView-iGBsD4a7.js +2 -0
  45. package/dist/chunks/ListView-iGBsD4a7.js.map +1 -0
  46. package/dist/chunks/MetricsCountryMapView-CAD9wR_T.js +2 -0
  47. package/dist/chunks/MetricsCountryMapView-CAD9wR_T.js.map +1 -0
  48. package/dist/chunks/MetricsCountryMapView-Dzk3Yrzx.js +2 -0
  49. package/dist/chunks/MetricsCountryMapView-Dzk3Yrzx.js.map +1 -0
  50. package/dist/chunks/Modal-DBJU16cc.js +3 -0
  51. package/dist/chunks/Modal-DBJU16cc.js.map +1 -0
  52. package/dist/chunks/Modal-DuULCMFZ.js +3 -0
  53. package/dist/chunks/Modal-DuULCMFZ.js.map +1 -0
  54. package/dist/chunks/Passkeys-CGRZ8ZMv.js +2 -0
  55. package/dist/chunks/{Passkeys-DfVHrRPY.js.map → Passkeys-CGRZ8ZMv.js.map} +1 -1
  56. package/dist/chunks/Passkeys-Dr8-oSm9.js +2 -0
  57. package/dist/chunks/{Passkeys-Bj-ufmei.js.map → Passkeys-Dr8-oSm9.js.map} +1 -1
  58. package/dist/chunks/TokenManager-CFsr1qUV.js +2 -0
  59. package/dist/chunks/TokenManager-CFsr1qUV.js.map +1 -0
  60. package/dist/chunks/TokenManager-CHQxK_e5.js +2 -0
  61. package/dist/chunks/TokenManager-CHQxK_e5.js.map +1 -0
  62. package/dist/chunks/User-DNQhdBtI.js +2 -0
  63. package/dist/chunks/User-DNQhdBtI.js.map +1 -0
  64. package/dist/chunks/User-Dg7xpYEI.js +2 -0
  65. package/dist/chunks/User-Dg7xpYEI.js.map +1 -0
  66. package/dist/chunks/UserProfileView-B5nczdfw.js +2 -0
  67. package/dist/chunks/UserProfileView-B5nczdfw.js.map +1 -0
  68. package/dist/chunks/UserProfileView-Bpz3VZmP.js +2 -0
  69. package/dist/chunks/UserProfileView-Bpz3VZmP.js.map +1 -0
  70. package/dist/chunks/View-C5n3sIFi.js +2 -0
  71. package/dist/chunks/View-C5n3sIFi.js.map +1 -0
  72. package/dist/chunks/View-Yazho7OL.js +2 -0
  73. package/dist/chunks/View-Yazho7OL.js.map +1 -0
  74. package/dist/chunks/WebApp-CeiDNV6L.js +2 -0
  75. package/dist/chunks/WebApp-CeiDNV6L.js.map +1 -0
  76. package/dist/chunks/WebApp-irKlhuFX.js +2 -0
  77. package/dist/chunks/WebApp-irKlhuFX.js.map +1 -0
  78. package/dist/chunks/admin-BkxeK68u.js +2 -0
  79. package/dist/chunks/admin-BkxeK68u.js.map +1 -0
  80. package/dist/chunks/admin-vjoNbv_1.js +2 -0
  81. package/dist/chunks/admin-vjoNbv_1.js.map +1 -0
  82. package/dist/chunks/exportChart-DbsHDCxw.js +2 -0
  83. package/dist/chunks/exportChart-DbsHDCxw.js.map +1 -0
  84. package/dist/chunks/exportChart-Dk8D_du5.js +2 -0
  85. package/dist/chunks/exportChart-Dk8D_du5.js.map +1 -0
  86. package/dist/chunks/index-BNjCQA7q.js +2 -0
  87. package/dist/chunks/{index-BY54viKF.js.map → index-BNjCQA7q.js.map} +1 -1
  88. package/dist/chunks/index-DBsIDOAa.js +2 -0
  89. package/dist/chunks/{index-Df5lx5TH.js.map → index-DBsIDOAa.js.map} +1 -1
  90. package/dist/chunks/{version-8mBBYRDe.js → version-B0cBv8MN.js} +2 -2
  91. package/dist/chunks/{version-8mBBYRDe.js.map → version-B0cBv8MN.js.map} +1 -1
  92. package/dist/chunks/{version-CoLHxZIU.js → version-DtqCY0ZY.js} +2 -2
  93. package/dist/chunks/{version-CoLHxZIU.js.map → version-DtqCY0ZY.js.map} +1 -1
  94. package/dist/core.css +306 -0
  95. package/dist/css/web-mojo.css +1 -1
  96. package/dist/docit.cjs.js +1 -1
  97. package/dist/docit.cjs.js.map +1 -1
  98. package/dist/docit.es.js +1 -1
  99. package/dist/docit.es.js.map +1 -1
  100. package/dist/index.cjs.js +1 -1
  101. package/dist/index.cjs.js.map +1 -1
  102. package/dist/index.es.js +1 -1
  103. package/dist/index.es.js.map +1 -1
  104. package/dist/lightbox.cjs.js +1 -1
  105. package/dist/lightbox.cjs.js.map +1 -1
  106. package/dist/lightbox.es.js +1 -1
  107. package/dist/lightbox.es.js.map +1 -1
  108. package/dist/map.cjs.js +1 -1
  109. package/dist/map.cjs.js.map +1 -1
  110. package/dist/map.es.js +1 -1
  111. package/dist/map.es.js.map +1 -1
  112. package/dist/portal.css +86 -0
  113. package/dist/timeline.cjs.js +1 -1
  114. package/dist/timeline.cjs.js.map +1 -1
  115. package/dist/timeline.es.js +1 -1
  116. package/dist/timeline.es.js.map +1 -1
  117. package/dist/user-profile.cjs.js +1 -1
  118. package/dist/user-profile.es.js +1 -1
  119. package/dist/web-mojo.lite.iife.js +4183 -3916
  120. package/dist/web-mojo.lite.iife.js.map +1 -1
  121. package/dist/web-mojo.lite.iife.min.js +289 -311
  122. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  123. package/package.json +7 -2
  124. package/dist/chunks/AssistantPanelView-Bdpmd4z7.js +0 -2
  125. package/dist/chunks/AssistantPanelView-Bdpmd4z7.js.map +0 -1
  126. package/dist/chunks/AssistantPanelView-C0bdbEWr.js +0 -2
  127. package/dist/chunks/AssistantPanelView-C0bdbEWr.js.map +0 -1
  128. package/dist/chunks/ChatView-B1MZNPGy.js +0 -2
  129. package/dist/chunks/ChatView-B1MZNPGy.js.map +0 -1
  130. package/dist/chunks/ChatView-DXl9nVVV.js +0 -2
  131. package/dist/chunks/ChatView-DXl9nVVV.js.map +0 -1
  132. package/dist/chunks/Collection-C39Oy2q0.js +0 -2
  133. package/dist/chunks/Collection-C39Oy2q0.js.map +0 -1
  134. package/dist/chunks/Collection-CyK0u557.js +0 -2
  135. package/dist/chunks/Collection-CyK0u557.js.map +0 -1
  136. package/dist/chunks/ContextMenu-D-C7V6J6.js +0 -2
  137. package/dist/chunks/ContextMenu-D-C7V6J6.js.map +0 -1
  138. package/dist/chunks/ContextMenu-hjqR1pGW.js +0 -2
  139. package/dist/chunks/ContextMenu-hjqR1pGW.js.map +0 -1
  140. package/dist/chunks/DataView-BFx2glFg.js +0 -2
  141. package/dist/chunks/DataView-D5C_lDdg.js +0 -2
  142. package/dist/chunks/Dialog-1umNJi4B.js +0 -3
  143. package/dist/chunks/Dialog-1umNJi4B.js.map +0 -1
  144. package/dist/chunks/Dialog-BnxWLMfr.js +0 -3
  145. package/dist/chunks/Dialog-BnxWLMfr.js.map +0 -1
  146. package/dist/chunks/FormView-Cu4iPfvU.js +0 -3
  147. package/dist/chunks/FormView-e-PeRx1s.js +0 -3
  148. package/dist/chunks/ListView-D_hOtfWZ.js +0 -2
  149. package/dist/chunks/ListView-D_hOtfWZ.js.map +0 -1
  150. package/dist/chunks/ListView-Jkke6pU1.js +0 -2
  151. package/dist/chunks/ListView-Jkke6pU1.js.map +0 -1
  152. package/dist/chunks/MetricsCountryMapView-UdvJWArx.js +0 -2
  153. package/dist/chunks/MetricsCountryMapView-UdvJWArx.js.map +0 -1
  154. package/dist/chunks/MetricsCountryMapView-jLWCL6Hm.js +0 -2
  155. package/dist/chunks/MetricsCountryMapView-jLWCL6Hm.js.map +0 -1
  156. package/dist/chunks/MetricsMiniChartWidget-BaXxR9C6.js +0 -2
  157. package/dist/chunks/MetricsMiniChartWidget-BaXxR9C6.js.map +0 -1
  158. package/dist/chunks/MetricsMiniChartWidget-DSKmKY2Z.js +0 -2
  159. package/dist/chunks/MetricsMiniChartWidget-DSKmKY2Z.js.map +0 -1
  160. package/dist/chunks/MiniPieChart-B3sM4Bjv.js +0 -2
  161. package/dist/chunks/MiniPieChart-B3sM4Bjv.js.map +0 -1
  162. package/dist/chunks/MiniPieChart-DL5Rynvm.js +0 -2
  163. package/dist/chunks/MiniPieChart-DL5Rynvm.js.map +0 -1
  164. package/dist/chunks/MiniSeriesChart-C4DPVbU_.js +0 -2
  165. package/dist/chunks/MiniSeriesChart-C4DPVbU_.js.map +0 -1
  166. package/dist/chunks/MiniSeriesChart-DdNMLwfh.js +0 -2
  167. package/dist/chunks/MiniSeriesChart-DdNMLwfh.js.map +0 -1
  168. package/dist/chunks/Modal-COT4zRh3.js +0 -2
  169. package/dist/chunks/Modal-COT4zRh3.js.map +0 -1
  170. package/dist/chunks/Modal-DgMMvDnw.js +0 -2
  171. package/dist/chunks/Modal-DgMMvDnw.js.map +0 -1
  172. package/dist/chunks/Passkeys-Bj-ufmei.js +0 -2
  173. package/dist/chunks/Passkeys-DfVHrRPY.js +0 -2
  174. package/dist/chunks/TokenManager-DIEaBGJh.js +0 -2
  175. package/dist/chunks/TokenManager-DIEaBGJh.js.map +0 -1
  176. package/dist/chunks/TokenManager-DeXkJy0u.js +0 -2
  177. package/dist/chunks/TokenManager-DeXkJy0u.js.map +0 -1
  178. package/dist/chunks/UserProfileView-B_jyMUp0.js +0 -2
  179. package/dist/chunks/UserProfileView-B_jyMUp0.js.map +0 -1
  180. package/dist/chunks/UserProfileView-DcpvvGQS.js +0 -2
  181. package/dist/chunks/UserProfileView-DcpvvGQS.js.map +0 -1
  182. package/dist/chunks/WebApp-BvFnKj-I.js +0 -2
  183. package/dist/chunks/WebApp-BvFnKj-I.js.map +0 -1
  184. package/dist/chunks/WebApp-CfDWKmwH.js +0 -2
  185. package/dist/chunks/WebApp-CfDWKmwH.js.map +0 -1
  186. package/dist/chunks/WebSocketClient-BQAZr8C4.js +0 -2
  187. package/dist/chunks/WebSocketClient-BQAZr8C4.js.map +0 -1
  188. package/dist/chunks/WebSocketClient-YR5d82h8.js +0 -2
  189. package/dist/chunks/WebSocketClient-YR5d82h8.js.map +0 -1
  190. package/dist/chunks/admin-BgvcCWQp.js +0 -2
  191. package/dist/chunks/admin-BgvcCWQp.js.map +0 -1
  192. package/dist/chunks/admin-DzhyZ_Tn.js +0 -2
  193. package/dist/chunks/admin-DzhyZ_Tn.js.map +0 -1
  194. package/dist/chunks/index-BY54viKF.js +0 -2
  195. package/dist/chunks/index-Df5lx5TH.js +0 -2
package/dist/charts.css CHANGED
@@ -23,7 +23,10 @@
23
23
  --chart-loading-bg: rgba(248, 249, 250, 0.95);
24
24
  }
25
25
 
26
- [data-theme="dark"] {
26
+ /* Bootstrap 5.3 sets `data-bs-theme="dark"` on <html>; the framework's
27
+ ThemeManager (src/core/utils/ThemeManager.js) uses the same attribute.
28
+ This block swaps the chart palette to match. */
29
+ [data-bs-theme="dark"] {
27
30
  /* Dark theme */
28
31
  --chart-bg: #212529;
29
32
  --chart-content-bg: #2b3035;
@@ -1748,3 +1751,896 @@
1748
1751
  font-size: 0.8125rem;
1749
1752
  }
1750
1753
  }
1754
+
1755
+
1756
+ /* ==========================================================================
1757
+ Native SeriesChart (.mini-series-*)
1758
+ ========================================================================== */
1759
+
1760
+ .mini-series-chart { display: block; }
1761
+
1762
+ .mini-series-wrapper {
1763
+ display: flex;
1764
+ width: 100%;
1765
+ height: 100%;
1766
+ }
1767
+
1768
+ .mini-series-wrapper.mini-series-legend-top { flex-direction: column; }
1769
+ .mini-series-wrapper.mini-series-legend-bottom { flex-direction: column-reverse; }
1770
+ .mini-series-wrapper.mini-series-legend-left { flex-direction: row-reverse; }
1771
+ .mini-series-wrapper.mini-series-legend-right { flex-direction: row; }
1772
+
1773
+ .mini-series-svg-area {
1774
+ flex: 1 1 auto;
1775
+ position: relative;
1776
+ min-width: 0;
1777
+ min-height: 0;
1778
+ }
1779
+
1780
+ .mini-series-svg {
1781
+ width: 100%;
1782
+ height: 100%;
1783
+ display: block;
1784
+ }
1785
+
1786
+ /* Legend */
1787
+ .mini-series-legend {
1788
+ display: flex;
1789
+ flex-wrap: wrap;
1790
+ gap: 0.5rem 1rem;
1791
+ padding: 0.25rem 0.5rem;
1792
+ font-size: 0.8125rem;
1793
+ color: var(--bs-secondary-color, #6c757d);
1794
+ }
1795
+
1796
+ .mini-series-wrapper.mini-series-legend-left .mini-series-legend,
1797
+ .mini-series-wrapper.mini-series-legend-right .mini-series-legend {
1798
+ flex-direction: column;
1799
+ align-items: flex-start;
1800
+ padding: 0.25rem 0.75rem;
1801
+ }
1802
+
1803
+ /* Legend justify — aligns items along the legend's main axis.
1804
+ - For top/bottom legends (horizontal flex), this is left/center/right.
1805
+ - For left/right legends (column flex), this is top/center/bottom.
1806
+ `start` (default) is also the implicit flex-content default; declared
1807
+ explicitly here so the contract is unambiguous. */
1808
+ .mini-series-wrapper.mini-series-legend-justify-start .mini-series-legend { justify-content: flex-start; }
1809
+ .mini-series-wrapper.mini-series-legend-justify-center .mini-series-legend { justify-content: center; }
1810
+ .mini-series-wrapper.mini-series-legend-justify-end .mini-series-legend { justify-content: flex-end; }
1811
+
1812
+ .mini-series-legend-item {
1813
+ display: inline-flex;
1814
+ align-items: center;
1815
+ gap: 0.375rem;
1816
+ cursor: pointer;
1817
+ user-select: none;
1818
+ transition: opacity 0.15s ease;
1819
+ }
1820
+
1821
+ .mini-series-legend-item:hover { opacity: 0.85; }
1822
+
1823
+ .mini-series-legend-item.mini-series-legend-hidden {
1824
+ opacity: 0.4;
1825
+ text-decoration: line-through;
1826
+ }
1827
+
1828
+ .mini-series-legend-swatch {
1829
+ display: inline-block;
1830
+ width: 0.75rem;
1831
+ height: 0.75rem;
1832
+ border-radius: 2px;
1833
+ }
1834
+
1835
+ .mini-series-legend-label { white-space: nowrap; }
1836
+
1837
+ /* Tooltip */
1838
+ .mini-series-tooltip {
1839
+ position: absolute;
1840
+ z-index: 50;
1841
+ background: var(--chart-overlay-bg, rgba(255, 255, 255, 0.96));
1842
+ color: var(--bs-body-color, #212529);
1843
+ border: 1px solid var(--bs-border-color, #dee2e6);
1844
+ border-radius: 0.25rem;
1845
+ box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.15);
1846
+ padding: 0.4rem 0.6rem;
1847
+ font-size: 0.8125rem;
1848
+ pointer-events: none;
1849
+ min-width: 120px;
1850
+ }
1851
+
1852
+ .mini-series-tooltip-label {
1853
+ font-weight: 600;
1854
+ margin-bottom: 0.25rem;
1855
+ }
1856
+
1857
+ .mini-series-tooltip-row {
1858
+ display: flex;
1859
+ align-items: center;
1860
+ gap: 0.375rem;
1861
+ line-height: 1.4;
1862
+ }
1863
+
1864
+ .mini-series-tooltip-row strong { margin-left: auto; }
1865
+
1866
+ .mini-series-tooltip-swatch {
1867
+ display: inline-block;
1868
+ width: 0.625rem;
1869
+ height: 0.625rem;
1870
+ border-radius: 2px;
1871
+ flex: 0 0 auto;
1872
+ }
1873
+
1874
+ [data-bs-theme="dark"] .mini-series-tooltip {
1875
+ background: var(--chart-overlay-bg, rgba(33, 37, 41, 0.96));
1876
+ color: var(--bs-body-color, #fff);
1877
+ border-color: var(--bs-border-color, #404449);
1878
+ }
1879
+
1880
+ /* Hover-isolated highlighting */
1881
+ .mini-series-faded {
1882
+ opacity: 0.25;
1883
+ transition: opacity 120ms ease;
1884
+ }
1885
+
1886
+ .mini-series-bar,
1887
+ .mini-series-dot {
1888
+ cursor: pointer;
1889
+ transition: opacity 120ms ease;
1890
+ }
1891
+
1892
+
1893
+ /* ==========================================================================
1894
+ Native PieChart (.mini-pie-*)
1895
+ ========================================================================== */
1896
+
1897
+ .mini-pie-chart { display: block; }
1898
+
1899
+ .mini-pie-wrapper {
1900
+ display: flex;
1901
+ align-items: center;
1902
+ gap: 1rem;
1903
+ }
1904
+
1905
+ .mini-pie-wrapper.mini-pie-layout-bottom {
1906
+ flex-direction: column;
1907
+ }
1908
+
1909
+ .mini-pie-wrapper.mini-pie-layout-right {
1910
+ flex-direction: row;
1911
+ }
1912
+
1913
+ .mini-pie-svg-area {
1914
+ position: relative;
1915
+ flex: 0 0 auto;
1916
+ }
1917
+
1918
+ .mini-pie-svg { display: block; }
1919
+
1920
+ .mini-pie-segment { cursor: pointer; transition: opacity 120ms ease; }
1921
+
1922
+ .mini-pie-tooltip {
1923
+ position: absolute;
1924
+ z-index: 50;
1925
+ background: var(--chart-overlay-bg, rgba(255, 255, 255, 0.96));
1926
+ color: var(--bs-body-color, #212529);
1927
+ border: 1px solid var(--bs-border-color, #dee2e6);
1928
+ border-radius: 0.25rem;
1929
+ box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.15);
1930
+ padding: 0.4rem 0.6rem;
1931
+ font-size: 0.8125rem;
1932
+ pointer-events: none;
1933
+ }
1934
+
1935
+ [data-bs-theme="dark"] .mini-pie-tooltip {
1936
+ background: var(--chart-overlay-bg, rgba(33, 37, 41, 0.96));
1937
+ color: var(--bs-body-color, #fff);
1938
+ border-color: var(--bs-border-color, #404449);
1939
+ }
1940
+
1941
+ .mini-pie-legend {
1942
+ display: flex;
1943
+ flex-direction: column;
1944
+ gap: 0.25rem;
1945
+ font-size: 0.8125rem;
1946
+ color: var(--bs-secondary-color, #6c757d);
1947
+ }
1948
+
1949
+ .mini-pie-wrapper.mini-pie-layout-bottom .mini-pie-legend {
1950
+ flex-direction: row;
1951
+ flex-wrap: wrap;
1952
+ gap: 0.5rem 1rem;
1953
+ }
1954
+
1955
+ .mini-pie-legend-item {
1956
+ display: flex;
1957
+ align-items: center;
1958
+ gap: 0.375rem;
1959
+ }
1960
+
1961
+ .mini-pie-legend-swatch {
1962
+ display: inline-block;
1963
+ width: 0.75rem;
1964
+ height: 0.75rem;
1965
+ border-radius: 2px;
1966
+ }
1967
+
1968
+ .mini-pie-legend-label { flex: 1 1 auto; min-width: 0; }
1969
+ .mini-pie-legend-value { font-variant-numeric: tabular-nums; opacity: 0.8; }
1970
+
1971
+
1972
+ /* ==========================================================================
1973
+ SeriesChart crosshair-tracking layer
1974
+ ========================================================================== */
1975
+
1976
+ .mini-series-crosshair-layer {
1977
+ pointer-events: none;
1978
+ }
1979
+
1980
+ .mini-series-crosshair-layer .mini-series-hit {
1981
+ fill: transparent;
1982
+ cursor: crosshair;
1983
+ pointer-events: all;
1984
+ }
1985
+
1986
+ .mini-series-crosshair {
1987
+ /* `currentColor` resolves through this rule unless `crosshairColor` was
1988
+ passed explicitly (which sets `stroke` inline and wins). Matches the
1989
+ Bootstrap text-muted color and auto-adapts under data-bs-theme="dark". */
1990
+ color: var(--bs-secondary-color, #6c757d);
1991
+ opacity: 0.4;
1992
+ pointer-events: none;
1993
+ }
1994
+
1995
+ .mini-series-ghost {
1996
+ pointer-events: none;
1997
+ }
1998
+
1999
+ /* ==========================================================================
2000
+ KPITile / KPIStrip
2001
+ Compact dashboard tiles fed by a parent's batched fetch (KPIStrip).
2002
+ Visual contract documented in planning/mockups/security_dashboard.
2003
+ ========================================================================== */
2004
+
2005
+ .mojo-kpi-strip {
2006
+ display: block;
2007
+ width: 100%;
2008
+ }
2009
+
2010
+ /* Default to 4 tiles per row at desktop, dropping to 2 on tablet and 1
2011
+ on mobile. The grid is responsive but never tries to fit 8 tiles in
2012
+ a single row — that visual is too dense to read at a glance. */
2013
+ .mojo-kpi-strip-grid {
2014
+ display: grid;
2015
+ grid-template-columns: repeat(4, minmax(0, 1fr));
2016
+ gap: 12px;
2017
+ }
2018
+ @media (max-width: 1100px) {
2019
+ .mojo-kpi-strip-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
2020
+ }
2021
+ @media (max-width: 600px) {
2022
+ .mojo-kpi-strip-grid { grid-template-columns: 1fr; }
2023
+ }
2024
+
2025
+ .mojo-kpi-strip-cell {
2026
+ min-width: 0; /* allow grid items to shrink below content width */
2027
+ display: flex;
2028
+ }
2029
+
2030
+ .mojo-kpi-tile {
2031
+ /* button reset */
2032
+ appearance: none;
2033
+ border: 1px solid var(--mojo-kpi-tile-border, var(--bs-border-color, #dee2e6));
2034
+ /* Tile surface — distinct from page bg via theme-aware vars.
2035
+ Dark theme overrides set a deeper near-black so the tile reads
2036
+ as a discrete card against a slightly lighter page bg. */
2037
+ background: var(--mojo-kpi-tile-bg, var(--bs-tertiary-bg, #f8f9fa));
2038
+ color: var(--mojo-kpi-tile-fg, var(--bs-emphasis-color, var(--bs-body-color)));
2039
+ font: inherit;
2040
+ cursor: pointer;
2041
+
2042
+ /* layout */
2043
+ display: grid;
2044
+ grid-template-rows: auto auto auto 1fr;
2045
+ text-align: left;
2046
+ width: 100%;
2047
+ min-height: 130px;
2048
+ padding: 14px 14px 8px;
2049
+ border-radius: 8px;
2050
+ overflow: hidden;
2051
+ position: relative;
2052
+ transition: border-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
2053
+ }
2054
+
2055
+ .mojo-kpi-tile:hover {
2056
+ border-color: var(--bs-secondary-border-subtle, #adb5bd);
2057
+ transform: translateY(-1px);
2058
+ box-shadow: 0 2px 12px -4px rgba(0, 0, 0, 0.08);
2059
+ }
2060
+
2061
+ .mojo-kpi-tile:focus-visible {
2062
+ outline: 2px solid var(--bs-primary, #0d6efd);
2063
+ outline-offset: 2px;
2064
+ }
2065
+
2066
+ /* severity stripe — 3px left bar */
2067
+ .mojo-kpi-tile-critical { box-shadow: inset 3px 0 0 var(--bs-danger, #dc3545); }
2068
+ .mojo-kpi-tile-high { box-shadow: inset 3px 0 0 var(--bs-orange, #fd7e14); }
2069
+ .mojo-kpi-tile-warn { box-shadow: inset 3px 0 0 var(--bs-warning, #ffc107); }
2070
+ .mojo-kpi-tile-info { box-shadow: inset 3px 0 0 var(--bs-info, #0dcaf0); }
2071
+ .mojo-kpi-tile-good { box-shadow: inset 3px 0 0 var(--bs-success, #198754); }
2072
+
2073
+ .mojo-kpi-tile-label {
2074
+ font-size: 10.5px;
2075
+ font-weight: 600;
2076
+ text-transform: uppercase;
2077
+ letter-spacing: 0.1em;
2078
+ color: var(--mojo-kpi-tile-label-fg, var(--bs-secondary-color, #6c757d));
2079
+ }
2080
+
2081
+ .mojo-kpi-tile-value {
2082
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
2083
+ font-variant-numeric: tabular-nums;
2084
+ font-weight: 500;
2085
+ font-size: 30px;
2086
+ line-height: 1.05;
2087
+ margin-top: 6px;
2088
+ letter-spacing: -0.01em;
2089
+ color: var(--mojo-kpi-tile-fg, var(--bs-emphasis-color, var(--bs-body-color)));
2090
+ }
2091
+
2092
+ .mojo-kpi-tile-delta {
2093
+ display: inline-flex;
2094
+ align-items: center;
2095
+ width: fit-content;
2096
+ margin-top: 6px;
2097
+ padding: 2px 9px;
2098
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
2099
+ font-variant-numeric: tabular-nums;
2100
+ font-size: 11px;
2101
+ font-weight: 600;
2102
+ line-height: 1.4;
2103
+ border-radius: 999px;
2104
+ letter-spacing: 0.01em;
2105
+ }
2106
+
2107
+ .mojo-kpi-tile-delta-neutral {
2108
+ color: var(--bs-secondary-color, #6c757d);
2109
+ background: var(--bs-tertiary-bg, rgba(0, 0, 0, 0.04));
2110
+ }
2111
+
2112
+ .mojo-kpi-tile-delta-flat {
2113
+ color: var(--bs-tertiary-color, #6c757d);
2114
+ background: var(--bs-tertiary-bg, rgba(0, 0, 0, 0.03));
2115
+ }
2116
+
2117
+ .mojo-kpi-tile-delta-bad {
2118
+ color: #b02a37;
2119
+ background: rgba(220, 53, 69, 0.12);
2120
+ }
2121
+
2122
+ .mojo-kpi-tile-delta-good {
2123
+ color: #146c43;
2124
+ background: rgba(25, 135, 84, 0.12);
2125
+ }
2126
+
2127
+ /* ── Dark theme: refined hover/badge tints ──
2128
+ The base tile surface, text, and border are picked up automatically
2129
+ from the framework's dark-theme tokens (--bs-tertiary-bg,
2130
+ --bs-emphasis-color, --bs-secondary-color, --bs-border-color) via the
2131
+ fallback chain on .mojo-kpi-tile. These rules just tune component-
2132
+ specific shades that don't map cleanly to a Bootstrap token. */
2133
+ [data-bs-theme="dark"] .mojo-kpi-tile:hover {
2134
+ border-color: #2a3441;
2135
+ }
2136
+ [data-bs-theme="dark"] .mojo-kpi-tile-delta-bad {
2137
+ color: #ffb4b4;
2138
+ background: rgba(255, 77, 79, 0.16);
2139
+ }
2140
+ [data-bs-theme="dark"] .mojo-kpi-tile-delta-good {
2141
+ color: #b8f5d6;
2142
+ background: rgba(52, 211, 153, 0.14);
2143
+ }
2144
+ [data-bs-theme="dark"] .mojo-kpi-tile-delta-neutral {
2145
+ color: #9aa6b6;
2146
+ background: rgba(255, 255, 255, 0.04);
2147
+ }
2148
+
2149
+ .mojo-kpi-tile-spark {
2150
+ /* MiniChart inside takes its declared height */
2151
+ margin-top: auto;
2152
+ }
2153
+
2154
+ /* Pull the embedded MiniChart's wrapper flush with the tile bottom */
2155
+ .mojo-kpi-tile-spark .mini-chart,
2156
+ .mojo-kpi-tile-spark .mini-chart-wrapper {
2157
+ width: 100%;
2158
+ }
2159
+
2160
+ /* ==========================================================================
2161
+ Modal drawer header — used by Modal.drawer() drill-downs
2162
+ ========================================================================== */
2163
+
2164
+ .modal-drawer-head {
2165
+ padding: 18px 20px 12px;
2166
+ border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.08));
2167
+ }
2168
+
2169
+ .modal-drawer-eyebrow {
2170
+ display: inline-block;
2171
+ font-size: 10.5px;
2172
+ font-weight: 700;
2173
+ text-transform: uppercase;
2174
+ letter-spacing: 0.16em;
2175
+ color: var(--bs-secondary-color, #6c757d);
2176
+ margin-bottom: 4px;
2177
+ }
2178
+
2179
+ .modal-drawer-title {
2180
+ margin: 0 0 6px;
2181
+ font-size: 19px;
2182
+ font-weight: 600;
2183
+ line-height: 1.25;
2184
+ letter-spacing: -0.005em;
2185
+ color: var(--bs-body-color);
2186
+ }
2187
+
2188
+ .modal-drawer-meta {
2189
+ display: flex;
2190
+ flex-wrap: wrap;
2191
+ gap: 14px;
2192
+ font-size: 12px;
2193
+ color: var(--bs-secondary-color, #6c757d);
2194
+ }
2195
+
2196
+ .modal-drawer-body {
2197
+ padding: 16px 20px 20px;
2198
+ }
2199
+
2200
+ /* ==========================================================================
2201
+ Security Dashboard layout — single-page mission-control.
2202
+ Visual contract documented in planning/mockups/security_dashboard.
2203
+ ========================================================================== */
2204
+
2205
+ .security-dashboard-page .security-dashboard {
2206
+ max-width: 1480px;
2207
+ margin: 0 auto;
2208
+ padding: 0 8px;
2209
+ }
2210
+
2211
+ /* The dashboard's dark mission-control palette is now the framework
2212
+ default — see core.css `:root[data-bs-theme="dark"]`. No page-scoped
2213
+ surface overrides are needed; everything cascades from the global
2214
+ tokens. */
2215
+
2216
+ .sd-page-head {
2217
+ display: flex;
2218
+ justify-content: space-between;
2219
+ align-items: flex-end;
2220
+ padding: 14px 4px 18px;
2221
+ border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.08));
2222
+ margin-bottom: 24px;
2223
+ }
2224
+
2225
+ .sd-page-title {
2226
+ margin: 4px 0 0;
2227
+ font-size: 22px;
2228
+ font-weight: 600;
2229
+ letter-spacing: -0.005em;
2230
+ color: var(--mojo-kpi-tile-fg, var(--bs-emphasis-color, var(--bs-body-color)));
2231
+ }
2232
+
2233
+ .sd-page-controls {
2234
+ display: flex;
2235
+ align-items: center;
2236
+ gap: 10px;
2237
+ }
2238
+
2239
+ .security-dashboard .sd-eyebrow {
2240
+ display: inline-block;
2241
+ margin: 0;
2242
+ font-size: 11px;
2243
+ font-weight: 700;
2244
+ text-transform: uppercase;
2245
+ letter-spacing: 0.16em;
2246
+ color: var(--bs-secondary-color, #6c757d);
2247
+ }
2248
+
2249
+ /* Generous gutters between sections — the mockup has 32px of breathing
2250
+ room between cards, which lets each section read as a unit. */
2251
+ .security-dashboard .sd-section {
2252
+ margin-bottom: 32px;
2253
+ }
2254
+
2255
+ .security-dashboard .sd-section-head {
2256
+ display: flex;
2257
+ justify-content: space-between;
2258
+ align-items: baseline;
2259
+ margin-bottom: 12px;
2260
+ padding: 0 2px;
2261
+ }
2262
+
2263
+ .security-dashboard .sd-section-meta {
2264
+ font-variant-numeric: tabular-nums;
2265
+ }
2266
+
2267
+ /* grid helpers — used by SecurityDashboardPage's hero row */
2268
+ .security-dashboard .sd-grid {
2269
+ display: grid;
2270
+ gap: 24px;
2271
+ }
2272
+ .security-dashboard .sd-grid-2 {
2273
+ grid-template-columns: 1fr 1fr;
2274
+ }
2275
+ .security-dashboard .sd-grid-2-3 {
2276
+ grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
2277
+ }
2278
+ @media (max-width: 1100px) {
2279
+ .security-dashboard .sd-grid-2,
2280
+ .security-dashboard .sd-grid-2-3 { grid-template-columns: 1fr; }
2281
+ }
2282
+
2283
+ /* Cards: shared mission-control surface, hairline border, subtle inner
2284
+ divider between header and body. */
2285
+ .security-dashboard .sd-card {
2286
+ border-radius: 10px;
2287
+ background: var(--mojo-kpi-tile-bg, var(--bs-tertiary-bg, #ffffff));
2288
+ border: 1px solid var(--mojo-kpi-tile-border, var(--bs-border-color-translucent, rgba(0, 0, 0, 0.08)));
2289
+ color: var(--mojo-kpi-tile-fg, var(--bs-body-color));
2290
+ }
2291
+
2292
+ .security-dashboard .sd-card .card-header {
2293
+ padding: 16px 20px 12px;
2294
+ border-bottom: 1px solid var(--bs-border-color-translucent, rgba(255, 255, 255, 0.04));
2295
+ }
2296
+
2297
+ .security-dashboard .sd-card .card-body {
2298
+ padding: 16px 20px;
2299
+ }
2300
+
2301
+ .security-dashboard .sd-card-title {
2302
+ font-size: 15px;
2303
+ font-weight: 600;
2304
+ letter-spacing: -0.005em;
2305
+ color: var(--mojo-kpi-tile-fg, var(--bs-emphasis-color, var(--bs-body-color)));
2306
+ }
2307
+
2308
+ .security-dashboard .sd-card .card-subtitle {
2309
+ margin-top: 3px;
2310
+ font-size: 11.5px;
2311
+ color: var(--bs-secondary-color, #6c757d);
2312
+ }
2313
+
2314
+ /* Bootstrap btn-outline-secondary needs higher contrast against the
2315
+ deep dashboard surface — bump border + text + hover saturation. */
2316
+ [data-bs-theme="dark"] .security-dashboard .btn-outline-secondary {
2317
+ color: #cfd6e0;
2318
+ border-color: #2a3441;
2319
+ }
2320
+ [data-bs-theme="dark"] .security-dashboard .btn-outline-secondary:hover,
2321
+ [data-bs-theme="dark"] .security-dashboard .btn-outline-secondary.active {
2322
+ color: var(--bs-emphasis-color, #fff);
2323
+ background: #1c232c;
2324
+ border-color: #3a4452;
2325
+ }
2326
+
2327
+ /* Geography map + leaderboard side-by-side layout. */
2328
+ .security-dashboard .sd-geo-grid {
2329
+ display: grid;
2330
+ grid-template-columns: minmax(0, 5fr) minmax(0, 2fr);
2331
+ gap: 0;
2332
+ align-items: stretch;
2333
+ }
2334
+ @media (max-width: 1100px) {
2335
+ .security-dashboard .sd-geo-grid { grid-template-columns: 1fr; }
2336
+ }
2337
+ .security-dashboard .sd-geo-map-cell {
2338
+ padding: 0;
2339
+ }
2340
+ .security-dashboard .sd-geo-leader {
2341
+ border-left: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.08));
2342
+ overflow-y: auto;
2343
+ max-height: 360px;
2344
+ }
2345
+ /* Compact-mode leaderboard (no inline map) — full card width, no left
2346
+ border (since there's nothing to the left of it). */
2347
+ .security-dashboard .sd-geo-leader-full {
2348
+ border-left: 0;
2349
+ max-height: 420px;
2350
+ }
2351
+ @media (max-width: 1100px) {
2352
+ .security-dashboard .sd-geo-leader {
2353
+ border-left: 0;
2354
+ border-top: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.08));
2355
+ }
2356
+ }
2357
+ .security-dashboard .sd-geo-leader-row {
2358
+ display: grid;
2359
+ grid-template-columns: 32px 1fr auto;
2360
+ gap: 10px;
2361
+ align-items: center;
2362
+ padding: 8px 14px;
2363
+ border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.06));
2364
+ cursor: pointer;
2365
+ transition: background-color 100ms ease;
2366
+ font-size: 12.5px;
2367
+ }
2368
+ .security-dashboard .sd-geo-leader-row:last-child { border-bottom: 0; }
2369
+ .security-dashboard .sd-geo-leader-row:hover {
2370
+ background: var(--bs-secondary-bg, rgba(0, 0, 0, 0.03));
2371
+ }
2372
+ .security-dashboard .sd-geo-cc {
2373
+ font-weight: 600;
2374
+ color: var(--bs-secondary-color, #6c757d);
2375
+ letter-spacing: 0.04em;
2376
+ }
2377
+ .security-dashboard .sd-geo-name {
2378
+ color: var(--bs-body-color);
2379
+ white-space: nowrap;
2380
+ overflow: hidden;
2381
+ text-overflow: ellipsis;
2382
+ }
2383
+ .security-dashboard .sd-geo-num {
2384
+ color: var(--bs-secondary-color, #6c757d);
2385
+ }
2386
+
2387
+ .security-dashboard .sd-card-title {
2388
+ font-size: 15px;
2389
+ font-weight: 600;
2390
+ letter-spacing: -0.005em;
2391
+ }
2392
+
2393
+ .security-dashboard .sd-mono {
2394
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
2395
+ font-variant-numeric: tabular-nums;
2396
+ }
2397
+
2398
+ /* Priority queue — list rows */
2399
+ .security-dashboard .sd-priority-list {
2400
+ list-style: none;
2401
+ margin: 0;
2402
+ padding: 0;
2403
+ }
2404
+ .security-dashboard .sd-pri-row {
2405
+ display: grid;
2406
+ grid-template-columns: 64px 1fr auto;
2407
+ gap: 14px;
2408
+ align-items: center;
2409
+ padding: 10px 16px;
2410
+ border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.06));
2411
+ cursor: pointer;
2412
+ transition: background-color 100ms ease;
2413
+ }
2414
+ .security-dashboard .sd-pri-row:last-child { border-bottom: 0; }
2415
+ .security-dashboard .sd-pri-row:hover { background: var(--bs-tertiary-bg, rgba(0, 0, 0, 0.025)); }
2416
+
2417
+ .security-dashboard .sd-pri {
2418
+ display: inline-flex;
2419
+ align-items: center;
2420
+ justify-content: center;
2421
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
2422
+ font-size: 10px;
2423
+ font-weight: 600;
2424
+ letter-spacing: 0.06em;
2425
+ padding: 3px 0;
2426
+ border-radius: 3px;
2427
+ text-align: center;
2428
+ width: 100%;
2429
+ color: #fff;
2430
+ }
2431
+ .security-dashboard .sd-pri-critical { background: var(--bs-danger, #dc3545); }
2432
+ .security-dashboard .sd-pri-high { background: var(--bs-orange, #fd7e14); }
2433
+ .security-dashboard .sd-pri-warn { background: var(--bs-warning, #ffc107); color: #1a1300; }
2434
+ .security-dashboard .sd-pri-info { background: var(--bs-info, #0dcaf0); color: #001823; }
2435
+
2436
+ .security-dashboard .sd-pri-body { min-width: 0; }
2437
+ .security-dashboard .sd-pri-title {
2438
+ display: block;
2439
+ font-weight: 500;
2440
+ color: var(--bs-body-color);
2441
+ white-space: nowrap;
2442
+ overflow: hidden;
2443
+ text-overflow: ellipsis;
2444
+ }
2445
+ .security-dashboard .sd-pri-meta {
2446
+ display: block;
2447
+ margin-top: 2px;
2448
+ font-size: 11.5px;
2449
+ color: var(--bs-secondary-color, #6c757d);
2450
+ font-variant-numeric: tabular-nums;
2451
+ }
2452
+ .security-dashboard .sd-pri-actions {
2453
+ display: inline-flex;
2454
+ gap: 4px;
2455
+ opacity: 0;
2456
+ transition: opacity 100ms ease;
2457
+ }
2458
+ .security-dashboard .sd-pri-row:hover .sd-pri-actions { opacity: 1; }
2459
+
2460
+ /* PieChart inside a dashboard card: never let its fixed-pixel
2461
+ width (e.g. 200px) push the legend past the card edge at narrow
2462
+ viewports. Constrains the SVG area to its parent and lets the
2463
+ legend wrap naturally. */
2464
+ .security-dashboard .mini-pie-chart,
2465
+ .security-dashboard .mini-pie-wrapper {
2466
+ max-width: 100%;
2467
+ }
2468
+ .security-dashboard .mini-pie-svg-area {
2469
+ max-width: 100%;
2470
+ flex-shrink: 0;
2471
+ }
2472
+ .security-dashboard .mini-pie-legend {
2473
+ min-width: 0;
2474
+ flex: 1 1 auto;
2475
+ }
2476
+
2477
+ /* Distributions — Priority Buckets (matches mockup contract).
2478
+ 3-col grid: [70px label/range stack | bar | num] */
2479
+ .security-dashboard .sd-bucket-list {
2480
+ display: grid;
2481
+ gap: 14px;
2482
+ margin: 0;
2483
+ padding: 0;
2484
+ }
2485
+ .security-dashboard .sd-bucket-row {
2486
+ display: grid;
2487
+ grid-template-columns: 70px 1fr auto;
2488
+ gap: 12px;
2489
+ align-items: center;
2490
+ cursor: pointer;
2491
+ }
2492
+ .security-dashboard .sd-bucket-label {
2493
+ font-size: 11px;
2494
+ font-weight: 600;
2495
+ letter-spacing: 0.06em;
2496
+ text-transform: uppercase;
2497
+ line-height: 1.25;
2498
+ }
2499
+ .security-dashboard .sd-bucket-range {
2500
+ display: block;
2501
+ font-weight: 400;
2502
+ font-size: 10px;
2503
+ letter-spacing: 0.04em;
2504
+ opacity: 0.6;
2505
+ margin-top: 2px;
2506
+ }
2507
+ .security-dashboard .sd-bucket-bar {
2508
+ position: relative;
2509
+ display: block;
2510
+ height: 8px;
2511
+ background: rgba(255, 255, 255, 0.05);
2512
+ border-radius: 999px;
2513
+ overflow: hidden;
2514
+ }
2515
+ .security-dashboard .sd-bucket-bar > span {
2516
+ display: block;
2517
+ height: 100%;
2518
+ border-radius: 999px;
2519
+ transition: width 200ms ease;
2520
+ }
2521
+ .security-dashboard .sd-bucket-num {
2522
+ font-size: 13px;
2523
+ color: var(--mojo-kpi-tile-fg, var(--bs-body-color));
2524
+ }
2525
+
2526
+ /* Distributions — Bouncer Funnel (matches mockup contract).
2527
+ Each row: 36px-tall track with a coloured fill that contains the
2528
+ stage label, plus the count to the right. */
2529
+ .security-dashboard .sd-funnel {
2530
+ display: grid;
2531
+ gap: 10px;
2532
+ }
2533
+ .security-dashboard .sd-funnel-row {
2534
+ display: grid;
2535
+ grid-template-columns: 1fr auto;
2536
+ gap: 12px;
2537
+ align-items: center;
2538
+ }
2539
+ .security-dashboard .sd-funnel-bar {
2540
+ position: relative;
2541
+ height: 36px;
2542
+ background: rgba(255, 255, 255, 0.04);
2543
+ border-radius: 6px;
2544
+ overflow: hidden;
2545
+ }
2546
+ .security-dashboard .sd-funnel-fill {
2547
+ position: absolute;
2548
+ left: 0;
2549
+ top: 0;
2550
+ bottom: 0;
2551
+ display: flex;
2552
+ align-items: center;
2553
+ padding: 0 12px;
2554
+ border-radius: 6px;
2555
+ color: #061018;
2556
+ font-weight: 600;
2557
+ font-size: 12px;
2558
+ white-space: nowrap;
2559
+ transition: width 200ms ease;
2560
+ }
2561
+ .security-dashboard .sd-funnel-num {
2562
+ font-size: 13px;
2563
+ color: var(--mojo-kpi-tile-fg, var(--bs-body-color));
2564
+ }
2565
+
2566
+ /* Top sources — rank rows */
2567
+ .security-dashboard .sd-rank-list {
2568
+ margin: 0;
2569
+ }
2570
+ .security-dashboard .sd-rank-row {
2571
+ cursor: pointer;
2572
+ transition: background-color 100ms ease;
2573
+ }
2574
+ .security-dashboard .sd-rank-row:hover {
2575
+ background: var(--bs-tertiary-bg, rgba(0, 0, 0, 0.025));
2576
+ }
2577
+
2578
+ /* Auth sub-tiles — small clickable tiles below the chart */
2579
+ .security-dashboard .sd-auth-tile {
2580
+ appearance: none;
2581
+ background: var(--bs-body-bg);
2582
+ color: inherit;
2583
+ border-color: var(--bs-border-color);
2584
+ cursor: pointer;
2585
+ transition: border-color 120ms ease;
2586
+ }
2587
+ .security-dashboard .sd-auth-tile:hover {
2588
+ border-color: var(--bs-secondary-border-subtle, #adb5bd);
2589
+ }
2590
+ .security-dashboard .sd-auth-tile-label {
2591
+ font-size: 10px;
2592
+ font-weight: 600;
2593
+ letter-spacing: 0.06em;
2594
+ text-transform: uppercase;
2595
+ color: var(--bs-secondary-color, #6c757d);
2596
+ line-height: 1.2;
2597
+ white-space: nowrap;
2598
+ overflow: hidden;
2599
+ text-overflow: ellipsis;
2600
+ }
2601
+ .security-dashboard .sd-auth-tile-suffix {
2602
+ margin-left: 4px;
2603
+ font-weight: 500;
2604
+ opacity: 0.6;
2605
+ }
2606
+ .security-dashboard .sd-auth-tile-value {
2607
+ font-size: 22px;
2608
+ margin-top: 2px;
2609
+ color: var(--mojo-kpi-tile-fg, var(--bs-body-color));
2610
+ }
2611
+
2612
+ /* Health strip */
2613
+ .security-dashboard .sd-health-summary {
2614
+ cursor: pointer;
2615
+ list-style: none;
2616
+ }
2617
+ .security-dashboard .sd-health-summary::-webkit-details-marker { display: none; }
2618
+ .security-dashboard .sd-health-card[open] .sd-health-toggle { transform: rotate(0deg); }
2619
+ .security-dashboard .sd-health-card:not([open]) .sd-health-toggle { transform: rotate(180deg); }
2620
+ .security-dashboard .sd-health-toggle { transition: transform 150ms ease; }
2621
+
2622
+ .security-dashboard .sd-health-row-link { cursor: pointer; }
2623
+ .security-dashboard .sd-health-row-link:hover { background: var(--bs-tertiary-bg, rgba(0, 0, 0, 0.025)); }
2624
+
2625
+ .security-dashboard .sd-dot {
2626
+ display: inline-block;
2627
+ width: 8px;
2628
+ height: 8px;
2629
+ border-radius: 50%;
2630
+ background: var(--bs-tertiary-color, #adb5bd);
2631
+ }
2632
+ .security-dashboard .sd-dot-good { background: var(--bs-success, #198754); box-shadow: 0 0 6px rgba(25, 135, 84, 0.4); }
2633
+ .security-dashboard .sd-dot-warn { background: var(--bs-warning, #ffc107); box-shadow: 0 0 6px rgba(255, 193, 7, 0.4); }
2634
+ .security-dashboard .sd-dot-crit { background: var(--bs-danger, #dc3545); box-shadow: 0 0 8px rgba(220, 53, 69, 0.55); }
2635
+
2636
+ /* Refresh button spinner */
2637
+ .bi-spin {
2638
+ animation: bi-spin-anim 1s linear infinite;
2639
+ display: inline-block;
2640
+ }
2641
+ @keyframes bi-spin-anim {
2642
+ from { transform: rotate(0deg); }
2643
+ to { transform: rotate(360deg); }
2644
+ }
2645
+
2646
+