@linxiraos/pi-stats 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/CHANGELOG.md +276 -0
  2. package/README.md +82 -0
  3. package/build.ts +95 -0
  4. package/dist/client/index.css +1 -0
  5. package/dist/client/index.html +24 -0
  6. package/dist/client/index.js +257 -0
  7. package/dist/client/styles.css +1695 -0
  8. package/dist/types/aggregator.d.ts +98 -0
  9. package/dist/types/client/App.d.ts +1 -0
  10. package/dist/types/client/api.d.ts +22 -0
  11. package/dist/types/client/app/AppLayout.d.ts +16 -0
  12. package/dist/types/client/app/NavRail.d.ts +7 -0
  13. package/dist/types/client/app/RangeControl.d.ts +7 -0
  14. package/dist/types/client/app/SyncButton.d.ts +14 -0
  15. package/dist/types/client/app/ThemeToggle.d.ts +1 -0
  16. package/dist/types/client/app/TopBar.d.ts +15 -0
  17. package/dist/types/client/app/routes.d.ts +12 -0
  18. package/dist/types/client/components/AgentTokenShare.d.ts +5 -0
  19. package/dist/types/client/components/chart-shared.d.ts +173 -0
  20. package/dist/types/client/components/models-table-shared.d.ts +175 -0
  21. package/dist/types/client/components/range-meta.d.ts +21 -0
  22. package/dist/types/client/data/charts.d.ts +1 -0
  23. package/dist/types/client/data/formatters.d.ts +8 -0
  24. package/dist/types/client/data/useHashRoute.d.ts +8 -0
  25. package/dist/types/client/data/useResource.d.ts +13 -0
  26. package/dist/types/client/data/view-models.d.ts +74 -0
  27. package/dist/types/client/index.d.ts +2 -0
  28. package/dist/types/client/routes/BehaviorRoute.d.ts +7 -0
  29. package/dist/types/client/routes/CostsRoute.d.ts +7 -0
  30. package/dist/types/client/routes/ErrorsRoute.d.ts +8 -0
  31. package/dist/types/client/routes/GainRoute.d.ts +7 -0
  32. package/dist/types/client/routes/ModelsRoute.d.ts +7 -0
  33. package/dist/types/client/routes/OverviewRoute.d.ts +8 -0
  34. package/dist/types/client/routes/ProjectsRoute.d.ts +7 -0
  35. package/dist/types/client/routes/ProvidersRoute.d.ts +7 -0
  36. package/dist/types/client/routes/RequestsRoute.d.ts +8 -0
  37. package/dist/types/client/routes/ToolsRoute.d.ts +7 -0
  38. package/dist/types/client/routes/index.d.ts +10 -0
  39. package/dist/types/client/types.d.ts +63 -0
  40. package/dist/types/client/ui/AsyncBoundary.d.ts +12 -0
  41. package/dist/types/client/ui/DataTable.d.ts +17 -0
  42. package/dist/types/client/ui/EmptyState.d.ts +7 -0
  43. package/dist/types/client/ui/ErrorState.d.ts +6 -0
  44. package/dist/types/client/ui/JsonBlock.d.ts +7 -0
  45. package/dist/types/client/ui/MetricCluster.d.ts +5 -0
  46. package/dist/types/client/ui/Panel.d.ts +7 -0
  47. package/dist/types/client/ui/RequestDrawer.d.ts +5 -0
  48. package/dist/types/client/ui/SegmentedControl.d.ts +12 -0
  49. package/dist/types/client/ui/Skeleton.d.ts +8 -0
  50. package/dist/types/client/ui/StatusPill.d.ts +7 -0
  51. package/dist/types/client/ui/index.d.ts +11 -0
  52. package/dist/types/client/useSystemTheme.d.ts +11 -0
  53. package/dist/types/db.d.ts +159 -0
  54. package/dist/types/embedded-client.d.ts +18 -0
  55. package/dist/types/gain-aggregator.d.ts +26 -0
  56. package/dist/types/index.d.ts +7 -0
  57. package/dist/types/parser.d.ts +53 -0
  58. package/dist/types/port-conflict.d.ts +14 -0
  59. package/dist/types/server.d.ts +12 -0
  60. package/dist/types/shared-types.d.ts +403 -0
  61. package/dist/types/sync-worker.d.ts +31 -0
  62. package/dist/types/types.d.ts +164 -0
  63. package/dist/types/usage-windows.d.ts +45 -0
  64. package/dist/types/user-metrics.d.ts +81 -0
  65. package/package.json +94 -0
  66. package/src/aggregator.ts +615 -0
  67. package/src/client/App.tsx +112 -0
  68. package/src/client/api.ts +118 -0
  69. package/src/client/app/AppLayout.tsx +93 -0
  70. package/src/client/app/NavRail.tsx +44 -0
  71. package/src/client/app/RangeControl.tsx +39 -0
  72. package/src/client/app/SyncButton.tsx +75 -0
  73. package/src/client/app/ThemeToggle.tsx +37 -0
  74. package/src/client/app/TopBar.tsx +73 -0
  75. package/src/client/app/routes.ts +86 -0
  76. package/src/client/components/AgentTokenShare.tsx +68 -0
  77. package/src/client/components/chart-shared.tsx +257 -0
  78. package/src/client/components/models-table-shared.tsx +255 -0
  79. package/src/client/components/range-meta.ts +73 -0
  80. package/src/client/css.d.ts +1 -0
  81. package/src/client/data/charts.ts +14 -0
  82. package/src/client/data/formatters.ts +45 -0
  83. package/src/client/data/useHashRoute.ts +88 -0
  84. package/src/client/data/useResource.ts +154 -0
  85. package/src/client/data/view-models.ts +259 -0
  86. package/src/client/index.tsx +10 -0
  87. package/src/client/routes/BehaviorRoute.tsx +623 -0
  88. package/src/client/routes/CostsRoute.tsx +234 -0
  89. package/src/client/routes/ErrorsRoute.tsx +118 -0
  90. package/src/client/routes/GainRoute.tsx +226 -0
  91. package/src/client/routes/ModelsRoute.tsx +430 -0
  92. package/src/client/routes/OverviewRoute.tsx +342 -0
  93. package/src/client/routes/ProjectsRoute.tsx +163 -0
  94. package/src/client/routes/ProvidersRoute.tsx +492 -0
  95. package/src/client/routes/RequestsRoute.tsx +123 -0
  96. package/src/client/routes/ToolsRoute.tsx +463 -0
  97. package/src/client/routes/index.ts +10 -0
  98. package/src/client/styles.css +1384 -0
  99. package/src/client/types.ts +80 -0
  100. package/src/client/ui/AsyncBoundary.tsx +54 -0
  101. package/src/client/ui/DataTable.tsx +122 -0
  102. package/src/client/ui/EmptyState.tsx +16 -0
  103. package/src/client/ui/ErrorState.tsx +25 -0
  104. package/src/client/ui/JsonBlock.tsx +75 -0
  105. package/src/client/ui/MetricCluster.tsx +78 -0
  106. package/src/client/ui/Panel.tsx +24 -0
  107. package/src/client/ui/RequestDrawer.tsx +208 -0
  108. package/src/client/ui/SegmentedControl.tsx +36 -0
  109. package/src/client/ui/Skeleton.tsx +17 -0
  110. package/src/client/ui/StatusPill.tsx +15 -0
  111. package/src/client/ui/index.ts +11 -0
  112. package/src/client/useSystemTheme.ts +87 -0
  113. package/src/db.ts +1702 -0
  114. package/src/embedded-client.generated.txt +0 -0
  115. package/src/embedded-client.ts +26 -0
  116. package/src/gain-aggregator.ts +311 -0
  117. package/src/index.ts +194 -0
  118. package/src/parser.ts +499 -0
  119. package/src/port-conflict.ts +263 -0
  120. package/src/server.ts +396 -0
  121. package/src/shared-types.ts +432 -0
  122. package/src/sync-worker.ts +40 -0
  123. package/src/types.ts +171 -0
  124. package/src/usage-windows.ts +304 -0
  125. package/src/user-metrics.ts +695 -0
  126. package/tailwind.config.js +40 -0
