adonisjs-server-stats 1.4.0 → 1.5.2

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 (84) hide show
  1. package/README.md +272 -142
  2. package/dist/configure.d.ts.map +1 -1
  3. package/dist/src/controller/debug_controller.d.ts +2 -2
  4. package/dist/src/controller/debug_controller.d.ts.map +1 -1
  5. package/dist/src/controller/server_stats_controller.d.ts +1 -1
  6. package/dist/src/controller/server_stats_controller.d.ts.map +1 -1
  7. package/dist/src/dashboard/chart_aggregator.d.ts.map +1 -1
  8. package/dist/src/dashboard/chart_aggregator.js +8 -8
  9. package/dist/src/dashboard/dashboard_controller.d.ts +12 -97
  10. package/dist/src/dashboard/dashboard_controller.d.ts.map +1 -1
  11. package/dist/src/dashboard/dashboard_controller.js +244 -522
  12. package/dist/src/dashboard/dashboard_routes.d.ts.map +1 -1
  13. package/dist/src/dashboard/dashboard_routes.js +7 -2
  14. package/dist/src/dashboard/dashboard_store.d.ts +6 -3
  15. package/dist/src/dashboard/dashboard_store.d.ts.map +1 -1
  16. package/dist/src/dashboard/dashboard_store.js +54 -78
  17. package/dist/src/dashboard/integrations/cache_inspector.d.ts.map +1 -1
  18. package/dist/src/dashboard/integrations/queue_inspector.d.ts.map +1 -1
  19. package/dist/src/dashboard/migrator.d.ts.map +1 -1
  20. package/dist/src/dashboard/migrator.js +3 -1
  21. package/dist/src/dashboard/models/stats_event.d.ts +1 -1
  22. package/dist/src/dashboard/models/stats_event.d.ts.map +1 -1
  23. package/dist/src/dashboard/models/stats_query.d.ts +1 -1
  24. package/dist/src/dashboard/models/stats_query.d.ts.map +1 -1
  25. package/dist/src/dashboard/models/stats_request.d.ts +2 -2
  26. package/dist/src/dashboard/models/stats_request.d.ts.map +1 -1
  27. package/dist/src/dashboard/models/stats_request.js +1 -1
  28. package/dist/src/dashboard/models/stats_trace.d.ts +1 -1
  29. package/dist/src/dashboard/models/stats_trace.d.ts.map +1 -1
  30. package/dist/src/debug/debug_store.d.ts +6 -6
  31. package/dist/src/debug/debug_store.d.ts.map +1 -1
  32. package/dist/src/debug/debug_store.js +10 -10
  33. package/dist/src/debug/email_collector.d.ts +0 -9
  34. package/dist/src/debug/email_collector.d.ts.map +1 -1
  35. package/dist/src/debug/email_collector.js +6 -28
  36. package/dist/src/debug/event_collector.d.ts +1 -1
  37. package/dist/src/debug/event_collector.d.ts.map +1 -1
  38. package/dist/src/debug/event_collector.js +17 -17
  39. package/dist/src/debug/query_collector.d.ts +1 -1
  40. package/dist/src/debug/query_collector.d.ts.map +1 -1
  41. package/dist/src/debug/query_collector.js +13 -14
  42. package/dist/src/debug/ring_buffer.d.ts.map +1 -1
  43. package/dist/src/debug/route_inspector.d.ts +1 -1
  44. package/dist/src/debug/route_inspector.d.ts.map +1 -1
  45. package/dist/src/debug/route_inspector.js +12 -12
  46. package/dist/src/debug/trace_collector.d.ts.map +1 -1
  47. package/dist/src/debug/trace_collector.js +6 -5
  48. package/dist/src/edge/client/dashboard.css +516 -171
  49. package/dist/src/edge/client/dashboard.js +2756 -1662
  50. package/dist/src/edge/client/debug-panel.css +476 -133
  51. package/dist/src/edge/client/debug-panel.js +1496 -1043
  52. package/dist/src/edge/client/stats-bar.css +64 -30
  53. package/dist/src/edge/client/stats-bar.js +598 -319
  54. package/dist/src/edge/plugin.d.ts +1 -1
  55. package/dist/src/edge/plugin.d.ts.map +1 -1
  56. package/dist/src/edge/plugin.js +41 -59
  57. package/dist/src/edge/views/stats-bar.edge +1 -1
  58. package/dist/src/index.d.ts +1 -1
  59. package/dist/src/index.d.ts.map +1 -1
  60. package/dist/src/middleware/request_tracking_middleware.d.ts +4 -4
  61. package/dist/src/middleware/request_tracking_middleware.d.ts.map +1 -1
  62. package/dist/src/middleware/request_tracking_middleware.js +7 -6
  63. package/dist/src/prometheus/prometheus_collector.d.ts +1 -1
  64. package/dist/src/prometheus/prometheus_collector.d.ts.map +1 -1
  65. package/dist/src/provider/server_stats_provider.d.ts +1 -1
  66. package/dist/src/provider/server_stats_provider.d.ts.map +1 -1
  67. package/dist/src/provider/server_stats_provider.js +33 -32
  68. package/dist/src/types.d.ts +2 -2
  69. package/dist/src/utils/json_helpers.d.ts +8 -0
  70. package/dist/src/utils/json_helpers.d.ts.map +1 -0
  71. package/dist/src/utils/json_helpers.js +21 -0
  72. package/dist/src/utils/mail_helpers.d.ts +13 -0
  73. package/dist/src/utils/mail_helpers.d.ts.map +1 -0
  74. package/dist/src/utils/mail_helpers.js +26 -0
  75. package/dist/src/utils/math_helpers.d.ts +8 -0
  76. package/dist/src/utils/math_helpers.d.ts.map +1 -0
  77. package/dist/src/utils/math_helpers.js +11 -0
  78. package/dist/src/utils/time_helpers.d.ts +12 -0
  79. package/dist/src/utils/time_helpers.d.ts.map +1 -0
  80. package/dist/src/utils/time_helpers.js +32 -0
  81. package/dist/src/utils/transmit_client.d.ts +9 -0
  82. package/dist/src/utils/transmit_client.d.ts.map +1 -0
  83. package/dist/src/utils/transmit_client.js +20 -0
  84. package/package.json +35 -29
@@ -22,20 +22,65 @@
22
22
  --ss-input-bg: #1a1a1a;
23
23
  --ss-shadow: rgb(0 0 0 / 0.4);
24
24
  /* Status colors */
25
- --ss-green-bg: #064e3b; --ss-green-fg: #34d399;
26
- --ss-blue-bg: #1e3a5f; --ss-blue-fg: #60a5fa;
27
- --ss-amber-bg: #422006; --ss-amber-fg: #fbbf24;
28
- --ss-red-bg: #450a0a; --ss-red-fg: #f87171;
29
- --ss-purple-bg: #2e1065; --ss-purple-fg: #c084fc;
25
+ --ss-green-bg: #064e3b;
26
+ --ss-green-fg: #34d399;
27
+ --ss-blue-bg: #1e3a5f;
28
+ --ss-blue-fg: #60a5fa;
29
+ --ss-amber-bg: #422006;
30
+ --ss-amber-fg: #fbbf24;
31
+ --ss-red-bg: #450a0a;
32
+ --ss-red-fg: #f87171;
33
+ --ss-purple-bg: #2e1065;
34
+ --ss-purple-fg: #c084fc;
30
35
  --ss-sql-color: #93c5fd;
