adonisjs-server-stats 1.2.2 → 1.3.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 (95) hide show
  1. package/README.md +144 -9
  2. package/dist/src/dashboard/chart_aggregator.d.ts +21 -0
  3. package/dist/src/dashboard/chart_aggregator.d.ts.map +1 -0
  4. package/dist/src/dashboard/chart_aggregator.js +89 -0
  5. package/dist/src/dashboard/dashboard_controller.d.ts +147 -0
  6. package/dist/src/dashboard/dashboard_controller.d.ts.map +1 -0
  7. package/dist/src/dashboard/dashboard_controller.js +1008 -0
  8. package/dist/src/dashboard/dashboard_routes.d.ts +16 -0
  9. package/dist/src/dashboard/dashboard_routes.d.ts.map +1 -0
  10. package/dist/src/dashboard/dashboard_routes.js +88 -0
  11. package/dist/src/dashboard/dashboard_store.d.ts +158 -0
  12. package/dist/src/dashboard/dashboard_store.d.ts.map +1 -0
  13. package/dist/src/dashboard/dashboard_store.js +723 -0
  14. package/dist/src/dashboard/integrations/cache_inspector.d.ts +88 -0
  15. package/dist/src/dashboard/integrations/cache_inspector.d.ts.map +1 -0
  16. package/dist/src/dashboard/integrations/cache_inspector.js +215 -0
  17. package/dist/src/dashboard/integrations/config_inspector.d.ts +33 -0
  18. package/dist/src/dashboard/integrations/config_inspector.d.ts.map +1 -0
  19. package/dist/src/dashboard/integrations/config_inspector.js +155 -0
  20. package/dist/src/dashboard/integrations/index.d.ts +7 -0
  21. package/dist/src/dashboard/integrations/index.d.ts.map +1 -0
  22. package/dist/src/dashboard/integrations/index.js +3 -0
  23. package/dist/src/dashboard/integrations/queue_inspector.d.ts +106 -0
  24. package/dist/src/dashboard/integrations/queue_inspector.d.ts.map +1 -0
  25. package/dist/src/dashboard/integrations/queue_inspector.js +182 -0
  26. package/dist/src/dashboard/migrator.d.ts +18 -0
  27. package/dist/src/dashboard/migrator.d.ts.map +1 -0
  28. package/dist/src/dashboard/migrator.js +144 -0
  29. package/dist/src/dashboard/models/stats_email.d.ts +19 -0
  30. package/dist/src/dashboard/models/stats_email.d.ts.map +1 -0
  31. package/dist/src/dashboard/models/stats_email.js +66 -0
  32. package/dist/src/dashboard/models/stats_event.d.ts +14 -0
  33. package/dist/src/dashboard/models/stats_event.d.ts.map +1 -0
  34. package/dist/src/dashboard/models/stats_event.js +43 -0
  35. package/dist/src/dashboard/models/stats_log.d.ts +12 -0
  36. package/dist/src/dashboard/models/stats_log.d.ts.map +1 -0
  37. package/dist/src/dashboard/models/stats_log.js +42 -0
  38. package/dist/src/dashboard/models/stats_metric.d.ts +15 -0
  39. package/dist/src/dashboard/models/stats_metric.d.ts.map +1 -0
  40. package/dist/src/dashboard/models/stats_metric.js +50 -0
  41. package/dist/src/dashboard/models/stats_query.d.ts +20 -0
  42. package/dist/src/dashboard/models/stats_query.d.ts.map +1 -0
  43. package/dist/src/dashboard/models/stats_query.js +67 -0
  44. package/dist/src/dashboard/models/stats_request.d.ts +21 -0
  45. package/dist/src/dashboard/models/stats_request.d.ts.map +1 -0
  46. package/dist/src/dashboard/models/stats_request.js +61 -0
  47. package/dist/src/dashboard/models/stats_saved_filter.d.ts +11 -0
  48. package/dist/src/dashboard/models/stats_saved_filter.d.ts.map +1 -0
  49. package/dist/src/dashboard/models/stats_saved_filter.js +38 -0
  50. package/dist/src/dashboard/models/stats_trace.d.ts +19 -0
  51. package/dist/src/dashboard/models/stats_trace.d.ts.map +1 -0
  52. package/dist/src/dashboard/models/stats_trace.js +67 -0
  53. package/dist/src/debug/debug_store.d.ts +5 -0
  54. package/dist/src/debug/debug_store.d.ts.map +1 -1
  55. package/dist/src/debug/debug_store.js +10 -0
  56. package/dist/src/debug/email_collector.d.ts +2 -0
  57. package/dist/src/debug/email_collector.d.ts.map +1 -1
  58. package/dist/src/debug/email_collector.js +4 -0
  59. package/dist/src/debug/event_collector.d.ts +2 -0
  60. package/dist/src/debug/event_collector.d.ts.map +1 -1
  61. package/dist/src/debug/event_collector.js +11 -2
  62. package/dist/src/debug/query_collector.d.ts +2 -0
  63. package/dist/src/debug/query_collector.d.ts.map +1 -1
  64. package/dist/src/debug/query_collector.js +11 -0
  65. package/dist/src/debug/ring_buffer.d.ts +3 -0
  66. package/dist/src/debug/ring_buffer.d.ts.map +1 -1
  67. package/dist/src/debug/ring_buffer.js +6 -0
  68. package/dist/src/debug/trace_collector.d.ts +4 -2
  69. package/dist/src/debug/trace_collector.d.ts.map +1 -1
  70. package/dist/src/debug/trace_collector.js +7 -2
  71. package/dist/src/debug/types.d.ts +8 -0
  72. package/dist/src/debug/types.d.ts.map +1 -1
  73. package/dist/src/edge/client/dashboard.css +1504 -0
  74. package/dist/src/edge/client/dashboard.js +2378 -0
  75. package/dist/src/edge/client/debug-panel.css +528 -108
  76. package/dist/src/edge/client/debug-panel.js +663 -22
  77. package/dist/src/edge/client/stats-bar.css +112 -38
  78. package/dist/src/edge/client/stats-bar.js +37 -3
  79. package/dist/src/edge/plugin.d.ts.map +1 -1
  80. package/dist/src/edge/plugin.js +21 -0
  81. package/dist/src/edge/views/dashboard.edge +382 -0
  82. package/dist/src/edge/views/debug-panel.edge +60 -14
  83. package/dist/src/edge/views/stats-bar.edge +9 -0
  84. package/dist/src/index.d.ts +2 -0
  85. package/dist/src/index.d.ts.map +1 -1
  86. package/dist/src/index.js +1 -0
  87. package/dist/src/middleware/request_tracking_middleware.d.ts +20 -0
  88. package/dist/src/middleware/request_tracking_middleware.d.ts.map +1 -1
  89. package/dist/src/middleware/request_tracking_middleware.js +66 -2
  90. package/dist/src/provider/server_stats_provider.d.ts +13 -0
  91. package/dist/src/provider/server_stats_provider.d.ts.map +1 -1
  92. package/dist/src/provider/server_stats_provider.js +175 -1
  93. package/dist/src/types.d.ts +42 -0
  94. package/dist/src/types.d.ts.map +1 -1
  95. package/package.json +14 -1
