@klars/agentobs 0.1.0 → 0.1.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.
@@ -1,668 +1,961 @@
1
- /*
2
- * AgentObs dashboard styling.
3
- *
4
- * Colors come from a validated data-viz palette: the categorical slots and
5
- * status steps below passed the six-checks validator (lightness band, chroma
6
- * floor, CVD separation, normal-vision floor, contrast) against both the
7
- * light (#fcfcfb) and dark (#1a1a19) surfaces. Do not substitute hexes by eye
8
- * - re-run the validator if these change.
9
- *
10
- * Every color is defined on bare :root first, then redefined for dark under
11
- * both the OS media query and the explicit [data-theme] scope, so the toggle
12
- * wins in either direction.
13
- */
14
-
15
- :root {
16
- color-scheme: light;
17
-
18
- --page: #f9f9f7;
19
- --surface: #fcfcfb;
20
- --text-primary: #0b0b0b;
21
- --text-secondary: #52514e;
22
- --text-muted: #898781;
23
- --grid: #e1e0d9;
24
- --axis: #c3c2b7;
25
- --border: rgba(11, 11, 11, 0.1);
26
- --raised: rgba(11, 11, 11, 0.04);
27
-
28
- /* Categorical slots 1-3 (validated all-pairs in both modes). */
29
- --series-1: #2a78d6; /* calls */
30
- --series-2: #eb6834; /* secondary */
31
- --series-3: #1baf7a;
32
-
33
- /* Status palette - reserved, never reused as a series color. */
34
- --status-good: #0ca30c;
35
- --status-warning: #fab219;
36
- --status-serious: #ec835a;
37
- --status-critical: #d03b3b;
38
- --success-text: #006300;
39
-
40
- --radius: 10px;
41
- --radius-sm: 6px;
42
- --shadow: 0 1px 2px rgba(11, 11, 11, 0.05), 0 8px 24px -12px rgba(11, 11, 11, 0.12);
43
- --font: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
44
- "Helvetica Neue", Arial, sans-serif;
45
- --mono: ui-monospace, SFMono-Regular, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
46
- }
47
-
48
- @media (prefers-color-scheme: dark) {
49
- :root:not([data-theme="light"]) {
50
- color-scheme: dark;
51
- --page: #0d0d0d;
52
- --surface: #1a1a19;
53
- --text-primary: #ffffff;
54
- --text-secondary: #c3c2b7;
55
- --text-muted: #898781;
56
- --grid: #2c2c2a;
57
- --axis: #383835;
58
- --border: rgba(255, 255, 255, 0.1);
59
- --raised: rgba(255, 255, 255, 0.05);
60
- --series-1: #3987e5;
61
- --series-2: #d95926;
62
- --series-3: #199e70;
63
- --success-text: #0ca30c;
64
- --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.6);
65
- }
66
- }
67
-
68
- :root[data-theme="dark"] {
69
- color-scheme: dark;
70
- --page: #0d0d0d;
71
- --surface: #1a1a19;
72
- --text-primary: #ffffff;
73
- --text-secondary: #c3c2b7;
74
- --text-muted: #898781;
75
- --grid: #2c2c2a;
76
- --axis: #383835;
77
- --border: rgba(255, 255, 255, 0.1);
78
- --raised: rgba(255, 255, 255, 0.05);
79
- --series-1: #3987e5;
80
- --series-2: #d95926;
81
- --series-3: #199e70;
82
- --success-text: #0ca30c;
83
- --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.6);
84
- }
85
-
86
- *,
87
- *::before,
88
- *::after {
89
- box-sizing: border-box;
90
- }
91
-
92
- html,
93
- body {
94
- margin: 0;
95
- padding: 0;
96
- }
97
-
98
- body {
99
- background: var(--page);
100
- color: var(--text-primary);
101
- font-family: var(--font);
102
- font-size: 14px;
103
- line-height: 1.5;
104
- -webkit-font-smoothing: antialiased;
105
- }
106
-
107
- .sr-only {
108
- position: absolute;
109
- width: 1px;
110
- height: 1px;
111
- padding: 0;
112
- margin: -1px;
113
- overflow: hidden;
114
- clip: rect(0 0 0 0);
115
- white-space: nowrap;
116
- border: 0;
117
- }
118
-
119
- .skip-link {
120
- position: absolute;
121
- left: -9999px;
122
- top: 0;
123
- background: var(--surface);
124
- color: var(--text-primary);
125
- padding: 10px 16px;
126
- z-index: 10;
127
- border-radius: var(--radius-sm);
128
- }
129
- .skip-link:focus {
130
- left: 12px;
131
- top: 12px;
132
- }
133
-
134
- /* ---------- Top bar ---------- */
135
-
136
- .topbar {
137
- display: flex;
138
- align-items: center;
139
- justify-content: space-between;
140
- gap: 16px;
141
- padding: 16px 24px;
142
- background: var(--surface);
143
- border-bottom: 1px solid var(--border);
144
- position: sticky;
145
- top: 0;
146
- z-index: 5;
147
- flex-wrap: wrap;
148
- }
149
-
150
- .brand {
151
- display: flex;
152
- align-items: center;
153
- gap: 12px;
154
- }
155
-
156
- .brand-mark {
157
- width: 30px;
158
- height: 30px;
159
- border-radius: 8px;
160
- background: linear-gradient(135deg, var(--series-1), var(--series-3));
161
- flex: none;
162
- }
163
-
164
- .brand h1 {
165
- margin: 0;
166
- font-size: 15px;
167
- font-weight: 650;
168
- letter-spacing: -0.01em;
169
- }
170
-
171
- .brand-sub {
172
- margin: 0;
173
- font-size: 12px;
174
- color: var(--text-muted);
175
- }
176
-
177
- .topbar-actions {
178
- display: flex;
179
- align-items: center;
180
- gap: 10px;
181
- }
182
-
183
- .rangeset,
184
- .filterset {
185
- display: inline-flex;
186
- background: var(--raised);
187
- border: 1px solid var(--border);
188
- border-radius: var(--radius-sm);
189
- padding: 2px;
190
- gap: 2px;
191
- }
192
-
193
- .rangeset button,
194
- .filterset button {
195
- appearance: none;
196
- border: 0;
197
- background: transparent;
198
- color: var(--text-secondary);
199
- font: inherit;
200
- font-size: 13px;
201
- padding: 5px 12px;
202
- border-radius: 4px;
203
- cursor: pointer;
204
- min-height: 30px;
205
- }
206
-
207
- .rangeset button:hover,
208
- .filterset button:hover {
209
- color: var(--text-primary);
210
- }
211
-
212
- .rangeset button[aria-pressed="true"],
213
- .filterset button[aria-pressed="true"] {
214
- background: var(--surface);
215
- color: var(--text-primary);
216
- font-weight: 600;
217
- box-shadow: 0 1px 2px rgba(11, 11, 11, 0.08);
218
- }
219
-
220
- .icon-btn {
221
- appearance: none;
222
- width: 34px;
223
- height: 34px;
224
- border-radius: var(--radius-sm);
225
- border: 1px solid var(--border);
226
- background: var(--raised);
227
- color: var(--text-secondary);
228
- cursor: pointer;
229
- font-size: 15px;
230
- line-height: 1;
231
- }
232
- .icon-btn:hover {
233
- color: var(--text-primary);
234
- }
235
-
236
- :focus-visible {
237
- outline: 2px solid var(--series-1);
238
- outline-offset: 2px;
239
- }
240
-
241
- /* ---------- Layout ---------- */
242
-
243
- main {
244
- max-width: 1240px;
245
- margin: 0 auto;
246
- padding: 24px;
247
- display: grid;
248
- gap: 20px;
249
- }
250
-
251
- .panel {
252
- background: var(--surface);
253
- border: 1px solid var(--border);
254
- border-radius: var(--radius);
255
- box-shadow: var(--shadow);
256
- overflow: hidden;
257
- }
258
-
259
- .panel-head {
260
- display: flex;
261
- align-items: flex-start;
262
- justify-content: space-between;
263
- gap: 16px;
264
- padding: 16px 18px;
265
- border-bottom: 1px solid var(--border);
266
- flex-wrap: wrap;
267
- }
268
-
269
- .panel-head h2 {
270
- margin: 0;
271
- font-size: 14px;
272
- font-weight: 650;
273
- }
274
-
275
- .panel-sub {
276
- margin: 2px 0 0;
277
- font-size: 12px;
278
- color: var(--text-muted);
279
- }
280
-
281
- .split {
282
- display: grid;
283
- grid-template-columns: 1fr 1fr;
284
- gap: 20px;
285
- /* Start-align so a short table doesn't stretch to match a tall neighbour,
286
- leaving a block of dead whitespace under its last row. */
287
- align-items: start;
288
- }
289
-
290
- @media (max-width: 900px) {
291
- .split {
292
- grid-template-columns: 1fr;
293
- }
294
- }
295
-
296
- /* ---------- Hero ---------- */
297
-
298
- .hero {
299
- background: var(--surface);
300
- border: 1px solid var(--border);
301
- border-radius: var(--radius);
302
- box-shadow: var(--shadow);
303
- padding: 22px 24px;
304
- display: flex;
305
- align-items: center;
306
- justify-content: space-between;
307
- gap: 24px;
308
- flex-wrap: wrap;
309
- }
310
-
311
- .hero-label {
312
- margin: 0;
313
- font-size: 12px;
314
- text-transform: uppercase;
315
- letter-spacing: 0.06em;
316
- color: var(--text-muted);
317
- font-weight: 600;
318
- }
319
-
320
- /* Proportional figures: tabular-nums makes a large value look loose. */
321
- .hero-figure {
322
- margin: 4px 0 0;
323
- font-size: 48px;
324
- line-height: 1.05;
325
- font-weight: 680;
326
- letter-spacing: -0.02em;
327
- }
328
-
329
- .hero-note {
330
- margin: 6px 0 0;
331
- font-size: 12px;
332
- color: var(--text-muted);
333
- }
334
-
335
- .hero-side {
336
- display: flex;
337
- gap: 28px;
338
- margin: 0;
339
- flex-wrap: wrap;
340
- }
341
-
342
- .hero-side div {
343
- min-width: 88px;
344
- }
345
-
346
- .hero-side dt {
347
- font-size: 11px;
348
- text-transform: uppercase;
349
- letter-spacing: 0.05em;
350
- color: var(--text-muted);
351
- font-weight: 600;
352
- }
353
-
354
- .hero-side dd {
355
- margin: 2px 0 0;
356
- font-size: 18px;
357
- font-weight: 600;
358
- font-variant-numeric: tabular-nums;
359
- }
360
-
361
- /* ---------- Stat tiles ---------- */
362
-
363
- .tiles {
364
- display: grid;
365
- grid-template-columns: repeat(4, 1fr);
366
- gap: 16px;
367
- }
368
-
369
- @media (max-width: 900px) {
370
- .tiles {
371
- grid-template-columns: repeat(2, 1fr);
372
- }
373
- }
374
-
375
- .tile {
376
- background: var(--surface);
377
- border: 1px solid var(--border);
378
- border-radius: var(--radius);
379
- padding: 16px 18px;
380
- box-shadow: var(--shadow);
381
- }
382
-
383
- .tile-label {
384
- margin: 0;
385
- font-size: 12px;
386
- color: var(--text-muted);
387
- font-weight: 600;
388
- text-transform: uppercase;
389
- letter-spacing: 0.05em;
390
- }
391
-
392
- .tile-value {
393
- margin: 6px 0 0;
394
- font-size: 28px;
395
- font-weight: 660;
396
- letter-spacing: -0.015em;
397
- }
398
-
399
- .tile-sub {
400
- margin: 2px 0 0;
401
- font-size: 12px;
402
- color: var(--text-muted);
403
- }
404
-
405
- /* ---------- Chart ---------- */
406
-
407
- .chart-wrap {
408
- position: relative;
409
- padding: 16px 18px 8px;
410
- }
411
-
412
- #timeline {
413
- width: 100%;
414
- display: block;
415
- }
416
-
417
- .legend {
418
- display: flex;
419
- gap: 14px;
420
- align-items: center;
421
- font-size: 12px;
422
- color: var(--text-secondary);
423
- }
424
-
425
- .legend-item {
426
- display: inline-flex;
427
- align-items: center;
428
- gap: 6px;
429
- }
430
-
431
- .swatch {
432
- width: 10px;
433
- height: 10px;
434
- border-radius: 3px;
435
- display: inline-block;
436
- }
437
-
438
- .swatch-calls {
439
- background: var(--series-1);
440
- }
441
-
442
- /* Errors use the reserved critical status step, never a categorical slot. */
443
- .swatch-errors {
444
- background: var(--status-critical);
445
- }
446
-
447
- .tooltip {
448
- position: absolute;
449
- pointer-events: none;
450
- background: var(--text-primary);
451
- color: var(--surface);
452
- padding: 7px 10px;
453
- border-radius: var(--radius-sm);
454
- font-size: 12px;
455
- line-height: 1.45;
456
- white-space: nowrap;
457
- opacity: 0;
458
- transition: opacity 0.12s ease;
459
- z-index: 4;
460
- font-variant-numeric: tabular-nums;
461
- }
462
-
463
- .tooltip.is-visible {
464
- opacity: 1;
465
- }
466
-
467
- .panel-note {
468
- margin: 0;
469
- padding: 0 18px 14px;
470
- }
471
-
472
- .linklike {
473
- appearance: none;
474
- background: none;
475
- border: 0;
476
- padding: 0;
477
- color: var(--text-secondary);
478
- font: inherit;
479
- font-size: 12px;
480
- text-decoration: underline;
481
- cursor: pointer;
482
- }
483
- .linklike:hover {
484
- color: var(--text-primary);
485
- }
486
-
487
- /* ---------- Tables ---------- */
488
-
489
- .table-wrap {
490
- overflow-x: auto;
491
- }
492
-
493
- .table-wrap.is-hidden {
494
- display: none;
495
- }
496
-
497
- table {
498
- width: 100%;
499
- border-collapse: collapse;
500
- font-size: 13px;
501
- }
502
-
503
- thead th {
504
- text-align: left;
505
- font-size: 11px;
506
- text-transform: uppercase;
507
- letter-spacing: 0.05em;
508
- color: var(--text-muted);
509
- font-weight: 600;
510
- padding: 10px 14px;
511
- border-bottom: 1px solid var(--border);
512
- white-space: nowrap;
513
- background: var(--surface);
514
- }
515
-
516
- tbody td {
517
- padding: 10px 14px;
518
- border-bottom: 1px solid var(--grid);
519
- vertical-align: top;
520
- }
521
-
522
- tbody tr:last-child td {
523
- border-bottom: 0;
524
- }
525
-
526
- tbody tr:hover td {
527
- background: var(--raised);
528
- }
529
-
530
- .num {
531
- text-align: right;
532
- font-variant-numeric: tabular-nums;
533
- }
534
-
535
- td.empty {
536
- color: var(--text-muted);
537
- text-align: center;
538
- padding: 28px 14px;
539
- }
540
-
541
- .mono {
542
- font-family: var(--mono);
543
- font-size: 12px;
544
- }
545
-
546
- .truncate {
547
- max-width: 420px;
548
- overflow: hidden;
549
- text-overflow: ellipsis;
550
- white-space: nowrap;
551
- display: block;
552
- }
553
-
554
- /* ---------- Status pills ---------- */
555
-
556
- /* Icon + label pairing, never color alone: on the light surface several
557
- status steps sit below 3:1, and this is the documented mitigation. */
558
- .pill {
559
- display: inline-flex;
560
- align-items: center;
561
- gap: 5px;
562
- font-size: 12px;
563
- font-weight: 600;
564
- padding: 2px 8px;
565
- border-radius: 999px;
566
- border: 1px solid transparent;
567
- white-space: nowrap;
568
- }
569
-
570
- .pill::before {
571
- font-size: 10px;
572
- line-height: 1;
573
- }
574
-
575
- .pill-success {
576
- color: var(--success-text);
577
- background: color-mix(in srgb, var(--status-good) 12%, transparent);
578
- border-color: color-mix(in srgb, var(--status-good) 34%, transparent);
579
- }
580
- .pill-success::before {
581
- content: "\2713";
582
- }
583
-
584
- .pill-error {
585
- color: var(--status-critical);
586
- background: color-mix(in srgb, var(--status-critical) 12%, transparent);
587
- border-color: color-mix(in srgb, var(--status-critical) 34%, transparent);
588
- }
589
- .pill-error::before {
590
- content: "\2717";
591
- }
592
-
593
- .pill-blocked {
594
- color: var(--status-serious);
595
- background: color-mix(in srgb, var(--status-serious) 14%, transparent);
596
- border-color: color-mix(in srgb, var(--status-serious) 38%, transparent);
597
- }
598
- .pill-blocked::before {
599
- content: "\26D4";
600
- }
601
-
602
- .pill-pending {
603
- color: var(--text-secondary);
604
- background: var(--raised);
605
- border-color: var(--border);
606
- }
607
- .pill-pending::before {
608
- content: "\25CB";
609
- }
610
-
611
- .badge {
612
- display: inline-block;
613
- font-size: 11px;
614
- padding: 1px 6px;
615
- border-radius: 4px;
616
- background: var(--raised);
617
- border: 1px solid var(--border);
618
- color: var(--text-secondary);
619
- margin-left: 6px;
620
- }
621
-
622
- /* ---------- Footer ---------- */
623
-
624
- .footer {
625
- max-width: 1240px;
626
- margin: 0 auto;
627
- padding: 8px 24px 32px;
628
- display: flex;
629
- justify-content: space-between;
630
- gap: 16px;
631
- font-size: 12px;
632
- color: var(--text-muted);
633
- flex-wrap: wrap;
634
- }
635
-
636
- .footer code {
637
- font-family: var(--mono);
638
- font-size: 11px;
639
- }
640
-
641
- .conn {
642
- display: inline-flex;
643
- align-items: center;
644
- gap: 6px;
645
- }
646
-
647
- .conn::before {
648
- content: "";
649
- width: 7px;
650
- height: 7px;
651
- border-radius: 50%;
652
- background: var(--text-muted);
653
- }
654
-
655
- .conn.is-live::before {
656
- background: var(--status-good);
657
- }
658
-
659
- .conn.is-down::before {
660
- background: var(--status-critical);
661
- }
662
-
663
- @media (prefers-reduced-motion: reduce) {
664
- * {
665
- transition-duration: 0.01ms !important;
666
- animation-duration: 0.01ms !important;
667
- }
668
- }
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
2
+
3
+ /*
4
+ * AgentObs dashboard styling.
5
+ *
6
+ * Colors come from a validated data-viz palette: the categorical slots and
7
+ * status steps below passed the six-checks validator (lightness band, chroma
8
+ * floor, CVD separation, normal-vision floor, contrast) against both the
9
+ * light (#fcfcfb) and dark (#1a1a19) surfaces. Do not substitute hexes by eye
10
+ * - re-run the validator if these change.
11
+ *
12
+ * Every color is defined on bare :root first, then redefined for dark under
13
+ * both the OS media query and the explicit [data-theme] scope, so the toggle
14
+ * wins in either direction.
15
+ */
16
+
17
+ :root {
18
+ color-scheme: light;
19
+
20
+ --page: #f9f9f7;
21
+ --surface: #fcfcfb;
22
+ --text-primary: #0b0b0b;
23
+ --text-secondary: #52514e;
24
+ --text-muted: #898781;
25
+ --grid: #e1e0d9;
26
+ --axis: #c3c2b7;
27
+ --border: rgba(11, 11, 11, 0.1);
28
+ --raised: rgba(11, 11, 11, 0.04);
29
+
30
+ /* Categorical slots 1-3 (validated all-pairs in both modes). */
31
+ --series-1: #2a78d6; /* calls */
32
+ --series-2: #eb6834; /* secondary */
33
+ --series-3: #1baf7a;
34
+
35
+ /* Status palette - reserved, never reused as a series color. */
36
+ --status-good: #0ca30c;
37
+ --status-warning: #fab219;
38
+ --status-serious: #ec835a;
39
+ --status-critical: #d03b3b;
40
+ --success-text: #006300;
41
+
42
+ --radius: 10px;
43
+ --radius-sm: 6px;
44
+ --shadow: 0 1px 2px rgba(11, 11, 11, 0.05), 0 8px 24px -12px rgba(11, 11, 11, 0.12);
45
+ --font: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
46
+ 'Helvetica Neue', Arial, sans-serif;
47
+ --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
48
+ }
49
+
50
+ @media (prefers-color-scheme: dark) {
51
+ :root:not([data-theme="light"]) {
52
+ color-scheme: dark;
53
+ --page: #0d0d0d;
54
+ --surface: #1a1a19;
55
+ --text-primary: #ffffff;
56
+ --text-secondary: #c3c2b7;
57
+ --text-muted: #898781;
58
+ --grid: #2c2c2a;
59
+ --axis: #383835;
60
+ --border: rgba(255, 255, 255, 0.1);
61
+ --raised: rgba(255, 255, 255, 0.05);
62
+ --series-1: #3987e5;
63
+ --series-2: #d95926;
64
+ --series-3: #199e70;
65
+ --success-text: #0ca30c;
66
+ --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.6);
67
+ }
68
+ }
69
+
70
+ :root[data-theme="dark"] {
71
+ color-scheme: dark;
72
+ --page: #0d0d0d;
73
+ --surface: #1a1a19;
74
+ --text-primary: #ffffff;
75
+ --text-secondary: #c3c2b7;
76
+ --text-muted: #898781;
77
+ --grid: #2c2c2a;
78
+ --axis: #383835;
79
+ --border: rgba(255, 255, 255, 0.1);
80
+ --raised: rgba(255, 255, 255, 0.05);
81
+ --series-1: #3987e5;
82
+ --series-2: #d95926;
83
+ --series-3: #199e70;
84
+ --success-text: #0ca30c;
85
+ --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.6);
86
+ }
87
+
88
+ *,
89
+ *::before,
90
+ *::after {
91
+ box-sizing: border-box;
92
+ }
93
+
94
+ html,
95
+ body {
96
+ margin: 0;
97
+ padding: 0;
98
+ }
99
+
100
+ body {
101
+ background: var(--page);
102
+ color: var(--text-primary);
103
+ font-family: var(--font);
104
+ font-size: 14px;
105
+ line-height: 1.5;
106
+ -webkit-font-smoothing: antialiased;
107
+ }
108
+
109
+ .sr-only {
110
+ position: absolute;
111
+ width: 1px;
112
+ height: 1px;
113
+ padding: 0;
114
+ margin: -1px;
115
+ overflow: hidden;
116
+ clip: rect(0 0 0 0);
117
+ white-space: nowrap;
118
+ border: 0;
119
+ }
120
+
121
+ .skip-link {
122
+ position: absolute;
123
+ left: -9999px;
124
+ top: 0;
125
+ background: var(--surface);
126
+ color: var(--text-primary);
127
+ padding: 10px 16px;
128
+ z-index: 10;
129
+ border-radius: var(--radius-sm);
130
+ }
131
+ .skip-link:focus {
132
+ left: 12px;
133
+ top: 12px;
134
+ }
135
+
136
+ /* ---------- Top bar ---------- */
137
+
138
+ .topbar {
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: space-between;
142
+ gap: 16px;
143
+ padding: 16px 24px;
144
+ background: var(--surface);
145
+ border-bottom: 1px solid var(--border);
146
+ position: sticky;
147
+ top: 0;
148
+ z-index: 5;
149
+ flex-wrap: wrap;
150
+ }
151
+
152
+ .brand {
153
+ display: flex;
154
+ align-items: center;
155
+ gap: 12px;
156
+ }
157
+
158
+ .brand-mark {
159
+ width: 30px;
160
+ height: 30px;
161
+ border-radius: 8px;
162
+ background: linear-gradient(135deg, var(--series-1), var(--series-3));
163
+ flex: none;
164
+ }
165
+
166
+ .brand h1 {
167
+ margin: 0;
168
+ font-size: 15px;
169
+ font-weight: 650;
170
+ letter-spacing: -0.01em;
171
+ }
172
+
173
+ .brand-sub {
174
+ margin: 0;
175
+ font-size: 12px;
176
+ color: var(--text-muted);
177
+ }
178
+
179
+ .topbar-actions {
180
+ display: flex;
181
+ align-items: center;
182
+ gap: 10px;
183
+ }
184
+
185
+ .rangeset,
186
+ .filterset {
187
+ display: inline-flex;
188
+ background: var(--raised);
189
+ border: 1px solid var(--border);
190
+ border-radius: var(--radius-sm);
191
+ padding: 2px;
192
+ gap: 2px;
193
+ }
194
+
195
+ .rangeset button,
196
+ .filterset button {
197
+ appearance: none;
198
+ border: 0;
199
+ background: transparent;
200
+ color: var(--text-secondary);
201
+ font: inherit;
202
+ font-size: 13px;
203
+ padding: 5px 12px;
204
+ border-radius: 4px;
205
+ cursor: pointer;
206
+ min-height: 30px;
207
+ }
208
+
209
+ .rangeset button:hover,
210
+ .filterset button:hover {
211
+ color: var(--text-primary);
212
+ }
213
+
214
+ .rangeset button[aria-pressed="true"],
215
+ .filterset button[aria-pressed="true"] {
216
+ background: var(--surface);
217
+ color: var(--text-primary);
218
+ font-weight: 600;
219
+ box-shadow: 0 1px 2px rgba(11, 11, 11, 0.08);
220
+ }
221
+
222
+ .icon-btn {
223
+ appearance: none;
224
+ width: 34px;
225
+ height: 34px;
226
+ border-radius: var(--radius-sm);
227
+ border: 1px solid var(--border);
228
+ background: var(--raised);
229
+ color: var(--text-secondary);
230
+ cursor: pointer;
231
+ font-size: 15px;
232
+ line-height: 1;
233
+ }
234
+ .icon-btn:hover {
235
+ color: var(--text-primary);
236
+ }
237
+
238
+ :focus-visible {
239
+ outline: 2px solid var(--series-1);
240
+ outline-offset: 2px;
241
+ }
242
+
243
+ /* ---------- Layout ---------- */
244
+
245
+ main {
246
+ max-width: 1240px;
247
+ margin: 0 auto;
248
+ padding: 24px;
249
+ display: grid;
250
+ gap: 20px;
251
+ }
252
+
253
+ .panel {
254
+ background: var(--surface);
255
+ border: 1px solid var(--border);
256
+ border-radius: var(--radius);
257
+ box-shadow: var(--shadow);
258
+ overflow: hidden;
259
+ }
260
+
261
+ .panel-head {
262
+ display: flex;
263
+ align-items: flex-start;
264
+ justify-content: space-between;
265
+ gap: 16px;
266
+ padding: 16px 18px;
267
+ border-bottom: 1px solid var(--border);
268
+ flex-wrap: wrap;
269
+ }
270
+
271
+ .panel-head h2 {
272
+ margin: 0;
273
+ font-size: 14px;
274
+ font-weight: 650;
275
+ }
276
+
277
+ .panel-sub {
278
+ margin: 2px 0 0;
279
+ font-size: 12px;
280
+ color: var(--text-muted);
281
+ }
282
+
283
+ .split {
284
+ display: grid;
285
+ grid-template-columns: 1fr 1fr;
286
+ gap: 20px;
287
+ /* Start-align so a short table doesn't stretch to match a tall neighbour,
288
+ leaving a block of dead whitespace under its last row. */
289
+ align-items: start;
290
+ }
291
+
292
+ @media (max-width: 900px) {
293
+ .split {
294
+ grid-template-columns: 1fr;
295
+ }
296
+ }
297
+
298
+ /* ---------- Hero ---------- */
299
+
300
+ .hero {
301
+ background: var(--surface);
302
+ border: 1px solid var(--border);
303
+ border-radius: var(--radius);
304
+ box-shadow: var(--shadow);
305
+ padding: 22px 24px;
306
+ display: flex;
307
+ align-items: center;
308
+ justify-content: space-between;
309
+ gap: 24px;
310
+ flex-wrap: wrap;
311
+ }
312
+
313
+ .hero-label {
314
+ margin: 0;
315
+ font-size: 12px;
316
+ text-transform: uppercase;
317
+ letter-spacing: 0.06em;
318
+ color: var(--text-muted);
319
+ font-weight: 600;
320
+ }
321
+
322
+ /* Proportional figures: tabular-nums makes a large value look loose. */
323
+ .hero-figure {
324
+ margin: 4px 0 0;
325
+ font-size: 48px;
326
+ line-height: 1.05;
327
+ font-weight: 680;
328
+ letter-spacing: -0.02em;
329
+ }
330
+
331
+ .hero-note {
332
+ margin: 6px 0 0;
333
+ font-size: 12px;
334
+ color: var(--text-muted);
335
+ }
336
+
337
+ .hero-side {
338
+ display: flex;
339
+ gap: 28px;
340
+ margin: 0;
341
+ flex-wrap: wrap;
342
+ }
343
+
344
+ .hero-side div {
345
+ min-width: 88px;
346
+ }
347
+
348
+ .hero-side dt {
349
+ font-size: 11px;
350
+ text-transform: uppercase;
351
+ letter-spacing: 0.05em;
352
+ color: var(--text-muted);
353
+ font-weight: 600;
354
+ }
355
+
356
+ .hero-side dd {
357
+ margin: 2px 0 0;
358
+ font-size: 18px;
359
+ font-weight: 600;
360
+ font-variant-numeric: tabular-nums;
361
+ }
362
+
363
+ /* ---------- Stat tiles ---------- */
364
+
365
+ .tiles {
366
+ display: grid;
367
+ grid-template-columns: repeat(4, 1fr);
368
+ gap: 16px;
369
+ }
370
+
371
+ @media (max-width: 900px) {
372
+ .tiles {
373
+ grid-template-columns: repeat(2, 1fr);
374
+ }
375
+ }
376
+
377
+ .tile {
378
+ background: var(--surface);
379
+ border: 1px solid var(--border);
380
+ border-radius: var(--radius);
381
+ padding: 16px 18px;
382
+ box-shadow: var(--shadow);
383
+ }
384
+
385
+ .tile-label {
386
+ margin: 0;
387
+ font-size: 12px;
388
+ color: var(--text-muted);
389
+ font-weight: 600;
390
+ text-transform: uppercase;
391
+ letter-spacing: 0.05em;
392
+ }
393
+
394
+ .tile-value {
395
+ margin: 6px 0 0;
396
+ font-size: 28px;
397
+ font-weight: 660;
398
+ letter-spacing: -0.015em;
399
+ }
400
+
401
+ .tile-sub {
402
+ margin: 2px 0 0;
403
+ font-size: 12px;
404
+ color: var(--text-muted);
405
+ }
406
+
407
+ /* ---------- Chart ---------- */
408
+
409
+ .chart-wrap {
410
+ position: relative;
411
+ padding: 16px 18px 8px;
412
+ }
413
+
414
+ #timeline {
415
+ width: 100%;
416
+ display: block;
417
+ }
418
+
419
+ .legend {
420
+ display: flex;
421
+ gap: 14px;
422
+ align-items: center;
423
+ font-size: 12px;
424
+ color: var(--text-secondary);
425
+ }
426
+
427
+ .legend-item {
428
+ display: inline-flex;
429
+ align-items: center;
430
+ gap: 6px;
431
+ }
432
+
433
+ .swatch {
434
+ width: 10px;
435
+ height: 10px;
436
+ border-radius: 3px;
437
+ display: inline-block;
438
+ }
439
+
440
+ .swatch-calls {
441
+ background: var(--series-1);
442
+ }
443
+
444
+ /* Errors use the reserved critical status step, never a categorical slot. */
445
+ .swatch-errors {
446
+ background: var(--status-critical);
447
+ }
448
+
449
+ .tooltip {
450
+ position: absolute;
451
+ pointer-events: none;
452
+ background: var(--text-primary);
453
+ color: var(--surface);
454
+ padding: 7px 10px;
455
+ border-radius: var(--radius-sm);
456
+ font-size: 12px;
457
+ line-height: 1.45;
458
+ white-space: nowrap;
459
+ opacity: 0;
460
+ transition: opacity 0.12s ease;
461
+ z-index: 4;
462
+ font-variant-numeric: tabular-nums;
463
+ }
464
+
465
+ .tooltip.is-visible {
466
+ opacity: 1;
467
+ }
468
+
469
+ .panel-note {
470
+ margin: 0;
471
+ padding: 0 18px 14px;
472
+ }
473
+
474
+ .linklike {
475
+ appearance: none;
476
+ background: none;
477
+ border: 0;
478
+ padding: 0;
479
+ color: var(--text-secondary);
480
+ font: inherit;
481
+ font-size: 12px;
482
+ text-decoration: underline;
483
+ cursor: pointer;
484
+ }
485
+ .linklike:hover {
486
+ color: var(--text-primary);
487
+ }
488
+
489
+ /* ---------- Tables ---------- */
490
+
491
+ .table-wrap {
492
+ overflow-x: auto;
493
+ }
494
+
495
+ .table-wrap.is-hidden {
496
+ display: none;
497
+ }
498
+
499
+ table {
500
+ width: 100%;
501
+ border-collapse: collapse;
502
+ font-size: 13px;
503
+ }
504
+
505
+ thead th {
506
+ text-align: left;
507
+ font-size: 11px;
508
+ text-transform: uppercase;
509
+ letter-spacing: 0.05em;
510
+ color: var(--text-muted);
511
+ font-weight: 600;
512
+ padding: 10px 14px;
513
+ border-bottom: 1px solid var(--border);
514
+ white-space: nowrap;
515
+ background: var(--surface);
516
+ }
517
+
518
+ tbody td {
519
+ padding: 10px 14px;
520
+ border-bottom: 1px solid var(--grid);
521
+ vertical-align: top;
522
+ }
523
+
524
+ tbody tr:last-child td {
525
+ border-bottom: 0;
526
+ }
527
+
528
+ tbody tr:hover td {
529
+ background: var(--raised);
530
+ }
531
+
532
+ .num {
533
+ text-align: right;
534
+ font-variant-numeric: tabular-nums;
535
+ }
536
+
537
+ td.empty {
538
+ color: var(--text-muted);
539
+ text-align: center;
540
+ padding: 28px 14px;
541
+ }
542
+
543
+ .mono {
544
+ font-family: var(--mono);
545
+ font-size: 12px;
546
+ }
547
+
548
+ .truncate {
549
+ max-width: 420px;
550
+ overflow: hidden;
551
+ text-overflow: ellipsis;
552
+ white-space: nowrap;
553
+ display: block;
554
+ }
555
+
556
+ /* ---------- Status pills ---------- */
557
+
558
+ /* Icon + label pairing, never color alone: on the light surface several
559
+ status steps sit below 3:1, and this is the documented mitigation. */
560
+ .pill {
561
+ display: inline-flex;
562
+ align-items: center;
563
+ gap: 5px;
564
+ font-size: 12px;
565
+ font-weight: 600;
566
+ padding: 2px 8px;
567
+ border-radius: 999px;
568
+ border: 1px solid transparent;
569
+ white-space: nowrap;
570
+ }
571
+
572
+ .pill::before {
573
+ font-size: 10px;
574
+ line-height: 1;
575
+ }
576
+
577
+ .pill-success {
578
+ color: var(--success-text);
579
+ background: color-mix(in srgb, var(--status-good) 12%, transparent);
580
+ border-color: color-mix(in srgb, var(--status-good) 34%, transparent);
581
+ }
582
+ .pill-success::before {
583
+ content: "\2713";
584
+ }
585
+
586
+ .pill-error {
587
+ color: var(--status-critical);
588
+ background: color-mix(in srgb, var(--status-critical) 12%, transparent);
589
+ border-color: color-mix(in srgb, var(--status-critical) 34%, transparent);
590
+ }
591
+ .pill-error::before {
592
+ content: "\2717";
593
+ }
594
+
595
+ .pill-blocked {
596
+ color: var(--status-serious);
597
+ background: color-mix(in srgb, var(--status-serious) 14%, transparent);
598
+ border-color: color-mix(in srgb, var(--status-serious) 38%, transparent);
599
+ }
600
+ .pill-blocked::before {
601
+ content: "\26D4";
602
+ }
603
+
604
+ .pill-pending {
605
+ color: var(--text-secondary);
606
+ background: var(--raised);
607
+ border-color: var(--border);
608
+ }
609
+ .pill-pending::before {
610
+ content: "\25CB";
611
+ }
612
+
613
+ .badge {
614
+ display: inline-block;
615
+ font-size: 11px;
616
+ padding: 1px 6px;
617
+ border-radius: 4px;
618
+ background: var(--raised);
619
+ border: 1px solid var(--border);
620
+ color: var(--text-secondary);
621
+ margin-left: 6px;
622
+ }
623
+
624
+ /* ---------- Footer ---------- */
625
+
626
+ .footer {
627
+ max-width: 1240px;
628
+ margin: 0 auto;
629
+ padding: 8px 24px 32px;
630
+ display: flex;
631
+ justify-content: space-between;
632
+ gap: 16px;
633
+ font-size: 12px;
634
+ color: var(--text-muted);
635
+ flex-wrap: wrap;
636
+ }
637
+
638
+ .footer code {
639
+ font-family: var(--mono);
640
+ font-size: 11px;
641
+ }
642
+
643
+ .conn {
644
+ display: inline-flex;
645
+ align-items: center;
646
+ gap: 6px;
647
+ }
648
+
649
+ .conn::before {
650
+ content: "";
651
+ width: 7px;
652
+ height: 7px;
653
+ border-radius: 50%;
654
+ background: var(--text-muted);
655
+ }
656
+
657
+ .conn.is-live::before {
658
+ background: var(--status-good);
659
+ }
660
+
661
+ .conn.is-down::before {
662
+ background: var(--status-critical);
663
+ }
664
+
665
+ @media (prefers-reduced-motion: reduce) {
666
+ * {
667
+ transition-duration: 0.01ms !important;
668
+ animation-duration: 0.01ms !important;
669
+ }
670
+ }
671
+
672
+ /* =====================================================================
673
+ Visual layer
674
+ ---------------------------------------------------------------------
675
+ Colors still come only from the validated palette tokens above; what
676
+ follows adds depth, brand presence and trend context on top of them.
677
+ ===================================================================== */
678
+
679
+ :root {
680
+ /* Tints derived from palette hues. Used for washes and accent bars only,
681
+ never as a series color, so nothing here competes with the data. */
682
+ --tint-blue: rgba(42, 120, 214, 0.08);
683
+ --tint-green: rgba(27, 175, 122, 0.08);
684
+ --tint-amber: rgba(250, 178, 25, 0.1);
685
+ --tint-red: rgba(208, 59, 59, 0.08);
686
+ --glow: rgba(42, 120, 214, 0.16);
687
+ }
688
+
689
+ @media (prefers-color-scheme: dark) {
690
+ :root:not([data-theme='light']) {
691
+ --tint-blue: rgba(57, 135, 229, 0.14);
692
+ --tint-green: rgba(25, 158, 112, 0.14);
693
+ --tint-amber: rgba(250, 178, 25, 0.14);
694
+ --tint-red: rgba(208, 59, 59, 0.14);
695
+ --glow: rgba(57, 135, 229, 0.22);
696
+ }
697
+ }
698
+
699
+ :root[data-theme='dark'] {
700
+ --tint-blue: rgba(57, 135, 229, 0.14);
701
+ --tint-green: rgba(25, 158, 112, 0.14);
702
+ --tint-amber: rgba(250, 178, 25, 0.14);
703
+ --tint-red: rgba(208, 59, 59, 0.14);
704
+ --glow: rgba(57, 135, 229, 0.22);
705
+ }
706
+
707
+ /* Ambient background. Two very low-opacity radial washes give the page
708
+ depth without tinting any surface the data sits on. Fixed attachment so
709
+ it reads as a backdrop rather than scrolling wallpaper. */
710
+ body {
711
+ background-image:
712
+ radial-gradient(900px 420px at 12% -8%, var(--tint-blue), transparent 62%),
713
+ radial-gradient(760px 380px at 92% 4%, var(--tint-green), transparent 58%);
714
+ background-attachment: fixed;
715
+ background-repeat: no-repeat;
716
+ letter-spacing: -0.006em;
717
+ }
718
+
719
+ /* ---------- brand ---------- */
720
+
721
+ .brand-mark {
722
+ background: none;
723
+ border-radius: 0;
724
+ display: grid;
725
+ place-items: center;
726
+ }
727
+
728
+ .brand-mark img,
729
+ .brand-mark svg {
730
+ width: 30px;
731
+ height: 30px;
732
+ display: block;
733
+ border-radius: 8px;
734
+ box-shadow: 0 2px 8px -2px var(--glow);
735
+ }
736
+
737
+ .topbar {
738
+ /* Translucent bar over the ambient wash, so the backdrop shows through
739
+ as the content scrolls under it. */
740
+ background: color-mix(in srgb, var(--surface) 82%, transparent);
741
+ backdrop-filter: saturate(1.4) blur(10px);
742
+ -webkit-backdrop-filter: saturate(1.4) blur(10px);
743
+ }
744
+
745
+ /* ---------- hero ---------- */
746
+
747
+ .hero {
748
+ position: relative;
749
+ overflow: hidden;
750
+ background:
751
+ linear-gradient(180deg, color-mix(in srgb, var(--series-1) 5%, var(--surface)), var(--surface));
752
+ }
753
+
754
+ /* A hairline of brand color along the top edge - enough to make the hero
755
+ read as the primary panel without adding a heavy colored block. */
756
+ .hero::before {
757
+ content: '';
758
+ position: absolute;
759
+ inset: 0 0 auto 0;
760
+ height: 3px;
761
+ background: linear-gradient(90deg, var(--series-1), var(--series-3));
762
+ }
763
+
764
+ .hero-figure {
765
+ font-variant-numeric: proportional-nums;
766
+ background: linear-gradient(135deg, var(--text-primary), color-mix(in srgb, var(--series-1) 55%, var(--text-primary)));
767
+ -webkit-background-clip: text;
768
+ background-clip: text;
769
+ color: transparent;
770
+ }
771
+
772
+ .hero-spark {
773
+ flex: 1 1 260px;
774
+ min-width: 200px;
775
+ max-width: 420px;
776
+ height: 76px;
777
+ display: block;
778
+ }
779
+
780
+ /* ---------- stat tiles ---------- */
781
+
782
+ .tile {
783
+ position: relative;
784
+ overflow: hidden;
785
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
786
+ }
787
+
788
+ .tile:hover {
789
+ transform: translateY(-1px);
790
+ box-shadow: 0 2px 4px rgba(11, 11, 11, 0.05), 0 14px 32px -14px rgba(11, 11, 11, 0.22);
791
+ }
792
+
793
+ /* Left accent bar: the one place each tile carries its own hue, so the four
794
+ read as distinct cards at a glance. Status hues stay reserved for status. */
795
+ .tile::before {
796
+ content: '';
797
+ position: absolute;
798
+ left: 0;
799
+ top: 0;
800
+ bottom: 0;
801
+ width: 3px;
802
+ background: var(--series-1);
803
+ opacity: 0.85;
804
+ }
805
+
806
+ .tile[data-accent='calls']::before { background: var(--series-1); }
807
+ .tile[data-accent='sessions']::before { background: var(--series-3); }
808
+ .tile[data-accent='errors']::before { background: var(--status-critical); }
809
+ .tile[data-accent='blocked']::before { background: var(--status-serious); }
810
+
811
+ .tile[data-accent='calls'] { background: linear-gradient(180deg, var(--tint-blue), transparent 42%), var(--surface); }
812
+ .tile[data-accent='sessions'] { background: linear-gradient(180deg, var(--tint-green), transparent 42%), var(--surface); }
813
+ .tile[data-accent='errors'] { background: linear-gradient(180deg, var(--tint-red), transparent 42%), var(--surface); }
814
+ .tile[data-accent='blocked'] { background: linear-gradient(180deg, var(--tint-amber), transparent 42%), var(--surface); }
815
+
816
+ .tile-head {
817
+ display: flex;
818
+ align-items: center;
819
+ justify-content: space-between;
820
+ gap: 10px;
821
+ }
822
+
823
+ .tile-value {
824
+ font-variant-numeric: proportional-nums;
825
+ }
826
+
827
+ .tile-spark {
828
+ width: 100%;
829
+ height: 30px;
830
+ display: block;
831
+ margin-top: 10px;
832
+ opacity: 0.9;
833
+ }
834
+
835
+ /* Delta chip: direction is carried by an arrow glyph and the sign, not by
836
+ color alone - the same icon+label rule the status pills follow. */
837
+ .delta[hidden] {
838
+ display: none;
839
+ }
840
+
841
+ .delta {
842
+ display: inline-flex;
843
+ align-items: center;
844
+ gap: 3px;
845
+ font-size: 11.5px;
846
+ font-weight: 600;
847
+ padding: 2px 7px;
848
+ border-radius: 999px;
849
+ white-space: nowrap;
850
+ font-variant-numeric: tabular-nums;
851
+ background: var(--raised);
852
+ color: var(--text-secondary);
853
+ border: 1px solid var(--border);
854
+ }
855
+
856
+ .delta-good {
857
+ color: var(--success-text);
858
+ background: color-mix(in srgb, var(--status-good) 12%, transparent);
859
+ border-color: color-mix(in srgb, var(--status-good) 30%, transparent);
860
+ }
861
+
862
+ .delta-bad {
863
+ color: var(--status-critical);
864
+ background: color-mix(in srgb, var(--status-critical) 12%, transparent);
865
+ border-color: color-mix(in srgb, var(--status-critical) 30%, transparent);
866
+ }
867
+
868
+ /* ---------- panels & tables ---------- */
869
+
870
+ .panel {
871
+ transition: box-shadow 0.15s ease;
872
+ }
873
+
874
+ .panel:hover {
875
+ box-shadow: 0 2px 4px rgba(11, 11, 11, 0.05), 0 16px 36px -18px rgba(11, 11, 11, 0.2);
876
+ }
877
+
878
+ .panel-head {
879
+ background: linear-gradient(180deg, var(--raised), transparent);
880
+ }
881
+
882
+ thead th {
883
+ position: sticky;
884
+ top: 0;
885
+ background: color-mix(in srgb, var(--surface) 92%, transparent);
886
+ backdrop-filter: blur(6px);
887
+ }
888
+
889
+ tbody tr {
890
+ transition: background 0.1s ease;
891
+ }
892
+
893
+ /* A tool name reads better with its own weight than with a colored dot,
894
+ which would imply a series identity the table does not have. */
895
+ tbody td:first-child {
896
+ font-weight: 500;
897
+ }
898
+
899
+ .pill {
900
+ letter-spacing: 0.01em;
901
+ }
902
+
903
+ .badge {
904
+ font-family: var(--mono);
905
+ font-size: 10.5px;
906
+ letter-spacing: -0.01em;
907
+ }
908
+
909
+ /* ---------- chart ---------- */
910
+
911
+ .chart-wrap {
912
+ background: linear-gradient(180deg, transparent, var(--raised));
913
+ }
914
+
915
+ .tooltip {
916
+ box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.45);
917
+ font-weight: 500;
918
+ }
919
+
920
+ /* ---------- footer ---------- */
921
+
922
+ .conn.is-live::before {
923
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-good) 22%, transparent);
924
+ }
925
+
926
+ /* ---------- icons ---------- */
927
+
928
+ /* Inline SVG icons inherit the text color of whatever they sit in, so they
929
+ never need a per-theme override and never carry a data color. */
930
+ .i {
931
+ width: 14px;
932
+ height: 14px;
933
+ flex: none;
934
+ vertical-align: -2px;
935
+ margin-right: 7px;
936
+ color: var(--text-muted);
937
+ }
938
+
939
+ .panel-head h2 {
940
+ display: flex;
941
+ align-items: center;
942
+ }
943
+
944
+ .panel-head h2 .i {
945
+ width: 15px;
946
+ height: 15px;
947
+ color: var(--series-1);
948
+ opacity: 0.9;
949
+ }
950
+
951
+ .tile-label {
952
+ display: flex;
953
+ align-items: center;
954
+ }
955
+
956
+ /* The tile icon picks up its card's accent, which is what makes the four
957
+ tiles scannable by color+shape rather than by reading each label. */
958
+ .tile[data-accent='calls'] .tile-label .i { color: var(--series-1); }
959
+ .tile[data-accent='sessions'] .tile-label .i { color: var(--series-3); }
960
+ .tile[data-accent='errors'] .tile-label .i { color: var(--status-critical); }
961
+ .tile[data-accent='blocked'] .tile-label .i { color: var(--status-serious); }