31
- --ss-handler-color: #93c5fd;
32
- --ss-reqid-bg: #1e1b2e; --ss-reqid-fg: #6d28d9;
33
- --ss-reqid-hover-bg: #2e2644; --ss-reqid-hover-fg: #a78bfa;
36
+ --ss-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
37
+ --ss-text-primary: var(--ss-text);
38
+ --ss-reqid-bg: #1e1b2e;
39
+ --ss-reqid-fg: #6d28d9;
40
+ --ss-reqid-hover-bg: #2e2644;
41
+ --ss-reqid-hover-fg: #a78bfa;
42
+ }
43
+
44
+ /* ── Theme: Dark (explicit toggle override) ───────────────────── */
45
+ [data-theme='dark'] {
46
+ --ss-bg: #0f0f0f;
47
+ --ss-surface: #171717;
48
+ --ss-surface-alt: #141414;
49
+ --ss-text: #e5e5e5;
50
+ --ss-text-secondary: #b5b5b5;
51
+ --ss-accent: #34d399;
52
+ --ss-accent-dim: #064e3b;
53
+ --ss-border: #333;
54
+ --ss-border-dim: #262626;
55
+ --ss-border-faint: #1f1f1f;
56
+ --ss-muted: #9ca3af;
57
+ --ss-dim: #6b7280;
58
+ --ss-hover: rgba(38, 38, 38, 0.4);
59
+ --ss-hover-accent: rgba(52, 211, 153, 0.08);
60
+ --ss-input-bg: #1a1a1a;
61
+ --ss-shadow: rgb(0 0 0 / 0.4);
62
+ --ss-green-bg: #064e3b;
63
+ --ss-green-fg: #34d399;
64
+ --ss-blue-bg: #1e3a5f;
65
+ --ss-blue-fg: #60a5fa;
66
+ --ss-amber-bg: #422006;
67
+ --ss-amber-fg: #fbbf24;
68
+ --ss-red-bg: #450a0a;
69
+ --ss-red-fg: #f87171;
70
+ --ss-purple-bg: #2e1065;
71
+ --ss-purple-fg: #c084fc;
72
+ --ss-sql-color: #93c5fd;
73
+ --ss-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
74
+ --ss-text-primary: var(--ss-text);
75
+ --ss-reqid-bg: #1e1b2e;
76
+ --ss-reqid-fg: #6d28d9;
77
+ --ss-reqid-hover-bg: #2e2644;
78
+ --ss-reqid-hover-fg: #a78bfa;
34
79
  }
35
80
 
36
81
  /* ── Theme: Light ──────────────────────────────────────────────── */