@@ -0,0 +1,1384 @@
1
+ @import "tailwindcss/index.css";
2
+
3
+ /* ==========================================================================
4
+ Zeta Theme Variables & Color Scheme (aligned with Zeta Web UI globals.css)
5
+ ========================================================================== */
6
+ :root {
7
+ color-scheme: dark;
8
+ /* Zeta dark theme — blue accent #60a5fa, neutral-gray surfaces.
9
+ Mirrors web-ui/app/globals.css `html.dark` token set. */
10
+ --bg: #1a1a1a;
11
+ --bg-panel: #242424;
12
+ --bg-hover: #2e2e2e;
13
+ --bg-selected: #383838;
14
+ --bg-subtle: rgba(255,255,255,0.04);
15
+ --border: #3a3a3a;
16
+ --border-strong: rgba(255,255,255,0.13);
17
+ --text: #e8e8e8;
18
+ --text-muted: #9ca3af;
19
+ --text-dim: #6b7280;
20
+ --accent: #60a5fa; /* Zeta blue */
21
+ --accent-hover: #93c5fd;
22
+ --accent-fg: #0f172a; /* ink on accent fills */
23
+ --accent-muted: rgba(96,165,250,0.18);
24
+ --link: #60a5fa; /* Zeta blue */
25
+ --success: #22c55e;
26
+ --danger: #ef4444;
27
+ --warning: #f59e0b;
28
+
29
+ /* Backward-compat aliases for existing class references */
30
+ --page: var(--bg);
31
+ --surface: var(--bg-panel);
32
+ --surface-2: var(--bg-hover);
33
+ --muted: var(--text-muted);
34
+ --dim: var(--text-dim);
35
+
36
+ /* Bridge view-component token vocabulary */
37
+ --text-primary: var(--text);
38
+ --text-secondary: var(--text-muted);
39
+ --border-subtle: var(--border);
40
+ --accent-red: var(--danger);
41
+ --accent-green: var(--success);
42
+ --accent-cyan: var(--link);
43
+ --bg-elevated: var(--bg-hover);
44
+
45
+ --radius-sm: 3px;
46
+ --radius-md: 6px;
47
+ --radius-lg: 8px;
48
+ }
49
+
50
+ /* System-default fallback before JS sets data-theme; an explicit data-theme
51
+ (set by the toggle / anti-flash script) opts out so the override wins. */
52
+ @media (prefers-color-scheme: light) {
53
+ :root:not([data-theme]) {
54
+ color-scheme: light;
55
+ --bg: #ffffff;
56
+ --bg-panel: #f5f5f5;
57
+ --bg-hover: #eeeeee;
58
+ --bg-selected: #e8e8e8;
59
+ --bg-subtle: rgba(0,0,0,0.03);
60
+ --border: #e0e0e0;
61
+ --border-strong: rgba(0,0,0,0.15);
62
+ --text: #1a1a1a;
63
+ --text-muted: #6b7280;
64
+ --text-dim: #9ca3af;
65
+ --accent: #2563eb; /* Zeta blue */
66
+ --accent-hover: #1d4ed8;
67
+ --accent-fg: #ffffff;
68
+ --accent-muted: rgba(37,99,235,0.14);
69
+ --link: #2563eb;
70
+ --success: #16a34a;
71
+ --danger: #dc2626;
72
+ --warning: #d97706;
73
+ /* Backward-compat aliases */
74
+ --page: var(--bg);
75
+ --surface: var(--bg-panel);
76
+ --surface-2: var(--bg-hover);
77
+ --muted: var(--text-muted);
78
+ --dim: var(--text-dim);
79
+ }
80
+ }
81
+
82
+ /* Explicit theme override (toggle or persisted preference). */
83
+ [data-theme="light"] {
84
+ color-scheme: light;
85
+ --bg: #ffffff;
86
+ --bg-panel: #f5f5f5;
87
+ --bg-hover: #eeeeee;
88
+ --bg-selected: #e8e8e8;
89
+ --bg-subtle: rgba(0,0,0,0.03);
90
+ --border: #e0e0e0;
91
+ --border-strong: rgba(0,0,0,0.15);
92
+ --text: #1a1a1a;
93
+ --text-muted: #6b7280;
94
+ --text-dim: #9ca3af;
95
+ --accent: #2563eb; /* Zeta blue */
96
+ --accent-hover: #1d4ed8;
97
+ --accent-fg: #ffffff;
98
+ --accent-muted: rgba(37,99,235,0.14);
99
+ --link: #2563eb;
100
+ --success: #16a34a;
101
+ --danger: #dc2626;
102
+ --warning: #d97706;
103
+ /* Backward-compat aliases */
104
+ --page: var(--bg);
105
+ --surface: var(--bg-panel);
106
+ --surface-2: var(--bg-hover);
107
+ --muted: var(--text-muted);
108
+ --dim: var(--text-dim);
109
+ }
110
+
111
+ /* Zeta Starfield theme — NASA-punk deep-space HUD, aligned with web-ui globals.css */
112
+ [data-theme="starfield"] {
113
+ color-scheme: dark;
114
+ --bg: #08090d;
115
+ --bg-panel: #0d1117;
116
+ --bg-hover: #161d2e;
117
+ --bg-selected: #1a2540;
118
+ --bg-subtle: rgba(217,155,38,0.05);
119
+ --border: #1e2d45;
120
+ --border-strong: rgba(217,155,38,0.2);
121
+ --text: #e8eeff;
122
+ --text-muted: #8fa3c0;
123
+ --text-dim: #3d5070;
124
+ --accent: #d99b26; /* Zeta Starfield gold */
125
+ --accent-hover: #f0b840;
126
+ --accent-fg: #0f172a;
127
+ --accent-muted: rgba(217,155,38,0.18);
128
+ --link: #d99b26;
129
+ --success: #22c55e;
130
+ --danger: #c81d25;
131
+ --warning: #e05a2b;
132
+ /* Backward-compat aliases */
133
+ --page: var(--bg);
134
+ --surface: var(--bg-panel);
135
+ --surface-2: var(--bg-hover);
136
+ --muted: var(--text-muted);
137
+ --dim: var(--text-dim);
138
+ }
139
+
140
+ /* ==========================================================================
141
+ Base Styles
142
+ ========================================================================== */
143
+ @layer base {
144
+ * {
145
+ box-sizing: border-box;
146
+ }
147
+
148
+ html {
149
+ -webkit-font-smoothing: antialiased;
150
+ -moz-osx-font-smoothing: grayscale;
151
+ }
152
+
153
+ body {
154
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
155
+ background: var(--page);
156
+ color: var(--text);
157
+ margin: 0;
158
+ min-height: 100vh;
159
+ }
160
+
161
+ /* Accessible focus ring style */
162
+ button:focus-visible,
163
+ a:focus-visible,
164
+ [tabindex]:focus-visible {
165
+ outline: 2px solid var(--link);
166
+ outline-offset: 2px;
167
+ }
168
+ }
169
+
170
+ /* ==========================================================================
171
+ Layout Components
172
+ ========================================================================== */
173
+ .stats-app-container {
174
+ display: flex;
175
+ min-height: 100vh;
176
+ background: var(--page);
177
+ color: var(--text);
178
+ }
179
+
180
+ /* Navigation Rail (Sidebar) */
181
+ .stats-nav-rail {
182
+ width: 240px;
183
+ background: var(--surface);
184
+ border-right: 1px solid var(--border);
185
+ display: flex;
186
+ flex-direction: column;
187
+ flex-shrink: 0;
188
+ }
189
+
190
+ .stats-desktop-nav {
191
+ display: flex;
192
+ }
193
+
194
+ @media (max-width: 1023px) {
195
+ .stats-desktop-nav {
196
+ display: none;
197
+ }
198
+ }
199
+
200
+ .stats-nav-rail-header {
201
+ padding: 20px 24px;
202
+ border-bottom: 1px solid var(--border);
203
+ height: 56px;
204
+ display: flex;
205
+ align-items: center;
206
+ }
207
+
208
+ .stats-logo-container {
209
+ display: flex;
210
+ flex-direction: column;
211
+ }
212
+
213
+ .stats-logo-text {
214
+ font-size: 14px;
215
+ font-weight: 700;
216
+ letter-spacing: 0.1em;
217
+ color: var(--text);
218
+ }
219
+
220
+ .stats-logo-subtext {
221
+ font-size: 10px;
222
+ text-transform: uppercase;
223
+ letter-spacing: 0.05em;
224
+ color: var(--muted);
225
+ }
226
+
227
+ .stats-nav-rail-menu {
228
+ flex: 1;
229
+ padding: 16px 12px;
230
+ display: flex;
231
+ flex-direction: column;
232
+ gap: 4px;
233
+ }
234
+
235
+ .stats-nav-rail-item {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: 12px;
239
+ padding: 10px 16px;
240
+ font-size: 13px;
241
+ font-weight: 500;
242
+ color: var(--muted);
243
+ background: transparent;
244
+ border: none;
245
+ border-radius: var(--radius-md);
246
+ cursor: pointer;
247
+ text-align: left;
248
+ transition: all 0.15s ease;
249
+ }
250
+
251
+ .stats-nav-rail-item:hover {
252
+ color: var(--text);
253
+ background: var(--surface-2);
254
+ }
255
+
256
+ .stats-nav-rail-item[data-active="true"] {
257
+ color: var(--accent);
258
+ background: var(--accent-muted);
259
+ position: relative;
260
+ }
261
+
262
+ .stats-nav-rail-item[data-active="true"]::before {
263
+ content: "";
264
+ position: absolute;
265
+ left: 0;
266
+ top: 50%;
267
+ height: 18px;
268
+ width: 3px;
269
+ border-radius: 0 3px 3px 0;
270
+ background: var(--accent);
271
+ transform: translateY(-50%);
272
+ }
273
+
274
+ .stats-nav-rail-item-icon {
275
+ flex-shrink: 0;
276
+ }
277
+
278
+ .stats-nav-rail-footer {
279
+ padding: 16px 24px;
280
+ border-top: 1px solid var(--border);
281
+ }
282
+
283
+ .stats-version-tag {
284
+ font-size: 11px;
285
+ color: var(--dim);
286
+ }
287
+
288
+ /* Main Content Area */
289
+ .stats-main-pane {
290
+ flex: 1;
291
+ display: flex;
292
+ flex-direction: column;
293
+ min-width: 0;
294
+ }
295
+
296
+ .stats-top-bar {
297
+ height: 56px;
298
+ background: var(--surface);
299
+ border-bottom: 1px solid var(--border);
300
+ display: flex;
301
+ align-items: center;
302
+ justify-content: space-between;
303
+ padding: 0 24px;
304
+ }
305
+
306
+ @media (max-width: 767px) {
307
+ .stats-top-bar {
308
+ padding: 0 16px;
309
+ flex-wrap: wrap;
310
+ height: auto;
311
+ min-height: 56px;
312
+ padding-top: 8px;
313
+ padding-bottom: 8px;
314
+ gap: 12px;
315
+ }
316
+ }
317
+
318
+ .stats-top-bar-left {
319
+ display: flex;
320
+ align-items: center;
321
+ gap: 12px;
322
+ }
323
+
324
+ .stats-mobile-menu-btn {
325
+ display: none;
326
+ background: transparent;
327
+ border: none;
328
+ color: var(--text);
329
+ padding: 4px;
330
+ cursor: pointer;
331
+ }
332
+
333
+ @media (max-width: 1023px) {
334
+ .stats-mobile-menu-btn {
335
+ display: inline-flex;
336
+ align-items: center;
337
+ justify-content: center;
338
+ }
339
+ }
340
+
341
+ .stats-page-title {
342
+ font-size: 16px;
343
+ font-weight: 600;
344
+ color: var(--text);
345
+ margin: 0;
346
+ }
347
+
348
+ .stats-top-bar-right {
349
+ display: flex;
350
+ align-items: center;
351
+ gap: 16px;
352
+ }
353
+
354
+ @media (max-width: 767px) {
355
+ .stats-top-bar-right {
356
+ width: 100%;
357
+ justify-content: space-between;
358
+ gap: 8px;
359
+ }
360
+ }
361
+
362
+ .stats-top-bar-meta {
363
+ display: flex;
364
+ align-items: center;
365
+ }
366
+
367
+ .stats-last-updated {
368
+ font-size: 11px;
369
+ color: var(--dim);
370
+ font-variant-numeric: tabular-nums;
371
+ }
372
+
373
+ .stats-content-area {
374
+ flex: 1;
375
+ overflow-y: auto;
376
+ }
377
+
378
+ .stats-content-inner {
379
+ max-width: 1560px;
380
+ margin: 0 auto;
381
+ padding: 24px;
382
+ display: flex;
383
+ flex-direction: column;
384
+ gap: 24px;
385
+ }
386
+
387
+ @media (max-width: 767px) {
388
+ .stats-content-inner {
389
+ padding: 16px;
390
+ gap: 16px;
391
+ }
392
+ }
393
+
394
+ /* Mobile Nav Drawer */
395
+ .stats-mobile-drawer-overlay {
396
+ position: fixed;
397
+ inset: 0;
398
+ background: rgba(0, 0, 0, 0.4);
399
+ backdrop-filter: none; /* No decorative blurs */
400
+ z-index: 100;
401
+ }
402
+
403
+ .stats-mobile-drawer {
404
+ position: absolute;
405
+ left: 0;
406
+ top: 0;
407
+ bottom: 0;
408
+ width: 260px;
409
+ background: var(--surface);
410
+ border-right: 1px solid var(--border);
411
+ display: flex;
412
+ flex-direction: column;
413
+ z-index: 101;
414
+ animation: slideIn 0.2s ease-out;
415
+ }
416
+
417
+ @keyframes slideIn {
418
+ from { transform: translateX(-100%); }
419
+ to { transform: translateX(0); }
420
+ }
421
+
422
+ .stats-mobile-drawer-header {
423
+ height: 56px;
424
+ display: flex;
425
+ align-items: center;
426
+ justify-content: space-between;
427
+ padding: 0 16px 0 24px;
428
+ border-bottom: 1px solid var(--border);
429
+ }
430
+
431
+ .stats-mobile-nav {
432
+ display: flex;
433
+ height: calc(100% - 56px);
434
+ }
435
+
436
+ /* ==========================================================================
437
+ UI Primitives & Styles
438
+ ========================================================================== */
439
+
440
+ /* Button */
441
+ .stats-button {
442
+ display: inline-flex;
443
+ align-items: center;
444
+ justify-content: center;
445
+ gap: 8px;
446
+ padding: 8px 14px;
447
+ font-size: 13px;
448
+ font-weight: 500;
449
+ border-radius: var(--radius-md);
450
+ border: 1px solid transparent;
451
+ cursor: pointer;
452
+ transition: all 0.15s ease;
453
+ font-family: inherit;
454
+ }
455
+
456
+ .stats-button:active:not(:disabled) {
457
+ transform: translateY(1px);
458
+ }
459
+
460
+ .stats-button-primary {
461
+ background: var(--accent);
462
+ color: var(--accent-fg);
463
+ }
464
+
465
+ .stats-button-primary:hover:not(:disabled) {
466
+ opacity: 0.9;
467
+ }
468
+
469
+ .stats-button-primary:disabled {
470
+ opacity: 0.5;
471
+ cursor: not-allowed;
472
+ }
473
+
474
+ .stats-button-secondary {
475
+ background: var(--surface-2);
476
+ color: var(--text);
477
+ border-color: var(--border);
478
+ }
479
+
480
+ .stats-button-secondary:hover:not(:disabled) {
481
+ background: var(--border);
482
+ }
483
+
484
+ .stats-button-secondary:disabled {
485
+ opacity: 0.5;
486
+ cursor: not-allowed;
487
+ }
488
+
489
+ /* RangeControl */
490
+ .stats-range-control {
491
+ display: flex;
492
+ background: var(--surface-2);
493
+ border: 1px solid var(--border);
494
+ border-radius: var(--radius-md);
495
+ padding: 2px;
496
+ }
497
+
498
+ .stats-range-control-btn {
499
+ padding: 4px 10px;
500
+ font-size: 12px;
501
+ font-weight: 500;
502
+ color: var(--muted);
503
+ background: transparent;
504
+ border: none;
505
+ border-radius: var(--radius-sm);
506
+ cursor: pointer;
507
+ transition: all 0.1s ease;
508
+ }
509
+
510
+ .stats-range-control-btn:hover {
511
+ color: var(--text);
512
+ }
513
+
514
+ .stats-range-control-btn[data-active="true"] {
515
+ color: var(--text);
516
+ background: var(--surface);
517
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
518
+ }
519
+
520
+ /* Sync Button & Container */
521
+ .stats-sync-container {
522
+ display: flex;
523
+ align-items: center;
524
+ gap: 12px;
525
+ }
526
+
527
+ .stats-sync-status-msg {
528
+ font-size: 11px;
529
+ font-variant-numeric: tabular-nums;
530
+ max-width: 200px;
531
+ white-space: nowrap;
532
+ overflow: hidden;
533
+ text-overflow: ellipsis;
534
+ }
535
+
536
+ .stats-sync-status-msg[data-type="success"] {
537
+ color: var(--success);
538
+ }
539
+
540
+ .stats-sync-status-msg[data-type="error"] {
541
+ color: var(--danger);
542
+ }
543
+
544
+ .stats-sync-icon {
545
+ flex-shrink: 0;
546
+ }
547
+
548
+ .stats-spin {
549
+ animation: spin 1s linear infinite;
550
+ }
551
+
552
+ @keyframes spin {
553
+ to { transform: rotate(360deg); }
554
+ }
555
+
556
+ /* Panel */
557
+ .stats-panel {
558
+ background: var(--surface);
559
+ border: 1px solid var(--border);
560
+ border-radius: var(--radius-lg);
561
+ display: flex;
562
+ flex-direction: column;
563
+ }
564
+
565
+ .stats-panel-header {
566
+ padding: 16px 20px;
567
+ border-bottom: 1px solid var(--border);
568
+ display: flex;
569
+ align-items: center;
570
+ justify-content: space-between;
571
+ gap: 16px;
572
+ }
573
+
574
+ @media (max-width: 480px) {
575
+ .stats-panel-header {
576
+ flex-direction: column;
577
+ align-items: flex-start;
578
+ gap: 8px;
579
+ }
580
+ }
581
+
582
+ .stats-panel-header-titles {
583
+ display: flex;
584
+ flex-direction: column;
585
+ }
586
+
587
+ .stats-panel-title {
588
+ font-size: 14px;
589
+ font-weight: 600;
590
+ color: var(--text);
591
+ margin: 0;
592
+ }
593
+
594
+ .stats-panel-subtitle {
595
+ font-size: 12px;
596
+ color: var(--muted);
597
+ margin: 2px 0 0 0;
598
+ }
599
+
600
+ .stats-panel-actions {
601
+ display: flex;
602
+ align-items: center;
603
+ gap: 12px;
604
+ }
605
+
606
+ .stats-panel-body {
607
+ padding: 20px;
608
+ }
609
+
610
+ /* Metric Cluster (Overview Dashboard KPI Grid) */
611
+ .stats-metric-cluster {
612
+ display: flex;
613
+ flex-direction: column;
614
+ gap: 16px;
615
+ }
616
+
617
+ .stats-metric-primary-grid {
618
+ display: grid;
619
+ grid-template-columns: repeat(4, 1fr);
620
+ gap: 16px;
621
+ }
622
+
623
+ @media (max-width: 1023px) {
624
+ .stats-metric-primary-grid {
625
+ grid-template-columns: repeat(2, 1fr);
626
+ }
627
+ }
628
+
629
+ @media (max-width: 480px) {
630
+ .stats-metric-primary-grid {
631
+ grid-template-columns: 1fr;
632
+ }
633
+ }
634
+
635
+ .stats-metric-secondary-grid {
636
+ display: grid;
637
+ grid-template-columns: repeat(8, 1fr);
638
+ gap: 12px;
639
+ }
640
+
641
+ @media (max-width: 1279px) {
642
+ .stats-metric-secondary-grid {
643
+ grid-template-columns: repeat(4, 1fr);
644
+ }
645
+ }
646
+
647
+ @media (max-width: 767px) {
648
+ .stats-metric-secondary-grid {
649
+ grid-template-columns: repeat(2, 1fr);
650
+ }
651
+ }
652
+
653
+ .stats-metric-card {
654
+ background: var(--surface);
655
+ border: 1px solid var(--border);
656
+ border-radius: var(--radius-lg);
657
+ padding: 16px;
658
+ display: flex;
659
+ flex-direction: column;
660
+ justify-content: space-between;
661
+ }
662
+
663
+ .stats-metric-card.primary {
664
+ padding: 20px 18px;
665
+ }
666
+
667
+ .stats-metric-card.primary .stats-metric-label {
668
+ color: var(--accent);
669
+ }
670
+
671
+ .stats-metric-card.secondary {
672
+ padding: 12px 14px;
673
+ }
674
+
675
+ .stats-metric-label {
676
+ font-size: 11px;
677
+ font-weight: 600;
678
+ text-transform: uppercase;
679
+ letter-spacing: 0.05em;
680
+ color: var(--muted);
681
+ margin-bottom: 8px;
682
+ }
683
+
684
+ .stats-metric-value {
685
+ font-size: 20px;
686
+ font-weight: 700;
687
+ color: var(--text);
688
+ font-variant-numeric: tabular-nums;
689
+ }
690
+
691
+ .stats-metric-card.secondary .stats-metric-value {
692
+ font-size: 15px;
693
+ font-weight: 600;
694
+ }
695
+
696
+ /* Data Table Component */
697
+ .stats-table-wrapper {
698
+ width: 100%;
699
+ }
700
+
701
+ .stats-table-container {
702
+ width: 100%;
703
+ overflow-x: auto;
704
+ }
705
+
706
+ .stats-table {
707
+ width: 100%;
708
+ border-collapse: collapse;
709
+ font-size: 13px;
710
+ font-variant-numeric: tabular-nums;
711
+ }
712
+
713
+ .stats-table-th {
714
+ font-size: 11px;
715
+ font-weight: 600;
716
+ text-transform: uppercase;
717
+ letter-spacing: 0.05em;
718
+ color: var(--muted);
719
+ padding: 12px 16px;
720
+ border-bottom: 2px solid var(--border);
721
+ }
722
+
723
+ .stats-table-td {
724
+ padding: 10px 16px;
725
+ border-bottom: 1px solid var(--border);
726
+ color: var(--text);
727
+ }
728
+
729
+ .stats-table-tr {
730
+ background: transparent;
731
+ }
732
+
733
+ .stats-table-tr-clickable {
734
+ cursor: pointer;
735
+ transition: background 0.12s ease, box-shadow 0.12s ease;
736
+ }
737
+
738
+ .stats-table-tr-clickable:hover {
739
+ background: var(--surface-2);
740
+ box-shadow: inset 2px 0 0 var(--accent);
741
+ }
742
+
743
+ .stats-text-left {
744
+ text-align: left;
745
+ }
746
+
747
+ .stats-text-right {
748
+ text-align: right;
749
+ }
750
+
751
+ .stats-table-empty {
752
+ padding: 40px;
753
+ text-align: center;
754
+ color: var(--muted);
755
+ font-size: 13px;
756
+ border: 1px dashed var(--border);
757
+ border-radius: var(--radius-lg);
758
+ }
759
+
760
+ /* Project progress bars */
761
+ .stats-progress-bar-track {
762
+ background: var(--surface-2);
763
+ border-radius: 999px;
764
+ overflow: hidden;
765
+ }
766
+
767
+ .stats-progress-bar-fill {
768
+ height: 100%;
769
+ border-radius: inherit;
770
+ transition: width 0.18s ease;
771
+ }
772
+
773
+ .stats-progress-bar-fill[data-variant="link"] {
774
+ background: var(--link);
775
+ }
776
+
777
+ .stats-progress-bar-fill[data-variant="success"] {
778
+ background: var(--success);
779
+ }
780
+
781
+ .stats-table-mobile-only {
782
+ display: none;
783
+ }
784
+
785
+ /* Match .stats-table-container so mobile-card tables also contain horizontal
786
+ overflow instead of spilling the page body on narrow desktops (768-1023px). */
787
+ .stats-table-desktop-only {
788
+ width: 100%;
789
+ overflow-x: auto;
790
+ }
791
+
792
+ @media (max-width: 767px) {
793
+ .stats-table-desktop-only {
794
+ display: none;
795
+ }
796
+ .stats-table-mobile-only {
797
+ display: block;
798
+ }
799
+ }
800
+
801
+ .stats-table-mobile-list {
802
+ display: flex;
803
+ flex-direction: column;
804
+ gap: 12px;
805
+ }
806
+
807
+ .stats-table-mobile-card-wrapper {
808
+ background: var(--surface);
809
+ border: 1px solid var(--border);
810
+ border-radius: var(--radius-lg);
811
+ padding: 14px;
812
+ }
813
+
814
+ /* Status Pill */
815
+ .stats-status-pill {
816
+ display: inline-flex;
817
+ align-items: center;
818
+ justify-content: center;
819
+ padding: 2px 8px;
820
+ font-size: 11px;
821
+ font-weight: 600;
822
+ border-radius: 100px;
823
+ line-height: 1.2;
824
+ }
825
+
826
+ .stats-status-pill[data-variant="success"] {
827
+ background: color-mix(in srgb, var(--success) 18%, transparent);
828
+ color: var(--success);
829
+ }
830
+
831
+ .stats-status-pill[data-variant="danger"] {
832
+ background: color-mix(in srgb, var(--danger) 18%, transparent);
833
+ color: var(--danger);
834
+ }
835
+
836
+ .stats-status-pill[data-variant="warning"] {
837
+ background: color-mix(in srgb, var(--warning) 18%, transparent);
838
+ color: var(--warning);
839
+ }
840
+
841
+ .stats-status-pill[data-variant="info"] {
842
+ background: color-mix(in srgb, var(--link) 18%, transparent);
843
+ color: var(--link);
844
+ }
845
+
846
+ .stats-status-pill[data-variant="default"] {
847
+ background: var(--surface-2);
848
+ color: var(--muted);
849
+ }
850
+
851
+ /* Segmented Control */
852
+ .stats-segmented-control {
853
+ display: flex;
854
+ background: var(--surface-2);
855
+ border: 1px solid var(--border);
856
+ border-radius: var(--radius-md);
857
+ padding: 2px;
858
+ gap: 2px;
859
+ }
860
+
861
+ .stats-segmented-control-btn {
862
+ padding: 6px 12px;
863
+ font-size: 12px;
864
+ font-weight: 500;
865
+ color: var(--muted);
866
+ background: transparent;
867
+ border: none;
868
+ border-radius: var(--radius-sm);
869
+ cursor: pointer;
870
+ transition: all 0.1s ease;
871
+ white-space: nowrap;
872
+ }
873
+
874
+ .stats-segmented-control-btn:hover {
875
+ color: var(--text);
876
+ }
877
+
878
+ .stats-segmented-control-btn[data-active="true"] {
879
+ color: var(--text);
880
+ background: var(--surface);
881
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
882
+ }
883
+
884
+ /* Drawer Detail Component */
885
+ .stats-drawer-overlay {
886
+ position: fixed;
887
+ inset: 0;
888
+ background: rgba(0, 0, 0, 0.5);
889
+ z-index: 100;
890
+ display: flex;
891
+ justify-content: flex-end;
892
+ }
893
+
894
+ .stats-drawer {
895
+ width: 600px;
896
+ max-width: 100%;
897
+ height: 100%;
898
+ background: var(--surface);
899
+ border-left: 1px solid var(--border);
900
+ display: flex;
901
+ flex-direction: column;
902
+ animation: drawerSlide 0.25s cubic-bezier(0.16, 1, 0.3, 1);
903
+ box-shadow: -4px 0 24px rgba(0, 0, 0, 0.25);
904
+ }
905
+
906
+ @keyframes drawerSlide {
907
+ from { transform: translateX(100%); }
908
+ to { transform: translateX(0); }
909
+ }
910
+
911
+ .stats-drawer-header {
912
+ height: 56px;
913
+ border-bottom: 1px solid var(--border);
914
+ padding: 0 24px;
915
+ display: flex;
916
+ align-items: center;
917
+ justify-content: space-between;
918
+ background: var(--surface);
919
+ flex-shrink: 0;
920
+ }
921
+
922
+ .stats-drawer-header-left {
923
+ display: flex;
924
+ align-items: baseline;
925
+ gap: 12px;
926
+ }
927
+
928
+ .stats-drawer-title {
929
+ font-size: 15px;
930
+ font-weight: 600;
931
+ color: var(--text);
932
+ margin: 0;
933
+ }
934
+
935
+ .stats-drawer-id {
936
+ font-size: 11px;
937
+ color: var(--muted);
938
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
939
+ }
940
+
941
+ .stats-drawer-close-btn {
942
+ background: transparent;
943
+ border: none;
944
+ color: var(--muted);
945
+ cursor: pointer;
946
+ padding: 4px;
947
+ display: inline-flex;
948
+ align-items: center;
949
+ justify-content: center;
950
+ border-radius: var(--radius-sm);
951
+ transition: all 0.1s ease;
952
+ }
953
+
954
+ .stats-drawer-close-btn:hover {
955
+ color: var(--text);
956
+ background: var(--surface-2);
957
+ }
958
+
959
+ .stats-drawer-body {
960
+ flex: 1;
961
+ overflow-y: auto;
962
+ padding: 24px;
963
+ }
964
+
965
+ .stats-drawer-content {
966
+ display: flex;
967
+ flex-direction: column;
968
+ gap: 24px;
969
+ }
970
+
971
+ .stats-drawer-status-card {
972
+ background: var(--surface-2);
973
+ border: 1px solid var(--border);
974
+ border-radius: var(--radius-lg);
975
+ padding: 16px;
976
+ }
977
+
978
+ .stats-drawer-status-row {
979
+ display: flex;
980
+ justify-content: space-between;
981
+ align-items: flex-start;
982
+ gap: 16px;
983
+ }
984
+
985
+ .stats-drawer-model {
986
+ font-size: 16px;
987
+ font-weight: 700;
988
+ color: var(--text);
989
+ }
990
+
991
+ .stats-drawer-provider {
992
+ font-size: 12px;
993
+ color: var(--muted);
994
+ margin-top: 2px;
995
+ }
996
+
997
+ .stats-drawer-error-block {
998
+ margin-top: 14px;
999
+ border-top: 1px solid var(--border);
1000
+ padding-top: 12px;
1001
+ }
1002
+
1003
+ .stats-drawer-error-label {
1004
+ font-size: 11px;
1005
+ font-weight: 600;
1006
+ text-transform: uppercase;
1007
+ letter-spacing: 0.05em;
1008
+ color: var(--danger);
1009
+ margin-bottom: 4px;
1010
+ }
1011
+
1012
+ .stats-drawer-error-text {
1013
+ font-size: 12px;
1014
+ color: var(--text);
1015
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1016
+ white-space: pre-wrap;
1017
+ word-break: break-all;
1018
+ }
1019
+
1020
+ .stats-drawer-metrics-grid {
1021
+ display: grid;
1022
+ grid-template-columns: repeat(2, 1fr);
1023
+ gap: 12px;
1024
+ }
1025
+
1026
+ .stats-drawer-metric-card {
1027
+ background: var(--surface);
1028
+ border: 1px solid var(--border);
1029
+ border-radius: var(--radius-lg);
1030
+ padding: 14px;
1031
+ display: flex;
1032
+ flex-direction: column;
1033
+ justify-content: center;
1034
+ }
1035
+
1036
+ .stats-drawer-metric-label {
1037
+ display: flex;
1038
+ align-items: center;
1039
+ gap: 6px;
1040
+ font-size: 11px;
1041
+ font-weight: 600;
1042
+ text-transform: uppercase;
1043
+ letter-spacing: 0.05em;
1044
+ color: var(--muted);
1045
+ margin-bottom: 6px;
1046
+ }
1047
+
1048
+ .stats-drawer-metric-icon {
1049
+ color: var(--dim);
1050
+ }
1051
+
1052
+ .stats-drawer-metric-value {
1053
+ font-size: 16px;
1054
+ font-weight: 700;
1055
+ color: var(--text);
1056
+ font-variant-numeric: tabular-nums;
1057
+ }
1058
+
1059
+ .stats-drawer-metric-sub {
1060
+ font-size: 11px;
1061
+ color: var(--muted);
1062
+ margin-top: 2px;
1063
+ font-variant-numeric: tabular-nums;
1064
+ }
1065
+
1066
+ .stats-drawer-json-blocks {
1067
+ display: flex;
1068
+ flex-direction: column;
1069
+ gap: 16px;
1070
+ }
1071
+
1072
+ /* Collapsible JSON Block */
1073
+ .stats-json-block {
1074
+ border: 1px solid var(--border);
1075
+ border-radius: var(--radius-lg);
1076
+ background: var(--surface);
1077
+ overflow: hidden;
1078
+ }
1079
+
1080
+ .stats-json-block-header {
1081
+ padding: 10px 16px;
1082
+ background: var(--surface-2);
1083
+ border-bottom: 1px solid var(--border);
1084
+ display: flex;
1085
+ justify-content: space-between;
1086
+ align-items: center;
1087
+ cursor: pointer;
1088
+ user-select: none;
1089
+ font-size: 12px;
1090
+ font-weight: 600;
1091
+ }
1092
+
1093
+ .stats-json-block-header:hover {
1094
+ background: var(--border);
1095
+ }
1096
+
1097
+ .stats-json-block-title {
1098
+ color: var(--text);
1099
+ }
1100
+
1101
+ .stats-json-block-toggle-indicator {
1102
+ color: var(--muted);
1103
+ }
1104
+
1105
+ .stats-json-block-content-wrapper {
1106
+ padding: 16px;
1107
+ background: var(--page);
1108
+ overflow-x: auto;
1109
+ }
1110
+
1111
+ .stats-json-block-content {
1112
+ margin: 0;
1113
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1114
+ font-size: 12px;
1115
+ color: var(--text);
1116
+ line-height: 1.5;
1117
+ }
1118
+
1119
+ /* Skeleton Loading Element */
1120
+ .stats-skeleton {
1121
+ background: var(--surface-2);
1122
+ position: relative;
1123
+ overflow: hidden;
1124
+ border-radius: var(--radius-sm);
1125
+ }
1126
+
1127
+ .stats-skeleton[data-variant="text"] {
1128
+ height: 14px;
1129
+ margin-top: 4px;
1130
+ margin-bottom: 4px;
1131
+ }
1132
+
1133
+ .stats-skeleton[data-variant="circle"] {
1134
+ border-radius: 50%;
1135
+ }
1136
+
1137
+ /* Subtle Shimmer effect, respecting media queries for reduced motion */
1138
+ .stats-skeleton::after {
1139
+ content: "";
1140
+ position: absolute;
1141
+ inset: 0;
1142
+ transform: translateX(-100%);
1143
+ background: linear-gradient(
1144
+ 90deg,
1145
+ transparent 0%,
1146
+ rgba(255, 255, 255, 0.05) 50%,
1147
+ transparent 100%
1148
+ );
1149
+ animation: shimmer 1.5s infinite;
1150
+ }
1151
+
1152
+ @media (prefers-color-scheme: light) {
1153
+ .stats-skeleton::after {
1154
+ background: linear-gradient(
1155
+ 90deg,
1156
+ transparent 0%,
1157
+ rgba(0, 0, 0, 0.03) 50%,
1158
+ transparent 100%
1159
+ );
1160
+ }
1161
+ }
1162
+
1163
+ @keyframes shimmer {
1164
+ 100% { transform: translateX(100%); }
1165
+ }
1166
+
1167
+ @media (prefers-reduced-motion: reduce) {
1168
+ .stats-skeleton::after {
1169
+ animation: none;
1170
+ }
1171
+ }
1172
+
1173
+ .stats-boundary-skeleton {
1174
+ padding: 20px;
1175
+ border: 1px solid var(--border);
1176
+ border-radius: var(--radius-lg);
1177
+ background: var(--surface);
1178
+ }
1179
+
1180
+ /* Empty State / Error State */
1181
+ .stats-empty-state,
1182
+ .stats-error-state {
1183
+ padding: 48px 24px;
1184
+ display: flex;
1185
+ flex-direction: column;
1186
+ align-items: center;
1187
+ justify-content: center;
1188
+ text-align: center;
1189
+ background: var(--surface);
1190
+ border: 1px dashed var(--border);
1191
+ border-radius: var(--radius-lg);
1192
+ }
1193
+
1194
+ .stats-empty-state-message {
1195
+ font-size: 13px;
1196
+ color: var(--muted);
1197
+ margin: 0;
1198
+ }
1199
+
1200
+ .stats-error-state-content {
1201
+ max-width: 360px;
1202
+ }
1203
+
1204
+ .stats-error-state-title {
1205
+ font-size: 14px;
1206
+ font-weight: 600;
1207
+ color: var(--text);
1208
+ margin: 0 0 8px 0;
1209
+ }
1210
+
1211
+ .stats-error-state-message {
1212
+ font-size: 12px;
1213
+ color: var(--danger);
1214
+ margin: 0 0 16px 0;
1215
+ word-break: break-word;
1216
+ }
1217
+
1218
+ .stats-error-state-btn {
1219
+ margin: 0 auto;
1220
+ }
1221
+
1222
+ /* ==========================================================================
1223
+ Token-vocabulary bridge utility classes (used across route components)
1224
+ ========================================================================== */
1225
+ .stats-text-primary { color: var(--text); }
1226
+ .stats-text-secondary { color: var(--muted); }
1227
+ .stats-text-muted { color: var(--dim); }
1228
+ .stats-text-warning { color: var(--warning); }
1229
+ .stats-text-xs { font-size: 12px; }
1230
+ .stats-font-medium { font-weight: 500; }
1231
+ .stats-font-semibold { font-weight: 600; }
1232
+
1233
+ /* ==========================================================================
1234
+ Owned scrollbars — thin, brand-tinted, app-wide (ComPress convention)
1235
+ ========================================================================== */
1236
+ * {
1237
+ scrollbar-width: thin;
1238
+ scrollbar-color: var(--border-strong) transparent;
1239
+ }
1240
+
1241
+ *::-webkit-scrollbar {
1242
+ width: 10px;
1243
+ height: 10px;
1244
+ }
1245
+
1246
+ *::-webkit-scrollbar-track {
1247
+ background: transparent;
1248
+ }
1249
+
1250
+ *::-webkit-scrollbar-thumb {
1251
+ background: var(--border-strong);
1252
+ border: 2px solid transparent;
1253
+ background-clip: padding-box;
1254
+ border-radius: 999px;
1255
+ }
1256
+
1257
+ *::-webkit-scrollbar-thumb:hover {
1258
+ background: var(--dim);
1259
+ border: 2px solid transparent;
1260
+ background-clip: padding-box;
1261
+ }
1262
+
1263
+ *::-webkit-scrollbar-corner {
1264
+ background: transparent;
1265
+ }
1266
+
1267
+ /* ==========================================================================
1268
+ Comprehensive reduced-motion fallback for all interaction motion
1269
+ ========================================================================== */
1270
+ @media (prefers-reduced-motion: reduce) {
1271
+ .stats-button,
1272
+ .stats-table-tr-clickable,
1273
+ .stats-nav-rail-item,
1274
+ .stats-range-control-btn,
1275
+ .stats-segmented-control-btn {
1276
+ transition: none;
1277
+ }
1278
+
1279
+ .stats-button:active:not(:disabled) {
1280
+ transform: none;
1281
+ }
1282
+
1283
+ .stats-mobile-drawer,
1284
+ .stats-drawer {
1285
+ animation: none;
1286
+ }
1287
+ }
1288
+
1289
+ /* ==========================================================================
1290
+ Brand mark on the Zeta wordmark (both rail + mobile drawer headers)
1291
+ ========================================================================== */
1292
+ .stats-logo-container {
1293
+ display: grid;
1294
+ grid-template-columns: auto 1fr;
1295
+ align-items: center;
1296
+ column-gap: 10px;
1297
+ }
1298
+
1299
+ .stats-logo-container::before {
1300
+ content: "";
1301
+ grid-row: 1 / 3;
1302
+ width: 16px;
1303
+ height: 16px;
1304
+ border-radius: 4px;
1305
+ background: linear-gradient(135deg, #1d4ed8 0%, #2563eb 50%, #60a5fa 100%); /* Zeta brand gradient mark */
1306
+ }
1307
+
1308
+ .stats-logo-text,
1309
+ .stats-logo-subtext {
1310
+ grid-column: 2;
1311
+ }
1312
+
1313
+ /* ==========================================================================
1314
+ JSON block copy affordance
1315
+ ========================================================================== */
1316
+ .stats-json-actions {
1317
+ display: flex;
1318
+ align-items: center;
1319
+ gap: 12px;
1320
+ }
1321
+
1322
+ .stats-json-copy-btn {
1323
+ display: inline-flex;
1324
+ align-items: center;
1325
+ gap: 5px;
1326
+ font-size: 11px;
1327
+ font-weight: 600;
1328
+ color: var(--muted);
1329
+ background: transparent;
1330
+ border: 1px solid var(--border);
1331
+ border-radius: var(--radius-sm);
1332
+ padding: 3px 8px;
1333
+ cursor: pointer;
1334
+ font-family: inherit;
1335
+ transition: color 0.12s ease, background 0.12s ease;
1336
+ }
1337
+
1338
+ .stats-json-copy-btn:hover {
1339
+ color: var(--text);
1340
+ background: var(--surface-2);
1341
+ }
1342
+
1343
+ /* ==========================================================================
1344
+ Empty-state icon
1345
+ ========================================================================== */
1346
+ .stats-empty-state-icon {
1347
+ color: var(--dim);
1348
+ margin-bottom: 12px;
1349
+ }
1350
+
1351
+ @media (prefers-reduced-motion: reduce) {
1352
+ .stats-json-copy-btn {
1353
+ transition: none;
1354
+ }
1355
+ }
1356
+
1357
+ /* ==========================================================================
1358
+ Theme toggle (system / light / dark)
1359
+ ========================================================================== */
1360
+ .stats-theme-toggle {
1361
+ display: inline-flex;
1362
+ align-items: center;
1363
+ justify-content: center;
1364
+ width: 32px;
1365
+ height: 32px;
1366
+ flex-shrink: 0;
1367
+ border: 1px solid var(--border);
1368
+ border-radius: var(--radius-md);
1369
+ background: var(--surface);
1370
+ color: var(--muted);
1371
+ cursor: pointer;
1372
+ transition: color 0.14s ease, background 0.14s ease, border-color 0.14s ease;
1373
+ }
1374
+
1375
+ .stats-theme-toggle:hover {
1376
+ color: var(--text);
1377
+ border-color: var(--border-strong);
1378
+ }
1379
+
1380
+ @media (prefers-reduced-motion: reduce) {
1381
+ .stats-theme-toggle {
1382
+ transition: none;
1383
+ }
1384
+ }