@@ -0,0 +1,1504 @@
1
+ /* Full-page dashboard styles for adonisjs-server-stats.
2
+ * All classes use the `.ss-dash-` prefix to avoid conflicts.
3
+ * Two themes via CSS custom properties + @media (prefers-color-scheme).
4
+ */
5
+
6
+ /* ── Theme: Dark (default) ─────────────────────────────────────── */
7
+ :root {
8
+ --ss-bg: #0f0f0f;
9
+ --ss-surface: #171717;
10
+ --ss-surface-alt: #141414;
11
+ --ss-text: #e5e5e5;
12
+ --ss-text-secondary: #b5b5b5;
13
+ --ss-accent: #34d399;
14
+ --ss-accent-dim: #064e3b;
15
+ --ss-border: #333;
16
+ --ss-border-dim: #262626;
17
+ --ss-border-faint: #1f1f1f;
18
+ --ss-muted: #9ca3af;
19
+ --ss-dim: #6b7280;
20
+ --ss-hover: rgba(38, 38, 38, 0.4);
21
+ --ss-hover-accent: rgba(52, 211, 153, 0.08);
22
+ --ss-input-bg: #1a1a1a;
23
+ --ss-shadow: rgb(0 0 0 / 0.4);
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;
30
+ --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;
34
+ }
35
+
36
+ /* ── Theme: Light ──────────────────────────────────────────────── */
37
+ @media (prefers-color-scheme: light) {
38
+ :root {
39
+ --ss-bg: #fafafa;
40
+ --ss-surface: #ffffff;
41
+ --ss-surface-alt: #f5f5f5;
42
+ --ss-text: #171717;
43
+ --ss-text-secondary: #525252;
44
+ --ss-accent: #059669;
45
+ --ss-accent-dim: #d1fae5;
46
+ --ss-border: #e5e5e5;
47
+ --ss-border-dim: #e5e5e5;
48
+ --ss-border-faint: #f0f0f0;
49
+ --ss-muted: #6b7280;
50
+ --ss-dim: #9ca3af;
51
+ --ss-hover: rgba(0, 0, 0, 0.03);
52
+ --ss-hover-accent: rgba(5, 150, 105, 0.06);
53
+ --ss-input-bg: #ffffff;
54
+ --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;
60
+ --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;
64
+ }
65
+ }
66
+
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;
94
+ }
95
+ [data-theme="light"] {
96
+ --ss-bg: #fafafa;
97
+ --ss-surface: #ffffff;
98
+ --ss-surface-alt: #f5f5f5;
99
+ --ss-text: #171717;
100
+ --ss-text-secondary: #525252;
101
+ --ss-accent: #059669;
102
+ --ss-accent-dim: #d1fae5;
103
+ --ss-border: #e5e5e5;
104
+ --ss-border-dim: #e5e5e5;
105
+ --ss-border-faint: #f0f0f0;
106
+ --ss-muted: #6b7280;
107
+ --ss-dim: #9ca3af;
108
+ --ss-hover: rgba(0, 0, 0, 0.03);
109
+ --ss-hover-accent: rgba(5, 150, 105, 0.06);
110
+ --ss-input-bg: #ffffff;
111
+ --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;
117
+ --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;
121
+ }
122
+
123
+ /* ── Reset & base ──────────────────────────────────────────────── */
124
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
125
+
126
+ html, body {
127
+ height: 100%;
128
+ overflow: hidden;
129
+ background: var(--ss-bg);
130
+ color: var(--ss-text);
131
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
132
+ font-size: 12px;
133
+ line-height: 1.5;
134
+ -webkit-font-smoothing: antialiased;
135
+ }
136
+
137
+ /* ── Page layout ───────────────────────────────────────────────── */
138
+ #ss-dash {
139
+ display: flex;
140
+ flex-direction: column;
141
+ height: 100vh;
142
+ }
143
+
144
+ .ss-dash-header {
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: space-between;
148
+ height: 42px;
149
+ padding: 0 16px;
150
+ background: var(--ss-surface);
151
+ border-bottom: 1px solid var(--ss-border);
152
+ flex-shrink: 0;
153
+ z-index: 10;
154
+ }
155
+
156
+ .ss-dash-header-left {
157
+ display: flex;
158
+ align-items: center;
159
+ gap: 10px;
160
+ }
161
+
162
+ .ss-dash-logo {
163
+ font-size: 13px;
164
+ font-weight: 700;
165
+ color: var(--ss-accent);
166
+ letter-spacing: -0.02em;
167
+ }
168
+
169
+ .ss-dash-logo-sub {
170
+ font-size: 10px;
171
+ color: var(--ss-dim);
172
+ font-weight: 400;
173
+ }
174
+
175
+ .ss-dash-header-center {
176
+ display: flex;
177
+ align-items: center;
178
+ gap: 6px;
179
+ }
180
+
181
+ .ss-dash-live-dot {
182
+ width: 7px;
183
+ height: 7px;
184
+ border-radius: 50%;
185
+ background: var(--ss-dim);
186
+ flex-shrink: 0;
187
+ }
188
+ .ss-dash-live-dot.ss-dash-connected {
189
+ background: var(--ss-accent);
190
+ box-shadow: 0 0 6px var(--ss-accent);
191
+ animation: ss-dash-pulse 2s infinite;
192
+ }
193
+ @keyframes ss-dash-pulse {
194
+ 0%, 100% { opacity: 1; }
195
+ 50% { opacity: 0.5; }
196
+ }
197
+
198
+ .ss-dash-live-label {
199
+ font-size: 10px;
200
+ color: var(--ss-dim);
201
+ text-transform: uppercase;
202
+ letter-spacing: 0.05em;
203
+ }
204
+ .ss-dash-live-label.ss-dash-connected { color: var(--ss-accent); }
205
+
206
+ .ss-dash-header-right {
207
+ display: flex;
208
+ align-items: center;
209
+ gap: 8px;
210
+ }
211
+
212
+ .ss-dash-theme-btn,
213
+ .ss-dash-back-link {
214
+ padding: 4px 8px;
215
+ font-size: 14px;
216
+ color: var(--ss-muted);
217
+ cursor: pointer;
218
+ border: none;
219
+ background: none;
220
+ font-family: inherit;
221
+ border-radius: 4px;
222
+ }
223
+ .ss-dash-theme-btn:hover,
224
+ .ss-dash-back-link:hover { color: var(--ss-text); background: var(--ss-hover); }
225
+
226
+ .ss-dash-back-link {
227
+ font-size: 10px;
228
+ text-decoration: none;
229
+ text-transform: uppercase;
230
+ letter-spacing: 0.04em;
231
+ }
232
+
233
+ /* ── Body: sidebar + main ──────────────────────────────────────── */
234
+ .ss-dash-body {
235
+ display: flex;
236
+ flex: 1;
237
+ overflow: hidden;
238
+ }
239
+
240
+ /* ── Sidebar ───────────────────────────────────────────────────── */
241
+ .ss-dash-sidebar {
242
+ width: 220px;
243
+ min-width: 220px;
244
+ background: var(--ss-surface);
245
+ border-right: 1px solid var(--ss-border);
246
+ display: flex;
247
+ flex-direction: column;
248
+ overflow-y: auto;
249
+ overflow-x: hidden;
250
+ transition: width 0.2s ease, min-width 0.2s ease;
251
+ scrollbar-width: none;
252
+ -ms-overflow-style: none;
253
+ }
254
+ .ss-dash-sidebar::-webkit-scrollbar { display: none; }
255
+
256
+ .ss-dash-sidebar.ss-dash-collapsed {
257
+ width: 56px;
258
+ min-width: 56px;
259
+ }
260
+
261
+ .ss-dash-nav {
262
+ flex: 1;
263
+ padding: 8px 0;
264
+ }
265
+
266
+ .ss-dash-nav-item {
267
+ display: flex;
268
+ align-items: center;
269
+ gap: 10px;
270
+ padding: 7px 16px;
271
+ cursor: pointer;
272
+ color: var(--ss-muted);
273
+ font-size: 11px;
274
+ font-weight: 500;
275
+ border: none;
276
+ background: none;
277
+ width: 100%;
278
+ text-align: left;
279
+ font-family: inherit;
280
+ transition: color 0.15s, background 0.15s;
281
+ position: relative;
282
+ white-space: nowrap;
283
+ }
284
+ .ss-dash-nav-item:hover { color: var(--ss-text-secondary); background: var(--ss-hover); }
285
+ .ss-dash-nav-item.ss-dash-active {
286
+ color: var(--ss-accent);
287
+ background: var(--ss-hover-accent);
288
+ }
289
+ .ss-dash-nav-item.ss-dash-active::before {
290
+ content: '';
291
+ position: absolute;
292
+ left: 0;
293
+ top: 4px;
294
+ bottom: 4px;
295
+ width: 3px;
296
+ background: var(--ss-accent);
297
+ border-radius: 0 2px 2px 0;
298
+ }
299
+
300
+ .ss-dash-nav-icon {
301
+ width: 20px;
302
+ height: 20px;
303
+ flex-shrink: 0;
304
+ display: flex;
305
+ align-items: center;
306
+ justify-content: center;
307
+ }
308
+ .ss-dash-nav-icon svg {
309
+ width: 16px;
310
+ height: 16px;
311
+ fill: none;
312
+ stroke: currentColor;
313
+ stroke-width: 1.5;
314
+ stroke-linecap: round;
315
+ stroke-linejoin: round;
316
+ }
317
+
318
+ .ss-dash-nav-label {
319
+ overflow: hidden;
320
+ text-overflow: ellipsis;
321
+ }
322
+ .ss-dash-collapsed .ss-dash-nav-label { display: none; }
323
+
324
+ .ss-dash-nav-badge {
325
+ margin-left: auto;
326
+ font-size: 9px;
327
+ padding: 1px 6px;
328
+ border-radius: 8px;
329
+ background: var(--ss-border-dim);
330
+ color: var(--ss-muted);
331
+ font-weight: 600;
332
+ font-variant-numeric: tabular-nums;
333
+ }
334
+ .ss-dash-nav-badge.ss-dash-badge-accent {
335
+ background: var(--ss-accent-dim);
336
+ color: var(--ss-accent);
337
+ }
338
+ .ss-dash-nav-badge.ss-dash-badge-red {
339
+ background: var(--ss-red-bg);
340
+ color: var(--ss-red-fg);
341
+ }
342
+ .ss-dash-collapsed .ss-dash-nav-badge { display: none; }
343
+
344
+ .ss-dash-nav-sep {
345
+ height: 1px;
346
+ background: var(--ss-border-dim);
347
+ margin: 6px 12px;
348
+ }
349
+
350
+ .ss-dash-sidebar-toggle {
351
+ display: flex;
352
+ align-items: center;
353
+ justify-content: center;
354
+ padding: 10px;
355
+ cursor: pointer;
356
+ color: var(--ss-dim);
357
+ border: none;
358
+ background: none;
359
+ font-family: inherit;
360
+ font-size: 14px;
361
+ border-top: 1px solid var(--ss-border-dim);
362
+ flex-shrink: 0;
363
+ }
364
+ .ss-dash-sidebar-toggle:hover { color: var(--ss-text-secondary); background: var(--ss-hover); }
365
+
366
+ /* ── Main content ──────────────────────────────────────────────── */
367
+ .ss-dash-main {
368
+ flex: 1;
369
+ overflow: auto;
370
+ background: var(--ss-bg);
371
+ scrollbar-width: thin;
372
+ scrollbar-color: var(--ss-border) transparent;
373
+ }
374
+
375
+ .ss-dash-pane {
376
+ display: none;
377
+ height: 100%;
378
+ overflow: auto;
379
+ scrollbar-width: thin;
380
+ scrollbar-color: var(--ss-border) transparent;
381
+ }
382
+ .ss-dash-pane.ss-dash-active { display: flex; flex-direction: column; }
383
+
384
+ /* ── Search bar ────────────────────────────────────────────────── */
385
+ .ss-dash-search-bar {
386
+ display: flex;
387
+ align-items: center;
388
+ gap: 8px;
389
+ padding: 8px 16px;
390
+ border-bottom: 1px solid var(--ss-border-dim);
391
+ background: var(--ss-surface-alt);
392
+ flex-shrink: 0;
393
+ flex-wrap: wrap;
394
+ }
395
+
396
+ .ss-dash-search {
397
+ flex: 1;
398
+ min-width: 200px;
399
+ padding: 5px 10px;
400
+ font-size: 11px;
401
+ font-family: inherit;
402
+ color: var(--ss-text);
403
+ background: var(--ss-input-bg);
404
+ border: 1px solid var(--ss-border);
405
+ border-radius: 4px;
406
+ outline: none;
407
+ }
408
+ .ss-dash-search:focus { border-color: var(--ss-accent); }
409
+ .ss-dash-search::placeholder { color: var(--ss-dim); }
410
+
411
+ .ss-dash-summary {
412
+ font-size: 11px;
413
+ color: var(--ss-muted);
414
+ white-space: nowrap;
415
+ padding: 0 4px;
416
+ }
417
+
418
+ /* ── Buttons ───────────────────────────────────────────────────── */
419
+ .ss-dash-btn {
420
+ padding: 4px 10px;
421
+ font-size: 10px;
422
+ font-family: inherit;
423
+ color: var(--ss-muted);
424
+ background: var(--ss-surface);
425
+ border: 1px solid var(--ss-border);
426
+ border-radius: 4px;
427
+ cursor: pointer;
428
+ text-transform: uppercase;
429
+ letter-spacing: 0.03em;
430
+ font-weight: 500;
431
+ white-space: nowrap;
432
+ }
433
+ .ss-dash-btn:hover { color: var(--ss-text); border-color: var(--ss-dim); }
434
+ .ss-dash-btn.ss-dash-active {
435
+ color: var(--ss-accent);
436
+ border-color: var(--ss-accent);
437
+ background: var(--ss-accent-dim);
438
+ }
439
+
440
+ .ss-dash-btn-group {
441
+ display: flex;
442
+ gap: 0;
443
+ }
444
+ .ss-dash-btn-group .ss-dash-btn {
445
+ border-radius: 0;
446
+ margin-left: -1px;
447
+ }
448
+ .ss-dash-btn-group .ss-dash-btn:first-child {
449
+ border-radius: 4px 0 0 4px;
450
+ margin-left: 0;
451
+ }
452
+ .ss-dash-btn-group .ss-dash-btn:last-child {
453
+ border-radius: 0 4px 4px 0;
454
+ }
455
+
456
+ /* ── Tables ────────────────────────────────────────────────────── */
457
+ .ss-dash-table-wrap {
458
+ flex: 1;
459
+ overflow: auto;
460
+ scrollbar-width: thin;
461
+ scrollbar-color: var(--ss-border) transparent;
462
+ }
463
+
464
+ .ss-dash-table {
465
+ width: 100%;
466
+ border-collapse: collapse;
467
+ font-size: 11px;
468
+ }
469
+ .ss-dash-table th {
470
+ position: sticky;
471
+ top: 0;
472
+ padding: 7px 12px;
473
+ text-align: left;
474
+ font-weight: 600;
475
+ font-size: 10px;
476
+ text-transform: uppercase;
477
+ letter-spacing: 0.05em;
478
+ color: var(--ss-muted);
479
+ background: var(--ss-surface);
480
+ border-bottom: 1px solid var(--ss-border);
481
+ white-space: nowrap;
482
+ z-index: 2;
483
+ }
484
+ .ss-dash-table td {
485
+ padding: 6px 12px;
486
+ border-bottom: 1px solid var(--ss-border-faint);
487
+ vertical-align: top;
488
+ max-width: 0;
489
+ }
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); }
494
+
495
+ /* ── Method badges ─────────────────────────────────────────────── */
496
+ .ss-dash-method {
497
+ display: inline-block;
498
+ padding: 1px 5px;
499
+ border-radius: 3px;
500
+ font-size: 10px;
501
+ font-weight: 600;
502
+ letter-spacing: 0.03em;
503
+ text-transform: uppercase;
504
+ }
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); }
514
+
515
+ /* ── Status badges ─────────────────────────────────────────────── */
516
+ .ss-dash-status {
517
+ font-size: 10px;
518
+ font-weight: 600;
519
+ padding: 1px 5px;
520
+ border-radius: 3px;
521
+ }
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); }
526
+
527
+ /* ── Badge generic ─────────────────────────────────────────────── */
528
+ .ss-dash-badge {
529
+ display: inline-block;
530
+ padding: 1px 6px;
531
+ border-radius: 3px;
532
+ font-size: 10px;
533
+ font-weight: 600;
534
+ text-transform: uppercase;
535
+ }
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); }
542
+
543
+ /* ── 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); }
547
+
548
+ /* ── SQL ───────────────────────────────────────────────────────── */
549
+ .ss-dash-sql {
550
+ font-size: 11px;
551
+ color: var(--ss-sql-color);
552
+ word-break: break-all;
553
+ cursor: pointer;
554
+ max-width: 600px;
555
+ overflow: hidden;
556
+ text-overflow: ellipsis;
557
+ white-space: nowrap;
558
+ display: inline-block;
559
+ }
560
+ .ss-dash-sql.ss-dash-expanded {
561
+ white-space: pre-wrap;
562
+ max-width: none;
563
+ }
564
+
565
+ .ss-dash-dup { color: var(--ss-purple-fg); font-size: 10px; font-weight: 600; }
566
+
567
+ /* ── Current route highlight ───────────────────────────────────── */
568
+ .ss-dash-current-route td { background: var(--ss-hover-accent) !important; }
569
+
570
+ /* ── Data preview / expand ─────────────────────────────────────── */
571
+ .ss-dash-data-preview {
572
+ cursor: pointer;
573
+ color: var(--ss-text-secondary);
574
+ border-bottom: 1px dashed var(--ss-dim);
575
+ }
576
+ .ss-dash-data-preview:hover { color: var(--ss-text); }
577
+
578
+ .ss-dash-data-full {
579
+ margin: 4px 0 0;
580
+ padding: 8px;
581
+ background: var(--ss-input-bg);
582
+ border: 1px solid var(--ss-border);
583
+ border-radius: 4px;
584
+ color: var(--ss-text-secondary);
585
+ font-size: 10px;
586
+ font-family: inherit;
587
+ white-space: pre-wrap;
588
+ word-break: break-all;
589
+ max-height: 300px;
590
+ overflow: auto;
591
+ cursor: pointer;
592
+ scrollbar-width: thin;
593
+ }
594
+
595
+ .ss-dash-copy-btn {
596
+ margin-left: 6px;
597
+ padding: 1px 5px;
598
+ font-size: 11px;
599
+ color: var(--ss-dim);
600
+ background: none;
601
+ border: 1px solid transparent;
602
+ border-radius: 3px;
603
+ cursor: pointer;
604
+ font-family: inherit;
605
+ vertical-align: middle;
606
+ }
607
+ .ss-dash-copy-btn:hover { color: var(--ss-text-secondary); border-color: var(--ss-border); }
608
+
609
+ /* ── Empty state ───────────────────────────────────────────────── */
610
+ .ss-dash-empty {
611
+ display: flex;
612
+ align-items: center;
613
+ justify-content: center;
614
+ height: 100%;
615
+ min-height: 120px;
616
+ color: var(--ss-dim);
617
+ font-size: 12px;
618
+ flex: 1;
619
+ }
620
+
621
+ /* ── 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; }
625
+
626
+ /* ── Logs ──────────────────────────────────────────────────────── */
627
+ .ss-dash-log-filters {
628
+ display: flex;
629
+ gap: 4px;
630
+ padding: 8px 16px;
631
+ border-bottom: 1px solid var(--ss-border-dim);
632
+ background: var(--ss-surface-alt);
633
+ flex-shrink: 0;
634
+ flex-wrap: wrap;
635
+ align-items: center;
636
+ }
637
+
638
+ .ss-dash-log-filter {
639
+ padding: 3px 10px;
640
+ font-size: 10px;
641
+ font-family: inherit;
642
+ border: 1px solid var(--ss-border);
643
+ border-radius: 4px;
644
+ cursor: pointer;
645
+ background: none;
646
+ color: var(--ss-muted);
647
+ text-transform: uppercase;
648
+ }
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); }
651
+
652
+ .ss-dash-log-entries {
653
+ flex: 1;
654
+ overflow: auto;
655
+ scrollbar-width: thin;
656
+ }
657
+
658
+ .ss-dash-log-entry {
659
+ padding: 4px 16px;
660
+ font-size: 11px;
661
+ border-bottom: 1px solid var(--ss-border-faint);
662
+ display: flex;
663
+ gap: 8px;
664
+ align-items: baseline;
665
+ }
666
+ .ss-dash-log-entry:hover { background: var(--ss-hover); }
667
+
668
+ .ss-dash-log-level {
669
+ font-size: 10px;
670
+ font-weight: 600;
671
+ width: 42px;
672
+ text-align: center;
673
+ flex-shrink: 0;
674
+ padding: 1px 0;
675
+ border-radius: 3px;
676
+ }
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); }
682
+
683
+ .ss-dash-log-time { color: var(--ss-dim); font-size: 10px; font-variant-numeric: tabular-nums; flex-shrink: 0; }
684
+ .ss-dash-log-reqid {
685
+ font-size: 10px;
686
+ color: var(--ss-reqid-fg);
687
+ background: var(--ss-reqid-bg);
688
+ padding: 1px 5px;
689
+ border-radius: 3px;
690
+ cursor: pointer;
691
+ flex-shrink: 0;
692
+ font-family: inherit;
693
+ letter-spacing: 0.02em;
694
+ }
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; }
698
+
699
+ /* ── Structured log search ─────────────────────────────────────── */
700
+ .ss-dash-structured-search {
701
+ display: flex;
702
+ gap: 6px;
703
+ align-items: center;
704
+ flex-wrap: wrap;
705
+ padding: 8px 16px;
706
+ border-bottom: 1px solid var(--ss-border-dim);
707
+ background: var(--ss-surface-alt);
708
+ flex-shrink: 0;
709
+ }
710
+
711
+ .ss-dash-filter-select,
712
+ .ss-dash-filter-input {
713
+ padding: 4px 8px;
714
+ font-size: 11px;
715
+ font-family: inherit;
716
+ color: var(--ss-text);
717
+ background: var(--ss-input-bg);
718
+ border: 1px solid var(--ss-border);
719
+ border-radius: 4px;
720
+ outline: none;
721
+ }
722
+ .ss-dash-filter-select:focus,
723
+ .ss-dash-filter-input:focus { border-color: var(--ss-accent); }
724
+
725
+ .ss-dash-filter-select { min-width: 100px; }
726
+ .ss-dash-filter-input { min-width: 150px; flex: 1; max-width: 300px; }
727
+
728
+ .ss-dash-filter-chips {
729
+ display: flex;
730
+ gap: 4px;
731
+ flex-wrap: wrap;
732
+ }
733
+
734
+ .ss-dash-filter-chip {
735
+ display: inline-flex;
736
+ align-items: center;
737
+ gap: 4px;
738
+ padding: 2px 8px;
739
+ font-size: 10px;
740
+ background: var(--ss-accent-dim);
741
+ color: var(--ss-accent);
742
+ border-radius: 4px;
743
+ font-family: inherit;
744
+ }
745
+ .ss-dash-filter-chip-remove {
746
+ cursor: pointer;
747
+ font-size: 12px;
748
+ line-height: 1;
749
+ color: var(--ss-accent);
750
+ background: none;
751
+ border: none;
752
+ font-family: inherit;
753
+ padding: 0;
754
+ }
755
+ .ss-dash-filter-chip-remove:hover { color: var(--ss-text); }
756
+
757
+ /* ── Saved filters ─────────────────────────────────────────────── */
758
+ .ss-dash-saved-filters {
759
+ display: flex;
760
+ gap: 6px;
761
+ align-items: center;
762
+ margin-left: auto;
763
+ }
764
+
765
+ .ss-dash-saved-select {
766
+ padding: 4px 8px;
767
+ font-size: 10px;
768
+ font-family: inherit;
769
+ color: var(--ss-text);
770
+ background: var(--ss-input-bg);
771
+ border: 1px solid var(--ss-border);
772
+ border-radius: 4px;
773
+ outline: none;
774
+ min-width: 120px;
775
+ }
776
+
777
+ /* ── Email preview ─────────────────────────────────────────────── */
778
+ .ss-dash-email-preview {
779
+ position: absolute;
780
+ inset: 0;
781
+ display: flex;
782
+ flex-direction: column;
783
+ background: var(--ss-bg);
784
+ z-index: 30;
785
+ }
786
+ .ss-dash-email-preview-header {
787
+ display: flex;
788
+ align-items: flex-start;
789
+ justify-content: space-between;
790
+ gap: 12px;
791
+ padding: 10px 16px;
792
+ border-bottom: 1px solid var(--ss-border-dim);
793
+ background: var(--ss-surface-alt);
794
+ flex-shrink: 0;
795
+ }
796
+ .ss-dash-email-preview-meta {
797
+ font-size: 11px;
798
+ color: var(--ss-text-secondary);
799
+ line-height: 1.6;
800
+ overflow: hidden;
801
+ }
802
+ .ss-dash-email-preview-meta strong { color: var(--ss-text); font-weight: 600; }
803
+ .ss-dash-email-iframe {
804
+ flex: 1;
805
+ border: none;
806
+ background: #fff;
807
+ }
808
+
809
+ .ss-dash-email-row { cursor: pointer; }
810
+ .ss-dash-email-row:hover td { background: var(--ss-hover-accent) !important; }
811
+
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;
819
+ }
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
+
825
+ /* ── Timeline / Waterfall ──────────────────────────────────────── */
826
+ .ss-dash-tl-detail-header {
827
+ display: flex;
828
+ align-items: center;
829
+ gap: 12px;
830
+ padding: 8px 16px;
831
+ border-bottom: 1px solid var(--ss-border-dim);
832
+ background: var(--ss-surface-alt);
833
+ flex-shrink: 0;
834
+ }
835
+
836
+ .ss-dash-tl-waterfall {
837
+ padding: 8px 16px;
838
+ overflow: auto;
839
+ flex: 1;
840
+ scrollbar-width: thin;
841
+ }
842
+
843
+ .ss-dash-tl-row {
844
+ display: flex;
845
+ align-items: center;
846
+ height: 26px;
847
+ font-size: 11px;
848
+ border-bottom: 1px solid var(--ss-border-faint);
849
+ }
850
+ .ss-dash-tl-row:hover { background: var(--ss-hover); }
851
+
852
+ .ss-dash-tl-label {
853
+ width: 320px;
854
+ min-width: 320px;
855
+ padding-right: 8px;
856
+ overflow: hidden;
857
+ text-overflow: ellipsis;
858
+ white-space: nowrap;
859
+ color: var(--ss-text-secondary);
860
+ font-size: 10px;
861
+ }
862
+
863
+ .ss-dash-tl-track {
864
+ flex: 1;
865
+ position: relative;
866
+ height: 18px;
867
+ }
868
+
869
+ .ss-dash-tl-bar {
870
+ position: absolute;
871
+ height: 14px;
872
+ top: 2px;
873
+ border-radius: 2px;
874
+ min-width: 2px;
875
+ cursor: default;
876
+ }
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); }
884
+
885
+ .ss-dash-tl-dur {
886
+ font-size: 10px;
887
+ color: var(--ss-dim);
888
+ margin-left: 6px;
889
+ white-space: nowrap;
890
+ font-variant-numeric: tabular-nums;
891
+ min-width: 60px;
892
+ text-align: right;
893
+ }
894
+
895
+ .ss-dash-tl-legend {
896
+ display: flex;
897
+ gap: 14px;
898
+ padding: 6px 16px;
899
+ border-bottom: 1px solid var(--ss-border-dim);
900
+ background: var(--ss-surface-alt);
901
+ font-size: 10px;
902
+ color: var(--ss-muted);
903
+ flex-shrink: 0;
904
+ }
905
+ .ss-dash-tl-legend-item {
906
+ display: flex;
907
+ align-items: center;
908
+ gap: 4px;
909
+ }
910
+ .ss-dash-tl-legend-dot {
911
+ width: 8px;
912
+ height: 8px;
913
+ border-radius: 2px;
914
+ flex-shrink: 0;
915
+ }
916
+
917
+ .ss-dash-tl-warnings {
918
+ margin-top: 12px;
919
+ padding: 8px 16px;
920
+ border-top: 1px solid var(--ss-border-dim);
921
+ }
922
+ .ss-dash-tl-warnings-title {
923
+ font-size: 10px;
924
+ font-weight: 600;
925
+ color: var(--ss-amber-fg);
926
+ text-transform: uppercase;
927
+ letter-spacing: 0.05em;
928
+ margin-bottom: 4px;
929
+ }
930
+ .ss-dash-tl-warning {
931
+ font-size: 11px;
932
+ color: var(--ss-amber-fg);
933
+ padding: 2px 0;
934
+ }
935
+
936
+ .ss-dash-tl-meta {
937
+ font-size: 10px;
938
+ color: var(--ss-dim);
939
+ margin-left: 8px;
940
+ }
941
+
942
+ /* ── EXPLAIN panel ─────────────────────────────────────────────── */
943
+ .ss-dash-explain-row td {
944
+ white-space: normal;
945
+ overflow: visible;
946
+ max-width: none;
947
+ }
948
+ .ss-dash-explain {
949
+ padding: 12px 16px;
950
+ background: var(--ss-surface-alt);
951
+ border-top: 1px solid var(--ss-border-dim);
952
+ font-size: 11px;
953
+ overflow: hidden;
954
+ word-break: break-word;
955
+ }
956
+ .ss-dash-explain-btn {
957
+ padding: 2px 8px;
958
+ font-size: 9px;
959
+ font-family: inherit;
960
+ color: var(--ss-purple-fg);
961
+ background: var(--ss-purple-bg);
962
+ border: none;
963
+ border-radius: 3px;
964
+ cursor: pointer;
965
+ text-transform: uppercase;
966
+ letter-spacing: 0.04em;
967
+ font-weight: 600;
968
+ }
969
+ .ss-dash-explain-btn:hover { opacity: 0.8; }
970
+ .ss-dash-explain-btn-active {
971
+ background: var(--ss-purple-fg);
972
+ color: #fff;
973
+ }
974
+ .ss-dash-explain-result {
975
+ margin-top: 6px;
976
+ font-size: 11px;
977
+ color: var(--ss-text-secondary);
978
+ }
979
+ .ss-dash-explain-error {
980
+ color: var(--ss-red-fg);
981
+ padding: 8px;
982
+ background: var(--ss-red-bg);
983
+ border-radius: 4px;
984
+ }
985
+ .ss-dash-explain-node {
986
+ padding: 4px 0;
987
+ border-left: 2px solid var(--ss-border-dim);
988
+ padding-left: 10px;
989
+ margin-top: 2px;
990
+ }
991
+ .ss-dash-explain-node:first-child {
992
+ border-left: 2px solid var(--ss-purple-fg);
993
+ }
994
+ .ss-dash-explain-node-header {
995
+ font-weight: 600;
996
+ color: var(--ss-text-primary);
997
+ font-size: 11px;
998
+ }
999
+ .ss-dash-explain-node-type {
1000
+ color: var(--ss-purple-fg);
1001
+ font-weight: 700;
1002
+ }
1003
+ .ss-dash-explain-metrics {
1004
+ font-size: 10px;
1005
+ color: var(--ss-dim);
1006
+ margin-top: 1px;
1007
+ font-family: var(--ss-font-mono);
1008
+ word-break: break-all;
1009
+ overflow-wrap: break-word;
1010
+ }
1011
+ .ss-dash-explain-result table {
1012
+ width: 100%;
1013
+ border-collapse: collapse;
1014
+ margin-top: 4px;
1015
+ }
1016
+ .ss-dash-explain-result th {
1017
+ padding: 3px 8px;
1018
+ text-align: left;
1019
+ font-weight: 600;
1020
+ color: var(--ss-muted);
1021
+ border-bottom: 1px solid var(--ss-border);
1022
+ font-size: 9px;
1023
+ text-transform: uppercase;
1024
+ }
1025
+ .ss-dash-explain-result td {
1026
+ padding: 3px 8px;
1027
+ border-bottom: 1px solid var(--ss-border-faint);
1028
+ color: var(--ss-text-secondary);
1029
+ }
1030
+
1031
+ /* ── Overview cards ────────────────────────────────────────────── */
1032
+ .ss-dash-overview {
1033
+ padding: 16px;
1034
+ }
1035
+
1036
+ .ss-dash-cards {
1037
+ display: grid;
1038
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
1039
+ gap: 12px;
1040
+ margin-bottom: 16px;
1041
+ }
1042
+
1043
+ .ss-dash-card {
1044
+ background: var(--ss-surface);
1045
+ border: 1px solid var(--ss-border);
1046
+ border-radius: 6px;
1047
+ padding: 14px 16px;
1048
+ display: flex;
1049
+ flex-direction: column;
1050
+ gap: 4px;
1051
+ }
1052
+
1053
+ .ss-dash-card-title {
1054
+ font-size: 10px;
1055
+ text-transform: uppercase;
1056
+ letter-spacing: 0.05em;
1057
+ color: var(--ss-muted);
1058
+ font-weight: 600;
1059
+ }
1060
+
1061
+ .ss-dash-card-value {
1062
+ font-size: 22px;
1063
+ font-weight: 700;
1064
+ color: var(--ss-text);
1065
+ font-variant-numeric: tabular-nums;
1066
+ line-height: 1.2;
1067
+ }
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); }
1072
+
1073
+ .ss-dash-sparkline {
1074
+ height: 30px;
1075
+ margin-top: 4px;
1076
+ }
1077
+ .ss-dash-sparkline svg {
1078
+ width: 100%;
1079
+ height: 100%;
1080
+ }
1081
+ .ss-dash-sparkline-line {
1082
+ fill: none;
1083
+ stroke: var(--ss-accent);
1084
+ stroke-width: 1.5;
1085
+ }
1086
+ .ss-dash-sparkline-area {
1087
+ fill: var(--ss-accent);
1088
+ opacity: 0.1;
1089
+ }
1090
+
1091
+ /* ── Chart container ───────────────────────────────────────────── */
1092
+ .ss-dash-chart-container {
1093
+ background: var(--ss-surface);
1094
+ border: 1px solid var(--ss-border);
1095
+ border-radius: 6px;
1096
+ padding: 16px;
1097
+ margin-bottom: 16px;
1098
+ }
1099
+
1100
+ .ss-dash-chart-header {
1101
+ display: flex;
1102
+ align-items: center;
1103
+ justify-content: space-between;
1104
+ margin-bottom: 12px;
1105
+ }
1106
+
1107
+ .ss-dash-chart-title {
1108
+ font-size: 11px;
1109
+ font-weight: 600;
1110
+ color: var(--ss-text);
1111
+ text-transform: uppercase;
1112
+ letter-spacing: 0.04em;
1113
+ }
1114
+
1115
+ .ss-dash-chart {
1116
+ width: 100%;
1117
+ height: 220px;
1118
+ position: relative;
1119
+ }
1120
+ .ss-dash-chart svg {
1121
+ width: 100%;
1122
+ height: 100%;
1123
+ }
1124
+ .ss-dash-chart-svg .ss-dash-chart-dot {
1125
+ transition: r 0.15s ease, opacity 0.15s ease;
1126
+ }
1127
+ .ss-dash-chart-svg .ss-dash-chart-hover-zone {
1128
+ cursor: crosshair;
1129
+ }
1130
+
1131
+ .ss-dash-chart-tooltip {
1132
+ position: absolute;
1133
+ padding: 8px 12px;
1134
+ background: var(--ss-surface);
1135
+ border: 1px solid var(--ss-border);
1136
+ border-radius: 6px;
1137
+ font-size: 11px;
1138
+ line-height: 1.5;
1139
+ color: var(--ss-text);
1140
+ pointer-events: none;
1141
+ z-index: 5;
1142
+ box-shadow: 0 4px 12px var(--ss-shadow);
1143
+ white-space: nowrap;
1144
+ }
1145
+
1146
+ .ss-dash-chart-legend {
1147
+ display: flex;
1148
+ gap: 16px;
1149
+ justify-content: center;
1150
+ padding: 8px 0 0;
1151
+ font-size: 10px;
1152
+ color: var(--ss-muted);
1153
+ }
1154
+ .ss-dash-chart-legend-item {
1155
+ display: inline-flex;
1156
+ align-items: center;
1157
+ gap: 5px;
1158
+ }
1159
+ .ss-dash-legend-dot {
1160
+ display: inline-block;
1161
+ width: 8px;
1162
+ height: 8px;
1163
+ border-radius: 50%;
1164
+ }
1165
+
1166
+ /* ── Secondary cards ───────────────────────────────────────────── */
1167
+ .ss-dash-secondary-cards {
1168
+ display: grid;
1169
+ grid-template-columns: repeat(3, 1fr);
1170
+ gap: 12px;
1171
+ }
1172
+
1173
+ .ss-dash-secondary-card {
1174
+ background: var(--ss-surface);
1175
+ border: 1px solid var(--ss-border);
1176
+ border-radius: 6px;
1177
+ padding: 14px 16px;
1178
+ min-width: 0;
1179
+ }
1180
+
1181
+ .ss-dash-secondary-card-title {
1182
+ font-size: 10px;
1183
+ text-transform: uppercase;
1184
+ letter-spacing: 0.05em;
1185
+ color: var(--ss-muted);
1186
+ font-weight: 600;
1187
+ margin-bottom: 8px;
1188
+ }
1189
+
1190
+ .ss-dash-secondary-list {
1191
+ list-style: none;
1192
+ }
1193
+ .ss-dash-secondary-list li {
1194
+ display: flex;
1195
+ justify-content: space-between;
1196
+ gap: 12px;
1197
+ padding: 3px 0;
1198
+ font-size: 11px;
1199
+ color: var(--ss-text);
1200
+ border-bottom: 1px solid var(--ss-border-faint);
1201
+ min-width: 0;
1202
+ }
1203
+ .ss-dash-secondary-list li > span:first-child {
1204
+ overflow: hidden;
1205
+ text-overflow: ellipsis;
1206
+ white-space: nowrap;
1207
+ min-width: 0;
1208
+ }
1209
+ .ss-dash-secondary-list li:last-child { border-bottom: none; }
1210
+ .ss-dash-secondary-list-value {
1211
+ color: var(--ss-text-secondary);
1212
+ font-variant-numeric: tabular-nums;
1213
+ flex-shrink: 0;
1214
+ white-space: nowrap;
1215
+ }
1216
+
1217
+ /* ── Pagination ────────────────────────────────────────────────── */
1218
+ .ss-dash-pagination {
1219
+ display: flex;
1220
+ align-items: center;
1221
+ justify-content: center;
1222
+ gap: 4px;
1223
+ padding: 8px 16px;
1224
+ border-top: 1px solid var(--ss-border-dim);
1225
+ background: var(--ss-surface-alt);
1226
+ flex-shrink: 0;
1227
+ }
1228
+
1229
+ .ss-dash-page-btn {
1230
+ padding: 3px 10px;
1231
+ font-size: 10px;
1232
+ font-family: inherit;
1233
+ color: var(--ss-muted);
1234
+ background: none;
1235
+ border: 1px solid var(--ss-border);
1236
+ border-radius: 4px;
1237
+ cursor: pointer;
1238
+ }
1239
+ .ss-dash-page-btn:hover { color: var(--ss-text); border-color: var(--ss-dim); }
1240
+ .ss-dash-page-btn.ss-dash-active { color: var(--ss-accent); border-color: var(--ss-accent); }
1241
+ .ss-dash-page-btn:disabled { opacity: 0.3; cursor: default; }
1242
+
1243
+ .ss-dash-page-info {
1244
+ font-size: 10px;
1245
+ color: var(--ss-dim);
1246
+ padding: 0 8px;
1247
+ }
1248
+
1249
+ /* ── Config viewer ─────────────────────────────────────────────── */
1250
+ .ss-dash-config-table-wrap {
1251
+ flex: 1;
1252
+ overflow: auto;
1253
+ scrollbar-width: thin;
1254
+ scrollbar-color: var(--ss-border) transparent;
1255
+ }
1256
+
1257
+ .ss-dash-config-env-table { table-layout: fixed; }
1258
+ .ss-dash-env-key {
1259
+ width: 280px;
1260
+ min-width: 280px;
1261
+ white-space: nowrap;
1262
+ overflow: hidden;
1263
+ text-overflow: ellipsis;
1264
+ }
1265
+ .ss-dash-env-val {
1266
+ overflow: hidden;
1267
+ text-overflow: ellipsis;
1268
+ white-space: nowrap;
1269
+ max-width: 0;
1270
+ }
1271
+
1272
+ .ss-dash-config-key {
1273
+ color: var(--ss-sql-color);
1274
+ font-weight: 500;
1275
+ font-size: 11px;
1276
+ }
1277
+ .ss-dash-config-val {
1278
+ color: var(--ss-text-secondary);
1279
+ font-size: 11px;
1280
+ }
1281
+ .ss-dash-config-redacted {
1282
+ color: var(--ss-dim);
1283
+ font-style: italic;
1284
+ }
1285
+ .ss-dash-redacted-wrap {
1286
+ display: inline-flex;
1287
+ align-items: center;
1288
+ gap: 4px;
1289
+ font-style: italic;
1290
+ color: var(--ss-dim);
1291
+ }
1292
+ .ss-dash-redacted-real {
1293
+ font-style: normal;
1294
+ color: var(--ss-text-secondary);
1295
+ font-family: var(--ss-font-mono);
1296
+ font-size: 11px;
1297
+ word-break: break-all;
1298
+ }
1299
+ .ss-dash-redacted-reveal,
1300
+ .ss-dash-redacted-copy {
1301
+ background: none;
1302
+ border: 1px solid var(--ss-border-dim);
1303
+ border-radius: 3px;
1304
+ padding: 2px 4px;
1305
+ cursor: pointer;
1306
+ color: var(--ss-dim);
1307
+ display: inline-flex;
1308
+ align-items: center;
1309
+ line-height: 1;
1310
+ transition: color 0.15s, border-color 0.15s;
1311
+ }
1312
+ .ss-dash-redacted-reveal:hover,
1313
+ .ss-dash-redacted-copy:hover {
1314
+ color: var(--ss-text-primary);
1315
+ border-color: var(--ss-border);
1316
+ }
1317
+
1318
+ .ss-dash-config-sections {
1319
+ flex: 1;
1320
+ overflow: auto;
1321
+ scrollbar-width: thin;
1322
+ scrollbar-color: var(--ss-border) transparent;
1323
+ }
1324
+
1325
+ .ss-dash-config-section {
1326
+ border-bottom: 1px solid var(--ss-border-dim);
1327
+ }
1328
+
1329
+ .ss-dash-config-section-header {
1330
+ display: flex;
1331
+ align-items: center;
1332
+ gap: 8px;
1333
+ padding: 9px 16px;
1334
+ cursor: pointer;
1335
+ user-select: none;
1336
+ font-size: 12px;
1337
+ font-weight: 600;
1338
+ transition: background 0.1s;
1339
+ }
1340
+ .ss-dash-config-section-header:hover { background: var(--ss-hover); }
1341
+ .ss-dash-config-section-header.ss-dash-config-leaf {
1342
+ cursor: default;
1343
+ font-weight: 400;
1344
+ }
1345
+
1346
+ .ss-dash-config-toggle {
1347
+ color: var(--ss-muted);
1348
+ font-size: 10px;
1349
+ flex-shrink: 0;
1350
+ width: 12px;
1351
+ text-align: center;
1352
+ }
1353
+
1354
+ .ss-dash-config-count {
1355
+ margin-left: auto;
1356
+ font-size: 10px;
1357
+ color: var(--ss-dim);
1358
+ font-weight: 400;
1359
+ }
1360
+
1361
+ .ss-dash-config-section-body {
1362
+ padding: 0 0 4px 0;
1363
+ background: var(--ss-surface-alt);
1364
+ }
1365
+
1366
+ .ss-dash-config-inner-table {
1367
+ font-size: 11px;
1368
+ table-layout: fixed;
1369
+ }
1370
+ .ss-dash-config-inner-table th {
1371
+ background: var(--ss-surface-alt);
1372
+ }
1373
+ .ss-dash-config-inner-table td {
1374
+ overflow: hidden;
1375
+ text-overflow: ellipsis;
1376
+ white-space: nowrap;
1377
+ }
1378
+ .ss-dash-config-inner-table td:hover {
1379
+ white-space: normal;
1380
+ word-break: break-all;
1381
+ }
1382
+
1383
+ .ss-dash-config-match {
1384
+ background: var(--ss-amber-bg);
1385
+ color: var(--ss-amber-fg);
1386
+ border-radius: 2px;
1387
+ padding: 0 1px;
1388
+ }
1389
+
1390
+ .ss-dash-copy-row-btn {
1391
+ padding: 2px 6px;
1392
+ font-size: 12px;
1393
+ color: var(--ss-dim);
1394
+ background: none;
1395
+ border: 1px solid transparent;
1396
+ border-radius: 3px;
1397
+ cursor: pointer;
1398
+ font-family: inherit;
1399
+ line-height: 1;
1400
+ opacity: 0;
1401
+ transition: opacity 0.1s;
1402
+ }
1403
+ tr:hover .ss-dash-copy-row-btn { opacity: 1; }
1404
+ .ss-dash-copy-row-btn:hover { color: var(--ss-text); border-color: var(--ss-border); }
1405
+ .ss-dash-copy-row-btn.ss-dash-copy-row-ok { color: var(--ss-green-fg); opacity: 1; }
1406
+
1407
+ /* ── Cache ─────────────────────────────────────────────────────── */
1408
+ .ss-dash-cache-stats {
1409
+ display: flex;
1410
+ gap: 12px;
1411
+ padding: 12px 16px;
1412
+ border-bottom: 1px solid var(--ss-border-dim);
1413
+ flex-shrink: 0;
1414
+ }
1415
+
1416
+ .ss-dash-cache-stat {
1417
+ font-size: 11px;
1418
+ }
1419
+ .ss-dash-cache-stat-label {
1420
+ font-size: 10px;
1421
+ color: var(--ss-muted);
1422
+ text-transform: uppercase;
1423
+ margin-right: 4px;
1424
+ }
1425
+ .ss-dash-cache-stat-value {
1426
+ font-weight: 600;
1427
+ font-variant-numeric: tabular-nums;
1428
+ }
1429
+
1430
+ .ss-dash-cache-detail {
1431
+ padding: 12px 16px;
1432
+ background: var(--ss-surface-alt);
1433
+ border-top: 1px solid var(--ss-border-dim);
1434
+ }
1435
+
1436
+ /* ── Jobs ──────────────────────────────────────────────────────── */
1437
+ .ss-dash-job-stats {
1438
+ display: flex;
1439
+ gap: 12px;
1440
+ padding: 8px 16px;
1441
+ border-bottom: 1px solid var(--ss-border-dim);
1442
+ background: var(--ss-surface-alt);
1443
+ flex-shrink: 0;
1444
+ flex-wrap: wrap;
1445
+ align-items: center;
1446
+ }
1447
+
1448
+ .ss-dash-job-stat {
1449
+ font-size: 10px;
1450
+ display: flex;
1451
+ align-items: center;
1452
+ gap: 4px;
1453
+ }
1454
+ .ss-dash-job-stat-label {
1455
+ color: var(--ss-muted);
1456
+ text-transform: uppercase;
1457
+ }
1458
+ .ss-dash-job-stat-value {
1459
+ font-weight: 600;
1460
+ font-variant-numeric: tabular-nums;
1461
+ }
1462
+
1463
+ .ss-dash-retry-btn {
1464
+ padding: 2px 8px;
1465
+ font-size: 9px;
1466
+ font-family: inherit;
1467
+ color: var(--ss-amber-fg);
1468
+ background: var(--ss-amber-bg);
1469
+ border: none;
1470
+ border-radius: 3px;
1471
+ cursor: pointer;
1472
+ text-transform: uppercase;
1473
+ letter-spacing: 0.04em;
1474
+ font-weight: 600;
1475
+ }
1476
+ .ss-dash-retry-btn:hover { opacity: 0.8; }
1477
+
1478
+ /* ── Grouped queries toggle ────────────────────────────────────── */
1479
+ .ss-dash-grouped-header {
1480
+ display: flex;
1481
+ align-items: center;
1482
+ gap: 8px;
1483
+ }
1484
+
1485
+ /* ── Filterable cell ───────────────────────────────────────────── */
1486
+ .ss-dash-filterable { cursor: pointer; }
1487
+ .ss-dash-filterable:hover { background: var(--ss-hover-accent); }
1488
+
1489
+ /* ── Reqid input in log bar ────────────────────────────────────── */
1490
+ .ss-dash-reqid-input { max-width: 200px; margin-left: auto; }
1491
+ .ss-dash-reqid-clear { margin-left: 4px; }
1492
+
1493
+ /* ── Scrollable pane content ───────────────────────────────────── */
1494
+ .ss-dash-pane-inner {
1495
+ display: flex;
1496
+ flex-direction: column;
1497
+ height: 100%;
1498
+ position: relative;
1499
+ }
1500
+
1501
+ /* ── Detail view for list/detail pattern ───────────────────────── */
1502
+ .ss-dash-list-view { display: flex; flex-direction: column; height: 100%; }
1503
+ .ss-dash-detail-view { display: none; flex-direction: column; height: 100%; }
1504
+ .ss-dash-detail-view.ss-dash-active { display: flex; }