37
82
  @media (prefers-color-scheme: light) {
38
- :root {
83
+ :root:not([data-theme='dark']) {
39
84
  --ss-bg: #fafafa;
40
85
  --ss-surface: #ffffff;
41
86
  --ss-surface-alt: #f5f5f5;
@@ -52,47 +97,63 @@
52
97
  --ss-hover-accent: rgba(5, 150, 105, 0.06);
53
98
  --ss-input-bg: #ffffff;
54
99
  --ss-shadow: rgb(0 0 0 / 0.08);
55
- --ss-green-bg: #d1fae5; --ss-green-fg: #059669;
56
- --ss-blue-bg: #dbeafe; --ss-blue-fg: #2563eb;
57
- --ss-amber-bg: #fef3c7; --ss-amber-fg: #b45309;
58
- --ss-red-bg: #fee2e2; --ss-red-fg: #dc2626;
59
- --ss-purple-bg: #ede9fe; --ss-purple-fg: #7c3aed;
100
+ --ss-green-bg: #d1fae5;
101
+ --ss-green-fg: #059669;
102
+ --ss-blue-bg: #dbeafe;
103
+ --ss-blue-fg: #2563eb;
104
+ --ss-amber-bg: #fef3c7;
105
+ --ss-amber-fg: #b45309;
106
+ --ss-red-bg: #fee2e2;
107
+ --ss-red-fg: #dc2626;
108
+ --ss-purple-bg: #ede9fe;
109
+ --ss-purple-fg: #7c3aed;
60
110
  --ss-sql-color: #2563eb;
61
- --ss-handler-color: #2563eb;
62
- --ss-reqid-bg: #ede9fe; --ss-reqid-fg: #7c3aed;
63
- --ss-reqid-hover-bg: #ddd6fe; --ss-reqid-hover-fg: #6d28d9;
111
+ --ss-text-primary: var(--ss-text);
112
+ --ss-reqid-bg: #ede9fe;
113
+ --ss-reqid-fg: #7c3aed;
114
+ --ss-reqid-hover-bg: #ddd6fe;
115
+ --ss-reqid-hover-fg: #6d28d9;
64
116
  }
65
117
  }
66
118
 
67
- /* ── Theme override via data attribute ─────────────────────────── */
68
- [data-theme="dark"] {
69
- --ss-bg: #0f0f0f;
70
- --ss-surface: #171717;
71
- --ss-surface-alt: #141414;
72
- --ss-text: #e5e5e5;
73
- --ss-text-secondary: #b5b5b5;
74
- --ss-accent: #34d399;
75
- --ss-accent-dim: #064e3b;
76
- --ss-border: #333;
77
- --ss-border-dim: #262626;
78
- --ss-border-faint: #1f1f1f;
79
- --ss-muted: #9ca3af;
80
- --ss-dim: #6b7280;
81
- --ss-hover: rgba(38, 38, 38, 0.4);
82
- --ss-hover-accent: rgba(52, 211, 153, 0.08);
83
- --ss-input-bg: #1a1a1a;
84
- --ss-shadow: rgb(0 0 0 / 0.4);
85
- --ss-green-bg: #064e3b; --ss-green-fg: #34d399;
86
- --ss-blue-bg: #1e3a5f; --ss-blue-fg: #60a5fa;
87
- --ss-amber-bg: #422006; --ss-amber-fg: #fbbf24;
88
- --ss-red-bg: #450a0a; --ss-red-fg: #f87171;
89
- --ss-purple-bg: #2e1065; --ss-purple-fg: #c084fc;
90
- --ss-sql-color: #93c5fd;
91
- --ss-handler-color: #93c5fd;
92
- --ss-reqid-bg: #1e1b2e; --ss-reqid-fg: #6d28d9;
93
- --ss-reqid-hover-bg: #2e2644; --ss-reqid-hover-fg: #a78bfa;
119
+ /* ── Theme: Light (explicit toggle override) ──────────────────── */
120
+ [data-theme='light'] {
121
+ --ss-bg: #fafafa;
122
+ --ss-surface: #ffffff;
123
+ --ss-surface-alt: #f5f5f5;
124
+ --ss-text: #171717;
125
+ --ss-text-secondary: #525252;
126
+ --ss-accent: #059669;
127
+ --ss-accent-dim: #d1fae5;
128
+ --ss-border: #e5e5e5;
129
+ --ss-border-dim: #e5e5e5;
130
+ --ss-border-faint: #f0f0f0;
131
+ --ss-muted: #6b7280;
132
+ --ss-dim: #9ca3af;
133
+ --ss-hover: rgba(0, 0, 0, 0.03);
134
+ --ss-hover-accent: rgba(5, 150, 105, 0.06);
135
+ --ss-input-bg: #ffffff;
136
+ --ss-shadow: rgb(0 0 0 / 0.08);
137
+ --ss-green-bg: #d1fae5;
138
+ --ss-green-fg: #059669;
139
+ --ss-blue-bg: #dbeafe;
140
+ --ss-blue-fg: #2563eb;
141
+ --ss-amber-bg: #fef3c7;
142
+ --ss-amber-fg: #b45309;
143
+ --ss-red-bg: #fee2e2;
144
+ --ss-red-fg: #dc2626;
145
+ --ss-purple-bg: #ede9fe;
146
+ --ss-purple-fg: #7c3aed;
147
+ --ss-sql-color: #2563eb;
148
+ --ss-text-primary: var(--ss-text);
149
+ --ss-reqid-bg: #ede9fe;
150
+ --ss-reqid-fg: #7c3aed;
151
+ --ss-reqid-hover-bg: #ddd6fe;
152
+ --ss-reqid-hover-fg: #6d28d9;
94
153
  }
95
- [data-theme="light"] {
154
+
155
+ /* ── Theme override via data attribute ─────────────────────────── */
156
+ [data-theme='light'] {
96
157
  --ss-bg: #fafafa;
97
158
  --ss-surface: #ffffff;
98
159
  --ss-surface-alt: #f5f5f5;
@@ -109,21 +170,35 @@
109
170
  --ss-hover-accent: rgba(5, 150, 105, 0.06);
110
171
  --ss-input-bg: #ffffff;
111
172
  --ss-shadow: rgb(0 0 0 / 0.08);
112
- --ss-green-bg: #d1fae5; --ss-green-fg: #059669;
113
- --ss-blue-bg: #dbeafe; --ss-blue-fg: #2563eb;
114
- --ss-amber-bg: #fef3c7; --ss-amber-fg: #b45309;
115
- --ss-red-bg: #fee2e2; --ss-red-fg: #dc2626;
116
- --ss-purple-bg: #ede9fe; --ss-purple-fg: #7c3aed;
173
+ --ss-green-bg: #d1fae5;
174
+ --ss-green-fg: #059669;
175
+ --ss-blue-bg: #dbeafe;
176
+ --ss-blue-fg: #2563eb;
177
+ --ss-amber-bg: #fef3c7;
178
+ --ss-amber-fg: #b45309;
179
+ --ss-red-bg: #fee2e2;
180
+ --ss-red-fg: #dc2626;
181
+ --ss-purple-bg: #ede9fe;
182
+ --ss-purple-fg: #7c3aed;
117
183
  --ss-sql-color: #2563eb;
118
- --ss-handler-color: #2563eb;
119
- --ss-reqid-bg: #ede9fe; --ss-reqid-fg: #7c3aed;
120
- --ss-reqid-hover-bg: #ddd6fe; --ss-reqid-hover-fg: #6d28d9;
184
+ --ss-text-primary: var(--ss-text);
185
+ --ss-reqid-bg: #ede9fe;
186
+ --ss-reqid-fg: #7c3aed;
187
+ --ss-reqid-hover-bg: #ddd6fe;
188
+ --ss-reqid-hover-fg: #6d28d9;
121
189
  }
122
190
 
123
191
  /* ── Reset & base ──────────────────────────────────────────────── */
124
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
192
+ *,
193
+ *::before,
194
+ *::after {
195
+ box-sizing: border-box;
196
+ margin: 0;
197
+ padding: 0;
198
+ }
125
199
 
126
- html, body {
200
+ html,
201
+ body {
127
202
  height: 100%;
128
203
  overflow: hidden;
129
204
  background: var(--ss-bg);
@@ -191,8 +266,13 @@ html, body {
191
266
  animation: ss-dash-pulse 2s infinite;
192
267
  }
193
268
  @keyframes ss-dash-pulse {
194
- 0%, 100% { opacity: 1; }
195
- 50% { opacity: 0.5; }
269
+ 0%,
270
+ 100% {
271
+ opacity: 1;
272
+ }
273
+ 50% {
274
+ opacity: 0.5;
275
+ }
196
276
  }
197
277
 
198
278
  .ss-dash-live-label {
@@ -201,7 +281,9 @@ html, body {
201
281
  text-transform: uppercase;
202
282
  letter-spacing: 0.05em;
203
283
  }
204
- .ss-dash-live-label.ss-dash-connected { color: var(--ss-accent); }
284
+ .ss-dash-live-label.ss-dash-connected {
285
+ color: var(--ss-accent);
286
+ }
205
287
 
206
288
  .ss-dash-header-right {
207
289
  display: flex;
@@ -221,7 +303,10 @@ html, body {
221
303
  border-radius: 4px;
222
304
  }
223
305
  .ss-dash-theme-btn:hover,
224
- .ss-dash-back-link:hover { color: var(--ss-text); background: var(--ss-hover); }
306
+ .ss-dash-back-link:hover {
307
+ color: var(--ss-text);
308
+ background: var(--ss-hover);
309
+ }
225
310
 
226
311
  .ss-dash-back-link {
227
312
  font-size: 10px;
@@ -247,11 +332,15 @@ html, body {
247
332
  flex-direction: column;
248
333
  overflow-y: auto;
249
334
  overflow-x: hidden;
250
- transition: width 0.2s ease, min-width 0.2s ease;
335
+ transition:
336
+ width 0.2s ease,
337
+ min-width 0.2s ease;
251
338
  scrollbar-width: none;
252
339
  -ms-overflow-style: none;
253
340
  }
254
- .ss-dash-sidebar::-webkit-scrollbar { display: none; }
341
+ .ss-dash-sidebar::-webkit-scrollbar {
342
+ display: none;
343
+ }
255
344
 
256
345
  .ss-dash-sidebar.ss-dash-collapsed {
257
346
  width: 56px;
@@ -277,11 +366,16 @@ html, body {
277
366
  width: 100%;
278
367
  text-align: left;
279
368
  font-family: inherit;
280
- transition: color 0.15s, background 0.15s;
369
+ transition:
370
+ color 0.15s,
371
+ background 0.15s;
281
372
  position: relative;
282
373
  white-space: nowrap;
283
374
  }
284
- .ss-dash-nav-item:hover { color: var(--ss-text-secondary); background: var(--ss-hover); }
375
+ .ss-dash-nav-item:hover {
376
+ color: var(--ss-text-secondary);
377
+ background: var(--ss-hover);
378
+ }
285
379
  .ss-dash-nav-item.ss-dash-active {
286
380
  color: var(--ss-accent);
287
381
  background: var(--ss-hover-accent);
@@ -319,7 +413,9 @@ html, body {
319
413
  overflow: hidden;
320
414
  text-overflow: ellipsis;
321
415
  }
322
- .ss-dash-collapsed .ss-dash-nav-label { display: none; }
416
+ .ss-dash-collapsed .ss-dash-nav-label {
417
+ display: none;
418
+ }
323
419
 
324
420
  .ss-dash-nav-badge {
325
421
  margin-left: auto;
@@ -339,7 +435,9 @@ html, body {
339
435
  background: var(--ss-red-bg);
340
436
  color: var(--ss-red-fg);
341
437
  }
342
- .ss-dash-collapsed .ss-dash-nav-badge { display: none; }
438
+ .ss-dash-collapsed .ss-dash-nav-badge {
439
+ display: none;
440
+ }
343
441
 
344
442
  .ss-dash-nav-sep {
345
443
  height: 1px;
@@ -361,7 +459,10 @@ html, body {
361
459
  border-top: 1px solid var(--ss-border-dim);
362
460
  flex-shrink: 0;
363
461
  }
364
- .ss-dash-sidebar-toggle:hover { color: var(--ss-text-secondary); background: var(--ss-hover); }
462
+ .ss-dash-sidebar-toggle:hover {
463
+ color: var(--ss-text-secondary);
464
+ background: var(--ss-hover);
465
+ }
365
466
 
366
467
  /* ── Main content ──────────────────────────────────────────────── */
367
468
  .ss-dash-main {
@@ -379,7 +480,10 @@ html, body {
379
480
  scrollbar-width: thin;
380
481
  scrollbar-color: var(--ss-border) transparent;
381
482
  }
382
- .ss-dash-pane.ss-dash-active { display: flex; flex-direction: column; }
483
+ .ss-dash-pane.ss-dash-active {
484
+ display: flex;
485
+ flex-direction: column;
486
+ }
383
487
 
384
488
  /* ── Search bar ────────────────────────────────────────────────── */
385
489
  .ss-dash-search-bar {
@@ -405,8 +509,12 @@ html, body {
405
509
  border-radius: 4px;
406
510
  outline: none;
407
511
  }
408
- .ss-dash-search:focus { border-color: var(--ss-accent); }
409
- .ss-dash-search::placeholder { color: var(--ss-dim); }
512
+ .ss-dash-search:focus {
513
+ border-color: var(--ss-accent);
514
+ }
515
+ .ss-dash-search::placeholder {
516
+ color: var(--ss-dim);
517
+ }
410
518
 
411
519
  .ss-dash-summary {
412
520
  font-size: 11px;
@@ -430,7 +538,10 @@ html, body {
430
538
  font-weight: 500;
431
539
  white-space: nowrap;
432
540
  }
433
- .ss-dash-btn:hover { color: var(--ss-text); border-color: var(--ss-dim); }
541
+ .ss-dash-btn:hover {
542
+ color: var(--ss-text);
543
+ border-color: var(--ss-dim);
544
+ }
434
545
  .ss-dash-btn.ss-dash-active {
435
546
  color: var(--ss-accent);
436
547
  border-color: var(--ss-accent);
@@ -487,10 +598,18 @@ html, body {
487
598
  vertical-align: top;
488
599
  max-width: 0;
489
600
  }
490
- .ss-dash-table tr:hover td { background: var(--ss-hover); }
491
- .ss-dash-table tr.ss-dash-explain-row:hover td { background: var(--ss-surface-alt); }
492
- .ss-dash-table tr.ss-dash-clickable { cursor: pointer; }
493
- .ss-dash-table tr.ss-dash-clickable:hover td { background: var(--ss-hover-accent); }
601
+ .ss-dash-table tr:hover td {
602
+ background: var(--ss-hover);
603
+ }
604
+ .ss-dash-table tr.ss-dash-explain-row:hover td {
605
+ background: var(--ss-surface-alt);
606
+ }
607
+ .ss-dash-table tr.ss-dash-clickable {
608
+ cursor: pointer;
609
+ }
610
+ .ss-dash-table tr.ss-dash-clickable:hover td {
611
+ background: var(--ss-hover-accent);
612
+ }
494
613
 
495
614
  /* ── Method badges ─────────────────────────────────────────────── */
496
615
  .ss-dash-method {
@@ -502,15 +621,32 @@ html, body {
502
621
  letter-spacing: 0.03em;
503
622
  text-transform: uppercase;
504
623
  }
505
- .ss-dash-method-get { background: var(--ss-green-bg); color: var(--ss-green-fg); }
506
- .ss-dash-method-post { background: var(--ss-blue-bg); color: var(--ss-blue-fg); }
507
- .ss-dash-method-put, .ss-dash-method-patch { background: var(--ss-amber-bg); color: var(--ss-amber-fg); }
508
- .ss-dash-method-delete { background: var(--ss-red-bg); color: var(--ss-red-fg); }
509
- .ss-dash-method-head, .ss-dash-method-options { background: var(--ss-surface); color: var(--ss-dim); }
510
- .ss-dash-method-select { background: var(--ss-green-bg); color: var(--ss-green-fg); }
511
- .ss-dash-method-insert { background: var(--ss-blue-bg); color: var(--ss-blue-fg); }
512
- .ss-dash-method-update { background: var(--ss-amber-bg); color: var(--ss-amber-fg); }
513
- .ss-dash-method-raw { background: var(--ss-surface); color: var(--ss-dim); }
624
+ .ss-dash-method-get,
625
+ .ss-dash-method-select {
626
+ background: var(--ss-green-bg);
627
+ color: var(--ss-green-fg);
628
+ }
629
+ .ss-dash-method-post,
630
+ .ss-dash-method-insert {
631
+ background: var(--ss-blue-bg);
632
+ color: var(--ss-blue-fg);
633
+ }
634
+ .ss-dash-method-put,
635
+ .ss-dash-method-patch,
636
+ .ss-dash-method-update {
637
+ background: var(--ss-amber-bg);
638
+ color: var(--ss-amber-fg);
639
+ }
640
+ .ss-dash-method-delete {
641
+ background: var(--ss-red-bg);
642
+ color: var(--ss-red-fg);
643
+ }
644
+ .ss-dash-method-head,
645
+ .ss-dash-method-options,
646
+ .ss-dash-method-raw {
647
+ background: var(--ss-surface);
648
+ color: var(--ss-dim);
649
+ }
514
650
 
515
651
  /* ── Status badges ─────────────────────────────────────────────── */
516
652
  .ss-dash-status {
@@ -519,10 +655,22 @@ html, body {
519
655
  padding: 1px 5px;
520
656
  border-radius: 3px;
521
657
  }
522
- .ss-dash-status-2xx { background: var(--ss-green-bg); color: var(--ss-green-fg); }
523
- .ss-dash-status-3xx { background: var(--ss-blue-bg); color: var(--ss-blue-fg); }
524
- .ss-dash-status-4xx { background: var(--ss-amber-bg); color: var(--ss-amber-fg); }
525
- .ss-dash-status-5xx { background: var(--ss-red-bg); color: var(--ss-red-fg); }
658
+ .ss-dash-status-2xx {
659
+ background: var(--ss-green-bg);
660
+ color: var(--ss-green-fg);
661
+ }
662
+ .ss-dash-status-3xx {
663
+ background: var(--ss-blue-bg);
664
+ color: var(--ss-blue-fg);
665
+ }
666
+ .ss-dash-status-4xx {
667
+ background: var(--ss-amber-bg);
668
+ color: var(--ss-amber-fg);
669
+ }
670
+ .ss-dash-status-5xx {
671
+ background: var(--ss-red-bg);
672
+ color: var(--ss-red-fg);
673
+ }
526
674
 
527
675
  /* ── Badge generic ─────────────────────────────────────────────── */
528
676
  .ss-dash-badge {
@@ -533,17 +681,41 @@ html, body {
533
681
  font-weight: 600;
534
682
  text-transform: uppercase;
535
683
  }
536
- .ss-dash-badge-green { background: var(--ss-green-bg); color: var(--ss-green-fg); }
537
- .ss-dash-badge-amber { background: var(--ss-amber-bg); color: var(--ss-amber-fg); }
538
- .ss-dash-badge-red { background: var(--ss-red-bg); color: var(--ss-red-fg); }
539
- .ss-dash-badge-blue { background: var(--ss-blue-bg); color: var(--ss-blue-fg); }
540
- .ss-dash-badge-purple { background: var(--ss-purple-bg); color: var(--ss-purple-fg); }
541
- .ss-dash-badge-muted { background: var(--ss-surface); color: var(--ss-muted); }
684
+ .ss-dash-badge-green {
685
+ background: var(--ss-green-bg);
686
+ color: var(--ss-green-fg);
687
+ }
688
+ .ss-dash-badge-amber {
689
+ background: var(--ss-amber-bg);
690
+ color: var(--ss-amber-fg);
691
+ }
692
+ .ss-dash-badge-red {
693
+ background: var(--ss-red-bg);
694
+ color: var(--ss-red-fg);
695
+ }
696
+ .ss-dash-badge-blue {
697
+ background: var(--ss-blue-bg);
698
+ color: var(--ss-blue-fg);
699
+ }
700
+ .ss-dash-badge-purple {
701
+ background: var(--ss-purple-bg);
702
+ color: var(--ss-purple-fg);
703
+ }
704
+ .ss-dash-badge-muted {
705
+ background: var(--ss-surface);
706
+ color: var(--ss-muted);
707
+ }
542
708
 
543
709
  /* ── Duration ──────────────────────────────────────────────────── */
544
- .ss-dash-duration { font-variant-numeric: tabular-nums; }
545
- .ss-dash-slow { color: var(--ss-amber-fg); }
546
- .ss-dash-very-slow { color: var(--ss-red-fg); }
710
+ .ss-dash-duration {
711
+ font-variant-numeric: tabular-nums;
712
+ }
713
+ .ss-dash-slow {
714
+ color: var(--ss-amber-fg);
715
+ }
716
+ .ss-dash-very-slow {
717
+ color: var(--ss-red-fg);
718
+ }
547
719
 
548
720
  /* ── SQL ───────────────────────────────────────────────────────── */
549
721
  .ss-dash-sql {
@@ -562,10 +734,16 @@ html, body {
562
734
  max-width: none;
563
735
  }
564
736
 
565
- .ss-dash-dup { color: var(--ss-purple-fg); font-size: 10px; font-weight: 600; }
737
+ .ss-dash-dup {
738
+ color: var(--ss-purple-fg);
739
+ font-size: 10px;
740
+ font-weight: 600;
741
+ }
566
742
 
567
743
  /* ── Current route highlight ───────────────────────────────────── */
568
- .ss-dash-current-route td { background: var(--ss-hover-accent) !important; }
744
+ .ss-dash-current-route td {
745
+ background: var(--ss-hover-accent) !important;
746
+ }
569
747
 
570
748
  /* ── Data preview / expand ─────────────────────────────────────── */
571
749
  .ss-dash-data-preview {
@@ -573,7 +751,9 @@ html, body {
573
751
  color: var(--ss-text-secondary);
574
752
  border-bottom: 1px dashed var(--ss-dim);
575
753
  }
576
- .ss-dash-data-preview:hover { color: var(--ss-text); }
754
+ .ss-dash-data-preview:hover {
755
+ color: var(--ss-text);
756
+ }
577
757
 
578
758
  .ss-dash-data-full {
579
759
  margin: 4px 0 0;
@@ -604,7 +784,10 @@ html, body {
604
784
  font-family: inherit;
605
785
  vertical-align: middle;
606
786
  }
607
- .ss-dash-copy-btn:hover { color: var(--ss-text-secondary); border-color: var(--ss-border); }
787
+ .ss-dash-copy-btn:hover {
788
+ color: var(--ss-text-secondary);
789
+ border-color: var(--ss-border);
790
+ }
608
791
 
609
792
  /* ── Empty state ───────────────────────────────────────────────── */
610
793
  .ss-dash-empty {
@@ -619,9 +802,19 @@ html, body {
619
802
  }
620
803
 
621
804
  /* ── Event name & time ─────────────────────────────────────────── */
622
- .ss-dash-event-name { color: var(--ss-sql-color); }
623
- .ss-dash-event-data { color: var(--ss-muted); font-size: 10px; position: relative; }
624
- .ss-dash-event-time { color: var(--ss-dim); font-size: 10px; font-variant-numeric: tabular-nums; }
805
+ .ss-dash-event-name {
806
+ color: var(--ss-sql-color);
807
+ }
808
+ .ss-dash-event-data {
809
+ color: var(--ss-muted);
810
+ font-size: 10px;
811
+ position: relative;
812
+ }
813
+ .ss-dash-event-time {
814
+ color: var(--ss-dim);
815
+ font-size: 10px;
816
+ font-variant-numeric: tabular-nums;
817
+ }
625
818
 
626
819
  /* ── Logs ──────────────────────────────────────────────────────── */
627
820
  .ss-dash-log-filters {
@@ -646,8 +839,14 @@ html, body {
646
839
  color: var(--ss-muted);
647
840
  text-transform: uppercase;
648
841
  }
649
- .ss-dash-log-filter:hover { border-color: var(--ss-dim); color: var(--ss-text-secondary); }
650
- .ss-dash-log-filter.ss-dash-active { border-color: var(--ss-accent); color: var(--ss-accent); }
842
+ .ss-dash-log-filter:hover {
843
+ border-color: var(--ss-dim);
844
+ color: var(--ss-text-secondary);
845
+ }
846
+ .ss-dash-log-filter.ss-dash-active {
847
+ border-color: var(--ss-accent);
848
+ color: var(--ss-accent);
849
+ }
651
850
 
652
851
  .ss-dash-log-entries {
653
852
  flex: 1;
@@ -663,7 +862,9 @@ html, body {
663
862
  gap: 8px;
664
863
  align-items: baseline;
665
864
  }
666
- .ss-dash-log-entry:hover { background: var(--ss-hover); }
865
+ .ss-dash-log-entry:hover {
866
+ background: var(--ss-hover);
867
+ }
667
868
 
668
869
  .ss-dash-log-level {
669
870
  font-size: 10px;
@@ -674,13 +875,34 @@ html, body {
674
875
  padding: 1px 0;
675
876
  border-radius: 3px;
676
877
  }
677
- .ss-dash-log-level-info { background: var(--ss-green-bg); color: var(--ss-green-fg); }
678
- .ss-dash-log-level-warn { background: var(--ss-amber-bg); color: var(--ss-amber-fg); }
679
- .ss-dash-log-level-error, .ss-dash-log-level-fatal { background: var(--ss-red-bg); color: var(--ss-red-fg); }
680
- .ss-dash-log-level-debug { background: var(--ss-surface); color: var(--ss-muted); }
681
- .ss-dash-log-level-trace { background: var(--ss-surface); color: var(--ss-dim); }
878
+ .ss-dash-log-level-info {
879
+ background: var(--ss-green-bg);
880
+ color: var(--ss-green-fg);
881
+ }
882
+ .ss-dash-log-level-warn {
883
+ background: var(--ss-amber-bg);
884
+ color: var(--ss-amber-fg);
885
+ }
886
+ .ss-dash-log-level-error,
887
+ .ss-dash-log-level-fatal {
888
+ background: var(--ss-red-bg);
889
+ color: var(--ss-red-fg);
890
+ }
891
+ .ss-dash-log-level-debug {
892
+ background: var(--ss-surface);
893
+ color: var(--ss-muted);
894
+ }
895
+ .ss-dash-log-level-trace {
896
+ background: var(--ss-surface);
897
+ color: var(--ss-dim);
898
+ }
682
899
 
683
- .ss-dash-log-time { color: var(--ss-dim); font-size: 10px; font-variant-numeric: tabular-nums; flex-shrink: 0; }
900
+ .ss-dash-log-time {
901
+ color: var(--ss-dim);
902
+ font-size: 10px;
903
+ font-variant-numeric: tabular-nums;
904
+ flex-shrink: 0;
905
+ }
684
906
  .ss-dash-log-reqid {
685
907
  font-size: 10px;
686
908
  color: var(--ss-reqid-fg);
@@ -692,9 +914,21 @@ html, body {
692
914
  font-family: inherit;
693
915
  letter-spacing: 0.02em;
694
916
  }
695
- .ss-dash-log-reqid:hover { color: var(--ss-reqid-hover-fg); background: var(--ss-reqid-hover-bg); }
696
- .ss-dash-log-reqid-empty { font-size: 10px; color: var(--ss-border); flex-shrink: 0; width: 58px; text-align: center; }
697
- .ss-dash-log-msg { color: var(--ss-text); word-break: break-word; }
917
+ .ss-dash-log-reqid:hover {
918
+ color: var(--ss-reqid-hover-fg);
919
+ background: var(--ss-reqid-hover-bg);
920
+ }
921
+ .ss-dash-log-reqid-empty {
922
+ font-size: 10px;
923
+ color: var(--ss-border);
924
+ flex-shrink: 0;
925
+ width: 58px;
926
+ text-align: center;
927
+ }
928
+ .ss-dash-log-msg {
929
+ color: var(--ss-text);
930
+ word-break: break-word;
931
+ }
698
932
 
699
933
  /* ── Structured log search ─────────────────────────────────────── */
700
934
  .ss-dash-structured-search {
@@ -720,10 +954,18 @@ html, body {
720
954
  outline: none;
721
955
  }
722
956
  .ss-dash-filter-select:focus,
723
- .ss-dash-filter-input:focus { border-color: var(--ss-accent); }
957
+ .ss-dash-filter-input:focus {
958
+ border-color: var(--ss-accent);
959
+ }
724
960
 
725
- .ss-dash-filter-select { min-width: 100px; }
726
- .ss-dash-filter-input { min-width: 150px; flex: 1; max-width: 300px; }
961
+ .ss-dash-filter-select {
962
+ min-width: 100px;
963
+ }
964
+ .ss-dash-filter-input {
965
+ min-width: 150px;
966
+ flex: 1;
967
+ max-width: 300px;
968
+ }
727
969
 
728
970
  .ss-dash-filter-chips {
729
971
  display: flex;
@@ -752,7 +994,9 @@ html, body {
752
994
  font-family: inherit;
753
995
  padding: 0;
754
996
  }
755
- .ss-dash-filter-chip-remove:hover { color: var(--ss-text); }
997
+ .ss-dash-filter-chip-remove:hover {
998
+ color: var(--ss-text);
999
+ }
756
1000
 
757
1001
  /* ── Saved filters ─────────────────────────────────────────────── */
758
1002
  .ss-dash-saved-filters {
@@ -799,28 +1043,40 @@ html, body {
799
1043
  line-height: 1.6;
800
1044
  overflow: hidden;
801
1045
  }
802
- .ss-dash-email-preview-meta strong { color: var(--ss-text); font-weight: 600; }
1046
+ .ss-dash-email-preview-meta strong {
1047
+ color: var(--ss-text);
1048
+ font-weight: 600;
1049
+ }
803
1050
  .ss-dash-email-iframe {
804
1051
  flex: 1;
805
1052
  border: none;
806
1053
  background: #fff;
807
1054
  }
808
1055
 
809
- .ss-dash-email-row { cursor: pointer; }
810
- .ss-dash-email-row:hover td { background: var(--ss-hover-accent) !important; }
1056
+ .ss-dash-email-row {
1057
+ cursor: pointer;
1058
+ }
1059
+ .ss-dash-email-row:hover td {
1060
+ background: var(--ss-hover-accent) !important;
1061
+ }
811
1062
 
812
- .ss-dash-email-status {
813
- display: inline-block;
814
- padding: 1px 6px;
815
- border-radius: 3px;
816
- font-size: 10px;
817
- font-weight: 600;
818
- text-transform: uppercase;
1063
+ /* Email status badges reuse .ss-dash-badge base */
1064
+ .ss-dash-email-status-sent {
1065
+ background: var(--ss-green-bg);
1066
+ color: var(--ss-green-fg);
1067
+ }
1068
+ .ss-dash-email-status-sending {
1069
+ background: var(--ss-amber-bg);
1070
+ color: var(--ss-amber-fg);
1071
+ }
1072
+ .ss-dash-email-status-queued {
1073
+ background: var(--ss-blue-bg);
1074
+ color: var(--ss-blue-fg);
1075
+ }
1076
+ .ss-dash-email-status-failed {
1077
+ background: var(--ss-red-bg);
1078
+ color: var(--ss-red-fg);
819
1079
  }
820
- .ss-dash-email-status-sent { background: var(--ss-green-bg); color: var(--ss-green-fg); }
821
- .ss-dash-email-status-sending { background: var(--ss-amber-bg); color: var(--ss-amber-fg); }
822
- .ss-dash-email-status-queued { background: var(--ss-blue-bg); color: var(--ss-blue-fg); }
823
- .ss-dash-email-status-failed { background: var(--ss-red-bg); color: var(--ss-red-fg); }
824
1080
 
825
1081
  /* ── Timeline / Waterfall ──────────────────────────────────────── */
826
1082
  .ss-dash-tl-detail-header {
@@ -847,7 +1103,9 @@ html, body {
847
1103
  font-size: 11px;
848
1104
  border-bottom: 1px solid var(--ss-border-faint);
849
1105
  }
850
- .ss-dash-tl-row:hover { background: var(--ss-hover); }
1106
+ .ss-dash-tl-row:hover {
1107
+ background: var(--ss-hover);
1108
+ }
851
1109
 
852
1110
  .ss-dash-tl-label {
853
1111
  width: 320px;
@@ -874,13 +1132,29 @@ html, body {
874
1132
  min-width: 2px;
875
1133
  cursor: default;
876
1134
  }
877
- .ss-dash-tl-bar-request { background: var(--ss-blue-bg); border: 1px solid var(--ss-blue-fg); }
878
- .ss-dash-tl-bar-middleware { background: var(--ss-blue-bg); opacity: 0.7; }
879
- .ss-dash-tl-bar-db { background: #6d28d9; }
880
- .ss-dash-tl-bar-view { background: #0e7490; }
881
- .ss-dash-tl-bar-mail { background: #059669; }
882
- .ss-dash-tl-bar-event { background: #b45309; }
883
- .ss-dash-tl-bar-custom { background: var(--ss-dim); }
1135
+ .ss-dash-tl-bar-request {
1136
+ background: var(--ss-blue-bg);
1137
+ border: 1px solid var(--ss-blue-fg);
1138
+ }
1139
+ .ss-dash-tl-bar-middleware {
1140
+ background: var(--ss-blue-bg);
1141
+ opacity: 0.7;
1142
+ }
1143
+ .ss-dash-tl-bar-db {
1144
+ background: #6d28d9;
1145
+ }
1146
+ .ss-dash-tl-bar-view {
1147
+ background: #0e7490;
1148
+ }
1149
+ .ss-dash-tl-bar-mail {
1150
+ background: #059669;
1151
+ }
1152
+ .ss-dash-tl-bar-event {
1153
+ background: #b45309;
1154
+ }
1155
+ .ss-dash-tl-bar-custom {
1156
+ background: var(--ss-dim);
1157
+ }
884
1158
 
885
1159
  .ss-dash-tl-dur {
886
1160
  font-size: 10px;
@@ -966,7 +1240,9 @@ html, body {
966
1240
  letter-spacing: 0.04em;
967
1241
  font-weight: 600;
968
1242
  }
969
- .ss-dash-explain-btn:hover { opacity: 0.8; }
1243
+ .ss-dash-explain-btn:hover {
1244
+ opacity: 0.8;
1245
+ }
970
1246
  .ss-dash-explain-btn-active {
971
1247
  background: var(--ss-purple-fg);
972
1248
  color: #fff;
@@ -1065,10 +1341,18 @@ html, body {
1065
1341
  font-variant-numeric: tabular-nums;
1066
1342
  line-height: 1.2;
1067
1343
  }
1068
- .ss-dash-card-value.ss-dash-accent { color: var(--ss-accent); }
1069
- .ss-dash-card-value.ss-dash-amber { color: var(--ss-amber-fg); }
1070
- .ss-dash-card-value.ss-dash-red { color: var(--ss-red-fg); }
1071
- .ss-dash-card-value.ss-dash-dim { color: var(--ss-dim); }
1344
+ .ss-dash-card-value.ss-dash-accent {
1345
+ color: var(--ss-accent);
1346
+ }
1347
+ .ss-dash-card-value.ss-dash-amber {
1348
+ color: var(--ss-amber-fg);
1349
+ }
1350
+ .ss-dash-card-value.ss-dash-red {
1351
+ color: var(--ss-red-fg);
1352
+ }
1353
+ .ss-dash-card-value.ss-dash-dim {
1354
+ color: var(--ss-dim);
1355
+ }
1072
1356
 
1073
1357
  .ss-dash-sparkline {
1074
1358
  height: 30px;
@@ -1122,7 +1406,9 @@ html, body {
1122
1406
  height: 100%;
1123
1407
  }
1124
1408
  .ss-dash-chart-svg .ss-dash-chart-dot {
1125
- transition: r 0.15s ease, opacity 0.15s ease;
1409
+ transition:
1410
+ r 0.15s ease,
1411
+ opacity 0.15s ease;
1126
1412
  }
1127
1413
  .ss-dash-chart-svg .ss-dash-chart-hover-zone {
1128
1414
  cursor: crosshair;
@@ -1211,7 +1497,9 @@ html, body {
1211
1497
  white-space: nowrap;
1212
1498
  min-width: 0;
1213
1499
  }
1214
- .ss-dash-secondary-list li:last-child { border-bottom: none; }
1500
+ .ss-dash-secondary-list li:last-child {
1501
+ border-bottom: none;
1502
+ }
1215
1503
  .ss-dash-secondary-list-value {
1216
1504
  color: var(--ss-text-secondary);
1217
1505
  font-variant-numeric: tabular-nums;
@@ -1241,9 +1529,18 @@ html, body {
1241
1529
  border-radius: 4px;
1242
1530
  cursor: pointer;
1243
1531
  }
1244
- .ss-dash-page-btn:hover { color: var(--ss-text); border-color: var(--ss-dim); }
1245
- .ss-dash-page-btn.ss-dash-active { color: var(--ss-accent); border-color: var(--ss-accent); }
1246
- .ss-dash-page-btn:disabled { opacity: 0.3; cursor: default; }
1532
+ .ss-dash-page-btn:hover {
1533
+ color: var(--ss-text);
1534
+ border-color: var(--ss-dim);
1535
+ }
1536
+ .ss-dash-page-btn.ss-dash-active {
1537
+ color: var(--ss-accent);
1538
+ border-color: var(--ss-accent);
1539
+ }
1540
+ .ss-dash-page-btn:disabled {
1541
+ opacity: 0.3;
1542
+ cursor: default;
1543
+ }
1247
1544
 
1248
1545
  .ss-dash-page-info {
1249
1546
  font-size: 10px;
@@ -1259,7 +1556,9 @@ html, body {
1259
1556
  scrollbar-color: var(--ss-border) transparent;
1260
1557
  }
1261
1558
 
1262
- .ss-dash-config-env-table { table-layout: fixed; }
1559
+ .ss-dash-config-env-table {
1560
+ table-layout: fixed;
1561
+ }
1263
1562
  .ss-dash-env-key {
1264
1563
  width: 280px;
1265
1564
  min-width: 280px;
@@ -1312,7 +1611,9 @@ html, body {
1312
1611
  display: inline-flex;
1313
1612
  align-items: center;
1314
1613
  line-height: 1;
1315
- transition: color 0.15s, border-color 0.15s;
1614
+ transition:
1615
+ color 0.15s,
1616
+ border-color 0.15s;
1316
1617
  }
1317
1618
  .ss-dash-redacted-reveal:hover,
1318
1619
  .ss-dash-redacted-copy:hover {
@@ -1342,7 +1643,9 @@ html, body {
1342
1643
  font-weight: 600;
1343
1644
  transition: background 0.1s;
1344
1645
  }
1345
- .ss-dash-config-section-header:hover { background: var(--ss-hover); }
1646
+ .ss-dash-config-section-header:hover {
1647
+ background: var(--ss-hover);
1648
+ }
1346
1649
  .ss-dash-config-section-header.ss-dash-config-leaf {
1347
1650
  cursor: default;
1348
1651
  font-weight: 400;
@@ -1405,9 +1708,17 @@ html, body {
1405
1708
  opacity: 0;
1406
1709
  transition: opacity 0.1s;
1407
1710
  }
1408
- tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1409
- .ss-dash-copy-row-btn:hover { color: var(--ss-text); border-color: var(--ss-border); }
1410
- .ss-dash-copy-row-btn.ss-dash-copy-row-ok { color: var(--ss-green-fg); opacity: 1; }
1711
+ tr:hover .ss-dash-copy-row-btn {
1712
+ opacity: 1;
1713
+ }
1714
+ .ss-dash-copy-row-btn:hover {
1715
+ color: var(--ss-text);
1716
+ border-color: var(--ss-border);
1717
+ }
1718
+ .ss-dash-copy-row-btn.ss-dash-copy-row-ok {
1719
+ color: var(--ss-green-fg);
1720
+ opacity: 1;
1721
+ }
1411
1722
 
1412
1723
  /* ── Cache ─────────────────────────────────────────────────────── */
1413
1724
  .ss-dash-cache-stats {
@@ -1478,7 +1789,9 @@ tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1478
1789
  letter-spacing: 0.04em;
1479
1790
  font-weight: 600;
1480
1791
  }
1481
- .ss-dash-retry-btn:hover { opacity: 0.8; }
1792
+ .ss-dash-retry-btn:hover {
1793
+ opacity: 0.8;
1794
+ }
1482
1795
 
1483
1796
  /* ── Grouped queries toggle ────────────────────────────────────── */
1484
1797
  .ss-dash-grouped-header {
@@ -1488,12 +1801,21 @@ tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1488
1801
  }
1489
1802
 
1490
1803
  /* ── Filterable cell ───────────────────────────────────────────── */
1491
- .ss-dash-filterable { cursor: pointer; }
1492
- .ss-dash-filterable:hover { background: var(--ss-hover-accent); }
1804
+ .ss-dash-filterable {
1805
+ cursor: pointer;
1806
+ }
1807
+ .ss-dash-filterable:hover {
1808
+ background: var(--ss-hover-accent);
1809
+ }
1493
1810
 
1494
1811
  /* ── Reqid input in log bar ────────────────────────────────────── */
1495
- .ss-dash-reqid-input { max-width: 200px; margin-left: auto; }
1496
- .ss-dash-reqid-clear { margin-left: 4px; }
1812
+ .ss-dash-reqid-input {
1813
+ max-width: 200px;
1814
+ margin-left: auto;
1815
+ }
1816
+ .ss-dash-reqid-clear {
1817
+ margin-left: 4px;
1818
+ }
1497
1819
 
1498
1820
  /* ── Scrollable pane content ───────────────────────────────────── */
1499
1821
  .ss-dash-pane-inner {
@@ -1504,9 +1826,19 @@ tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1504
1826
  }
1505
1827
 
1506
1828
  /* ── Detail view for list/detail pattern ───────────────────────── */
1507
- .ss-dash-list-view { display: flex; flex-direction: column; height: 100%; }
1508
- .ss-dash-detail-view { display: none; flex-direction: column; height: 100%; }
1509
- .ss-dash-detail-view.ss-dash-active { display: flex; }
1829
+ .ss-dash-list-view {
1830
+ display: flex;
1831
+ flex-direction: column;
1832
+ height: 100%;
1833
+ }
1834
+ .ss-dash-detail-view {
1835
+ display: none;
1836
+ flex-direction: column;
1837
+ height: 100%;
1838
+ }
1839
+ .ss-dash-detail-view.ss-dash-active {
1840
+ display: flex;
1841
+ }
1510
1842
 
1511
1843
  /* Widget deep links */
1512
1844
  .ss-dash-widget-link {
@@ -1514,7 +1846,9 @@ tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1514
1846
  text-decoration: none;
1515
1847
  transition: color 0.15s;
1516
1848
  }
1517
- .ss-dash-widget-link:hover { color: var(--ss-accent); }
1849
+ .ss-dash-widget-link:hover {
1850
+ color: var(--ss-accent);
1851
+ }
1518
1852
 
1519
1853
  .ss-dash-widget-row-link {
1520
1854
  display: flex;
@@ -1528,8 +1862,12 @@ tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1528
1862
  min-width: 0;
1529
1863
  transition: color 0.15s;
1530
1864
  }
1531
- .ss-dash-widget-row-link:last-child { border-bottom: none; }
1532
- .ss-dash-widget-row-link:hover { color: var(--ss-accent); }
1865
+ .ss-dash-widget-row-link:last-child {
1866
+ border-bottom: none;
1867
+ }
1868
+ .ss-dash-widget-row-link:hover {
1869
+ color: var(--ss-accent);
1870
+ }
1533
1871
  .ss-dash-widget-row-link > span:first-child {
1534
1872
  overflow: hidden;
1535
1873
  text-overflow: ellipsis;
@@ -1544,6 +1882,13 @@ tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1544
1882
  font-size: 11px;
1545
1883
  border-bottom: 1px solid var(--ss-border-faint);
1546
1884
  }
1547
- .ss-dash-widget-stat:last-child { border-bottom: none; }
1548
- .ss-dash-widget-stat-label { color: var(--ss-muted); }
1549
- .ss-dash-widget-stat-value { font-weight: 600; font-variant-numeric: tabular-nums; }
1885
+ .ss-dash-widget-stat:last-child {
1886
+ border-bottom: none;
1887
+ }
1888
+ .ss-dash-widget-stat-label {
1889
+ color: var(--ss-muted);
1890
+ }
1891
+ .ss-dash-widget-stat-value {
1892
+ font-weight: 600;
1893
+ font-variant-numeric: tabular-nums;
1894
+ }