@oh-my-pi/omp-stats 18.16.0 → 18.17.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 (77) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/client/index.css +1 -1
  3. package/dist/client/index.js +102 -99
  4. package/dist/types/client/api.d.ts +4 -1
  5. package/dist/types/client/app/nav.d.ts +1 -1
  6. package/dist/types/client/charts/Chart.d.ts +16 -8
  7. package/dist/types/client/charts/DotWhisker.d.ts +50 -0
  8. package/dist/types/client/charts/Sparkline.d.ts +1 -1
  9. package/dist/types/client/charts/Waterfall.d.ts +26 -0
  10. package/dist/types/client/charts/index.d.ts +2 -0
  11. package/dist/types/client/charts/types.d.ts +8 -2
  12. package/dist/types/client/routes/SpotlightRoute.d.ts +7 -0
  13. package/dist/types/client/routes/index.d.ts +1 -0
  14. package/dist/types/client/spotlight/Compounding.d.ts +8 -0
  15. package/dist/types/client/spotlight/Coverage.d.ts +6 -0
  16. package/dist/types/client/spotlight/Economics.d.ts +10 -0
  17. package/dist/types/client/spotlight/FetchBack.d.ts +9 -0
  18. package/dist/types/client/spotlight/Hero.d.ts +12 -0
  19. package/dist/types/client/spotlight/Overhead.d.ts +6 -0
  20. package/dist/types/client/spotlight/Ranking.d.ts +6 -0
  21. package/dist/types/client/spotlight/ResultsFeed.d.ts +6 -0
  22. package/dist/types/client/spotlight/Savings.d.ts +10 -0
  23. package/dist/types/client/spotlight/ShareTrend.d.ts +8 -0
  24. package/dist/types/client/spotlight/Steps.d.ts +6 -0
  25. package/dist/types/client/spotlight/TimeCost.d.ts +6 -0
  26. package/dist/types/client/spotlight/chips.d.ts +16 -0
  27. package/dist/types/client/spotlight/meta.d.ts +64 -0
  28. package/dist/types/db.d.ts +26 -0
  29. package/dist/types/index.d.ts +2 -1
  30. package/dist/types/parser.d.ts +4 -0
  31. package/dist/types/rollup.d.ts +22 -1
  32. package/dist/types/shared-types.d.ts +419 -0
  33. package/dist/types/spotlight-aggregator.d.ts +189 -0
  34. package/dist/types/spotlight-bootstrap.d.ts +32 -0
  35. package/dist/types/spotlight-ingest.d.ts +258 -0
  36. package/dist/types/spotlight-measures.d.ts +51 -0
  37. package/package.json +5 -5
  38. package/src/aggregator.ts +3 -1
  39. package/src/client/App.tsx +3 -0
  40. package/src/client/api.ts +21 -0
  41. package/src/client/app/nav.ts +4 -1
  42. package/src/client/charts/Chart.tsx +105 -22
  43. package/src/client/charts/DotWhisker.tsx +149 -0
  44. package/src/client/charts/Sparkline.tsx +3 -2
  45. package/src/client/charts/Waterfall.tsx +86 -0
  46. package/src/client/charts/index.ts +2 -0
  47. package/src/client/charts/types.ts +9 -2
  48. package/src/client/react-css.d.ts +1 -1
  49. package/src/client/routes/SpotlightRoute.tsx +138 -0
  50. package/src/client/routes/index.ts +1 -0
  51. package/src/client/spotlight/Compounding.tsx +222 -0
  52. package/src/client/spotlight/Coverage.tsx +96 -0
  53. package/src/client/spotlight/Economics.tsx +167 -0
  54. package/src/client/spotlight/FetchBack.tsx +222 -0
  55. package/src/client/spotlight/Hero.tsx +177 -0
  56. package/src/client/spotlight/Overhead.tsx +135 -0
  57. package/src/client/spotlight/Ranking.tsx +248 -0
  58. package/src/client/spotlight/ResultsFeed.tsx +354 -0
  59. package/src/client/spotlight/Savings.tsx +355 -0
  60. package/src/client/spotlight/ShareTrend.tsx +103 -0
  61. package/src/client/spotlight/Steps.tsx +225 -0
  62. package/src/client/spotlight/TimeCost.tsx +64 -0
  63. package/src/client/spotlight/chips.tsx +63 -0
  64. package/src/client/spotlight/meta.ts +206 -0
  65. package/src/client/spotlight/spotlight.css +1387 -0
  66. package/src/client/styles.css +289 -1
  67. package/src/db.ts +480 -2
  68. package/src/index.ts +10 -1
  69. package/src/live.ts +21 -9
  70. package/src/parser.ts +44 -8
  71. package/src/rollup.ts +203 -10
  72. package/src/server.ts +42 -0
  73. package/src/shared-types.ts +453 -0
  74. package/src/spotlight-aggregator.ts +1738 -0
  75. package/src/spotlight-bootstrap.ts +110 -0
  76. package/src/spotlight-ingest.ts +981 -0
  77. package/src/spotlight-measures.ts +667 -0
@@ -0,0 +1,1387 @@
1
+ /* ==========================================================================
2
+ Spotlight page. Baselines are muted greys (hollow marks), the cuts take
3
+ vivid hues; everything a recovery takes back uses the warm "loss" family.
4
+ ========================================================================== */
5
+
6
+ :root,
7
+ [data-theme="dark"] {
8
+ --spot-gross: var(--chart-primary);
9
+ --spot-net: var(--accent);
10
+ --spot-net-fill: var(--accent-gradient);
11
+ --spot-ghost: var(--accent);
12
+ --spot-clawback: #f5a524;
13
+ --spot-artifact: #f5b54a;
14
+ --spot-reread: #ff8a4c;
15
+ --spot-rerun: #fb7185;
16
+ --spot-turns: #c084fc;
17
+ --spot-cost: #8e8e98;
18
+ /* Fetch-backs held-out results show happen anyway: added back, so neutral rather than a loss hue. */
19
+ --spot-anyway: var(--ink-3);
20
+ /* Tool output the experiment does not shape: untouched, so a neutral grey. */
21
+ --spot-unshaped: #a0a0a8;
22
+
23
+ --spot-shaped: var(--accent-a);
24
+ --spot-outside: #7c8cff;
25
+
26
+ /* Fetch-back groups: the cut is vivid, its baselines neutral (held out, the counterfactual, the stronger). */
27
+ --spot-applied: var(--chart-primary);
28
+ --spot-score-free: #8b9cff;
29
+ --spot-holdout: var(--ink-1);
30
+ --spot-reference: var(--ink-3);
31
+ /* Reads pi's former edit gate kept whole: shown whole like the holdout, in a hue of their own. */
32
+ --spot-gated: #46c08a;
33
+ }
34
+
35
+ [data-theme="light"] {
36
+ --spot-clawback: #d98a04;
37
+ --spot-artifact: #c77c02;
38
+ --spot-reread: #e0612a;
39
+ --spot-rerun: #e0405f;
40
+ --spot-turns: #9b5de5;
41
+ --spot-cost: #8b8b94;
42
+
43
+ --spot-unshaped: #7d7d86;
44
+ --spot-outside: #5b6bd6;
45
+
46
+ --spot-score-free: #4c5fd6;
47
+ --spot-gated: #16895a;
48
+ }
49
+
50
+ /* The four questions the page answers, in order. */
51
+ .spot-section {
52
+ margin-top: 18px;
53
+ padding: 0 2px;
54
+ scroll-margin-top: 24px;
55
+ }
56
+
57
+ .spot-section-title {
58
+ font-size: 17px;
59
+ font-weight: 600;
60
+ letter-spacing: -0.015em;
61
+ color: var(--ink-1);
62
+ text-wrap: balance;
63
+ }
64
+
65
+ .spot-section-copy {
66
+ margin-top: 3px;
67
+ max-width: 80ch;
68
+ font-size: 13px;
69
+ color: var(--ink-2);
70
+ text-wrap: pretty;
71
+ }
72
+
73
+ .spot-eyebrow {
74
+ font-size: 12px;
75
+ font-weight: 500;
76
+ color: var(--ink-2);
77
+ }
78
+
79
+ /* --------------------------------------------------------------------------
80
+ Hero
81
+ -------------------------------------------------------------------------- */
82
+ .spot-hero {
83
+ overflow: hidden;
84
+ background:
85
+ radial-gradient(38rem 15rem at 0% 0%, color-mix(in srgb, var(--accent-a) 9%, transparent), transparent 72%)
86
+ padding-box,
87
+ radial-gradient(34rem 15rem at 100% 0%, color-mix(in srgb, var(--accent-b) 8%, transparent), transparent 72%)
88
+ padding-box,
89
+ linear-gradient(var(--card), var(--card)) padding-box,
90
+ linear-gradient(180deg, var(--line-3), var(--line-1) 40%) border-box;
91
+ }
92
+
93
+ .spot-hero-main {
94
+ display: grid;
95
+ grid-template-columns: minmax(0, auto) minmax(0, 1fr);
96
+ align-items: end;
97
+ gap: 20px 48px;
98
+ padding: 24px 26px 22px;
99
+ }
100
+
101
+ .spot-hero-aside {
102
+ display: flex;
103
+ flex-direction: column;
104
+ gap: 10px;
105
+ max-width: 64ch;
106
+ justify-self: end;
107
+ }
108
+
109
+ .spot-hero-figures {
110
+ display: flex;
111
+ align-items: baseline;
112
+ flex-wrap: wrap;
113
+ gap: 6px 10px;
114
+ margin-top: 8px;
115
+ }
116
+
117
+ .spot-hero-value {
118
+ font-size: 56px;
119
+ font-weight: 650;
120
+ line-height: 1;
121
+ letter-spacing: -0.04em;
122
+ font-variant-numeric: tabular-nums;
123
+ /* Keep descender room so the gradient clip doesn't shave glyph edges. */
124
+ padding-bottom: 4px;
125
+ }
126
+
127
+ .spot-hero-unit {
128
+ font-size: 15px;
129
+ font-weight: 500;
130
+ color: var(--ink-3);
131
+ }
132
+
133
+ .spot-hero-usd {
134
+ align-self: center;
135
+ margin-left: 6px;
136
+ padding: 3px 11px;
137
+ border-radius: var(--r-pill);
138
+ border: 1px solid var(--line-2);
139
+ background: color-mix(in srgb, var(--raised) 70%, transparent);
140
+ font-size: 18px;
141
+ font-weight: 550;
142
+ letter-spacing: -0.01em;
143
+ font-variant-numeric: tabular-nums;
144
+ white-space: nowrap;
145
+ }
146
+
147
+ .spot-hero-usd[data-negative="true"] {
148
+ color: var(--bad);
149
+ border-color: color-mix(in srgb, var(--bad) 35%, transparent);
150
+ background: var(--bad-soft);
151
+ }
152
+
153
+ .spot-hero-interval {
154
+ margin-top: 6px;
155
+ font-size: 12.5px;
156
+ color: var(--ink-3);
157
+ }
158
+
159
+ .spot-hero-interval .num {
160
+ color: var(--ink-2);
161
+ }
162
+
163
+ .spot-hero-note {
164
+ font-size: 12.5px;
165
+ line-height: 1.6;
166
+ color: var(--ink-3);
167
+ text-wrap: pretty;
168
+ }
169
+
170
+ .spot-hero-note code {
171
+ font-size: 11.5px;
172
+ color: var(--ink-2);
173
+ }
174
+
175
+ .spot-struck {
176
+ color: var(--ink-2);
177
+ text-decoration-thickness: 1.5px;
178
+ text-decoration-color: color-mix(in srgb, var(--ink-3) 80%, transparent);
179
+ }
180
+
181
+ .spot-hero-warn {
182
+ display: flex;
183
+ align-items: flex-start;
184
+ gap: 7px;
185
+ padding: 6px 10px;
186
+ border-radius: var(--r-control);
187
+ background: var(--warn-soft);
188
+ font-size: 12.5px;
189
+ line-height: 1.5;
190
+ color: var(--ink-1);
191
+ }
192
+
193
+ .spot-hero-warn > svg {
194
+ flex: none;
195
+ margin-top: 2px;
196
+ color: var(--warn);
197
+ }
198
+
199
+ .spot-nowrap {
200
+ white-space: nowrap;
201
+ }
202
+
203
+ .spot-hero-tools {
204
+ display: flex;
205
+ flex-wrap: wrap;
206
+ gap: 2px 10px;
207
+ }
208
+
209
+ .spot-hero-tools > span {
210
+ display: inline-flex;
211
+ align-items: center;
212
+ gap: 4px;
213
+ }
214
+
215
+ .spot-hero-tools > [data-thin="true"] {
216
+ color: var(--warn);
217
+ }
218
+
219
+ .spot-hero-stats {
220
+ display: grid;
221
+ grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
222
+ border-top: 1px solid var(--line-1);
223
+ }
224
+
225
+ .spot-hero-stats .stat {
226
+ padding: 14px 18px 14px;
227
+ }
228
+
229
+ .spot-hero-stats .stat-foot .truncate {
230
+ white-space: normal;
231
+ overflow: visible;
232
+ }
233
+
234
+ @media (max-width: 1100px) {
235
+ .spot-hero-main {
236
+ grid-template-columns: minmax(0, 1fr);
237
+ }
238
+
239
+ .spot-hero-aside {
240
+ justify-self: start;
241
+ }
242
+ }
243
+
244
+ @media (max-width: 900px) {
245
+ .spot-hero-value {
246
+ font-size: 44px;
247
+ }
248
+ }
249
+
250
+ /* --------------------------------------------------------------------------
251
+ Chips and badges
252
+ -------------------------------------------------------------------------- */
253
+ .spot-kind {
254
+ display: inline-flex;
255
+ align-items: center;
256
+ gap: 4px;
257
+ height: 20px;
258
+ padding: 0 7px;
259
+ border-radius: var(--r-pill);
260
+ font-size: 11.5px;
261
+ font-weight: 500;
262
+ white-space: nowrap;
263
+ color: var(--kind);
264
+ background: color-mix(in srgb, var(--kind) 13%, transparent);
265
+ }
266
+
267
+ .spot-chart-legend {
268
+ margin-bottom: 12px;
269
+ }
270
+
271
+ .spot-by-tool {
272
+ margin-top: 18px;
273
+ padding-top: 14px;
274
+ border-top: 1px solid var(--line-1);
275
+ }
276
+
277
+ .spot-tool-net {
278
+ display: flex;
279
+ flex-direction: column;
280
+ gap: 12px;
281
+ margin: 0;
282
+ padding: 0;
283
+ list-style: none;
284
+ }
285
+
286
+ .spot-tool-net-head {
287
+ gap: 7px;
288
+ font-size: 12.5px;
289
+ }
290
+
291
+ .spot-tool-net-head svg {
292
+ color: var(--ink-3);
293
+ }
294
+
295
+ .spot-tool-net-value {
296
+ margin-left: auto;
297
+ font-weight: 550;
298
+ color: var(--ink-1);
299
+ }
300
+
301
+ .spot-tool-net-track {
302
+ margin: 5px 0 4px;
303
+ height: 8px;
304
+ border-radius: 3px;
305
+ background: var(--line-1);
306
+ }
307
+
308
+ .spot-tool-net-bar {
309
+ position: relative;
310
+ display: flex;
311
+ justify-content: flex-end;
312
+ height: 100%;
313
+ min-width: 2px;
314
+ border-radius: 3px;
315
+ overflow: hidden;
316
+ background: var(--spot-gross);
317
+ }
318
+
319
+ /* The tool's fetch-back beyond its holdout baseline, hatched off the end of its gross. */
320
+ .spot-tool-net-excess {
321
+ height: 100%;
322
+ background: repeating-linear-gradient(
323
+ -45deg,
324
+ var(--spot-clawback) 0 2px,
325
+ color-mix(in srgb, var(--spot-clawback) 30%, var(--card)) 2px 5px
326
+ );
327
+ }
328
+
329
+ .spot-tool-net-detail {
330
+ color: var(--ink-2);
331
+ font-variant-numeric: tabular-nums;
332
+ }
333
+
334
+ .spot-step-swatch {
335
+ width: 8px;
336
+ height: 8px;
337
+ border-radius: 2px;
338
+ flex: none;
339
+ }
340
+
341
+ /* --------------------------------------------------------------------------
342
+ Compounding
343
+ -------------------------------------------------------------------------- */
344
+ .spot-session-select {
345
+ max-width: 380px;
346
+ }
347
+
348
+ .spot-compounding {
349
+ display: grid;
350
+ grid-template-columns: minmax(0, 1fr) 268px;
351
+ gap: 28px;
352
+ }
353
+
354
+ .spot-compounding-chart {
355
+ min-width: 0;
356
+ }
357
+
358
+ .spot-context {
359
+ display: flex;
360
+ flex-direction: column;
361
+ gap: 12px;
362
+ }
363
+
364
+ .spot-compounding-side {
365
+ display: flex;
366
+ flex-direction: column;
367
+ gap: 6px;
368
+ padding-left: 28px;
369
+ border-left: 1px solid var(--line-1);
370
+ }
371
+
372
+ .spot-side-value {
373
+ font-size: 36px;
374
+ font-weight: 600;
375
+ line-height: 1.1;
376
+ letter-spacing: -0.03em;
377
+ font-variant-numeric: tabular-nums;
378
+ }
379
+
380
+ .spot-side-copy {
381
+ font-size: 12.5px;
382
+ line-height: 1.6;
383
+ color: var(--ink-2);
384
+ text-wrap: pretty;
385
+ }
386
+
387
+ .spot-side-range {
388
+ margin-top: 14px;
389
+ padding-top: 12px;
390
+ border-top: 1px solid var(--line-1);
391
+ font-size: 12px;
392
+ line-height: 1.55;
393
+ color: var(--ink-3);
394
+ text-wrap: pretty;
395
+ }
396
+
397
+ .spot-side-range-value {
398
+ font-weight: 600;
399
+ color: var(--ink-1);
400
+ font-variant-numeric: tabular-nums;
401
+ }
402
+
403
+ .spot-facts {
404
+ display: grid;
405
+ grid-template-columns: repeat(2, minmax(0, 1fr));
406
+ gap: 12px 16px;
407
+ margin: 10px 0 0;
408
+ padding-top: 14px;
409
+ border-top: 1px solid var(--line-1);
410
+ }
411
+
412
+ .spot-facts dt {
413
+ font-size: 11.5px;
414
+ color: var(--ink-3);
415
+ }
416
+
417
+ .spot-facts dd {
418
+ margin: 2px 0 0;
419
+ color: var(--ink-1);
420
+ }
421
+
422
+ .spot-tooltip-extra {
423
+ display: flex;
424
+ flex-direction: column;
425
+ }
426
+
427
+ @media (max-width: 1100px) {
428
+ .spot-compounding {
429
+ grid-template-columns: minmax(0, 1fr);
430
+ }
431
+
432
+ .spot-compounding-side {
433
+ padding: 16px 0 0;
434
+ border-left: 0;
435
+ border-top: 1px solid var(--line-1);
436
+ }
437
+ }
438
+
439
+ /* --------------------------------------------------------------------------
440
+ Fetch-back groups: legend marks match the dot-whisker marks
441
+ -------------------------------------------------------------------------- */
442
+ .spot-group-legend {
443
+ margin-bottom: 10px;
444
+ }
445
+
446
+ .spot-group-mark {
447
+ width: 9px;
448
+ height: 9px;
449
+ flex: none;
450
+ border-radius: 50%;
451
+ background: var(--dot);
452
+ }
453
+
454
+ .spot-group-mark[data-shape="ring"] {
455
+ background: transparent;
456
+ border: 2px solid var(--dot);
457
+ }
458
+
459
+ .spot-group-mark[data-shape="square"] {
460
+ border-radius: 2px;
461
+ }
462
+
463
+ .spot-group-mark[data-shape="diamond"] {
464
+ width: 7px;
465
+ height: 7px;
466
+ margin: 0 1px;
467
+ border-radius: 1.5px;
468
+ transform: rotate(45deg);
469
+ }
470
+
471
+ /* --------------------------------------------------------------------------
472
+ Does the agent come back for it?
473
+ -------------------------------------------------------------------------- */
474
+ .spot-fb .dw-row {
475
+ grid-template-columns: 14rem minmax(0, 1fr) 128px;
476
+ height: 44px;
477
+ }
478
+
479
+ .spot-fb-tool {
480
+ display: inline-flex;
481
+ align-items: center;
482
+ gap: 6px;
483
+ width: 6.5rem;
484
+ flex: none;
485
+ font-weight: 550;
486
+ color: var(--ink-1);
487
+ }
488
+
489
+ /* Long names (MCP and extension tools) end in an ellipsis; the full name is the label's title. */
490
+ .spot-fb-tool-name {
491
+ min-width: 0;
492
+ overflow: hidden;
493
+ text-overflow: ellipsis;
494
+ white-space: nowrap;
495
+ }
496
+
497
+ .spot-fb-tool svg {
498
+ flex: none;
499
+ color: var(--ink-3);
500
+ }
501
+
502
+ .spot-fb-detail[data-group="holdout"] {
503
+ color: var(--ink-1);
504
+ }
505
+
506
+ .spot-fb-detail[data-group="scoreFree"] {
507
+ color: var(--spot-score-free);
508
+ }
509
+
510
+ /* --------------------------------------------------------------------------
511
+ Does Spotlight keep what the agent needs?
512
+ -------------------------------------------------------------------------- */
513
+ .spot-rank {
514
+ display: flex;
515
+ flex-direction: column;
516
+ gap: 22px;
517
+ }
518
+
519
+ .spot-rank-panels {
520
+ display: grid;
521
+ grid-template-columns: repeat(3, minmax(0, 1fr));
522
+ gap: 22px 32px;
523
+ }
524
+
525
+ .spot-rank-panel .dw-row {
526
+ grid-template-columns: 6.25rem minmax(0, 1fr) 84px;
527
+ gap: 10px;
528
+ height: 40px;
529
+ }
530
+
531
+ .spot-rank-panel .spot-panel-title,
532
+ .spot-rank-foot .spot-panel-title {
533
+ display: flex;
534
+ align-items: baseline;
535
+ justify-content: space-between;
536
+ gap: 8px;
537
+ }
538
+
539
+ .spot-rank-chance {
540
+ font-family: var(--font-mono);
541
+ font-size: 10.5px;
542
+ font-weight: 400;
543
+ color: var(--ink-3);
544
+ white-space: nowrap;
545
+ }
546
+
547
+ .spot-rank-foot {
548
+ display: grid;
549
+ grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.5fr) minmax(0, 0.6fr);
550
+ gap: 22px 32px;
551
+ padding-top: 18px;
552
+ border-top: 1px solid var(--line-1);
553
+ }
554
+
555
+ .spot-rank-n {
556
+ width: 100%;
557
+ border-collapse: collapse;
558
+ font-size: 12px;
559
+ }
560
+
561
+ .spot-rank-n th {
562
+ font-weight: 500;
563
+ color: var(--ink-3);
564
+ text-align: right;
565
+ padding: 4px 0 4px 10px;
566
+ }
567
+
568
+ .spot-rank-n th:first-child {
569
+ text-align: left;
570
+ padding-left: 0;
571
+ }
572
+
573
+ .spot-rank-n tbody th {
574
+ text-align: left;
575
+ padding-left: 0;
576
+ }
577
+
578
+ .spot-rank-n td {
579
+ padding: 5px 0 5px 10px;
580
+ text-align: right;
581
+ color: var(--ink-1);
582
+ border-top: 1px solid var(--line-1);
583
+ white-space: nowrap;
584
+ }
585
+
586
+ .spot-rank-n tbody th {
587
+ border-top: 1px solid var(--line-1);
588
+ }
589
+
590
+ /* Under 20 results a cell's intervals are wide: the count says so. */
591
+ .spot-rank-n td[data-thin="true"] {
592
+ color: var(--warn);
593
+ }
594
+
595
+ .spot-rank-bars {
596
+ display: grid;
597
+ grid-auto-columns: minmax(0, 1fr);
598
+ grid-auto-flow: column;
599
+ gap: 4px;
600
+ height: 112px;
601
+ margin-top: 8px;
602
+ }
603
+
604
+ .spot-rank-bar {
605
+ display: flex;
606
+ flex-direction: column;
607
+ justify-content: flex-end;
608
+ align-items: center;
609
+ gap: 3px;
610
+ min-width: 0;
611
+ }
612
+
613
+ .spot-rank-bar-track {
614
+ display: flex;
615
+ flex-direction: column;
616
+ justify-content: flex-end;
617
+ align-items: center;
618
+ gap: 2px;
619
+ flex: 1;
620
+ width: 100%;
621
+ min-height: 0;
622
+ }
623
+
624
+ .spot-rank-bar-fill {
625
+ width: 100%;
626
+ min-height: 1px;
627
+ border-radius: 3px 3px 1px 1px;
628
+ background: color-mix(in srgb, var(--spot-applied) 75%, transparent);
629
+ }
630
+
631
+ .spot-rank-bar-value,
632
+ .spot-rank-bar-label {
633
+ font-size: 10px;
634
+ color: var(--ink-3);
635
+ white-space: nowrap;
636
+ }
637
+
638
+ .spot-rank-bar-value {
639
+ color: var(--ink-2);
640
+ }
641
+
642
+ .spot-rank-axis {
643
+ margin-top: 6px;
644
+ font-size: 11px;
645
+ font-weight: 400;
646
+ }
647
+
648
+ .spot-rank-facts {
649
+ grid-template-columns: minmax(0, 1fr);
650
+ margin: 0;
651
+ padding-top: 4px;
652
+ border-top: 0;
653
+ }
654
+
655
+ @media (max-width: 1100px) {
656
+ .spot-rank-panels,
657
+ .spot-rank-foot {
658
+ grid-template-columns: minmax(0, 1fr);
659
+ }
660
+ }
661
+
662
+ /* --------------------------------------------------------------------------
663
+ What cuts earn, by tool
664
+ -------------------------------------------------------------------------- */
665
+ .spot-econ {
666
+ border-collapse: separate;
667
+ border-spacing: 6px;
668
+ margin: -6px;
669
+ width: calc(100% + 12px);
670
+ table-layout: fixed;
671
+ }
672
+
673
+ .spot-econ th {
674
+ font-size: 12px;
675
+ font-weight: 500;
676
+ color: var(--ink-2);
677
+ text-align: left;
678
+ }
679
+
680
+ .spot-econ thead th {
681
+ padding: 0 4px 2px;
682
+ }
683
+
684
+ .spot-econ thead th:first-child,
685
+ .spot-econ tbody th {
686
+ width: 8rem;
687
+ }
688
+
689
+ .spot-econ-tool {
690
+ gap: 6px;
691
+ color: var(--ink-1);
692
+ }
693
+
694
+ .spot-econ-tool svg {
695
+ flex: none;
696
+ color: var(--ink-3);
697
+ }
698
+
699
+ .spot-econ-tool-name {
700
+ min-width: 0;
701
+ overflow: hidden;
702
+ text-overflow: ellipsis;
703
+ white-space: nowrap;
704
+ }
705
+
706
+ .spot-econ td {
707
+ padding: 0;
708
+ }
709
+
710
+ .spot-econ-cell {
711
+ display: flex;
712
+ flex-direction: column;
713
+ gap: 8px;
714
+ min-height: 84px;
715
+ padding: 11px 13px;
716
+ border-radius: var(--r-control);
717
+ border: 1px solid var(--line-1);
718
+ background: var(--raised);
719
+ }
720
+
721
+ .spot-econ-cell[data-tone="ok"] {
722
+ border-color: color-mix(in srgb, var(--ok) calc(var(--tint) + 8%), transparent);
723
+ background: color-mix(in srgb, var(--ok) var(--tint), var(--card));
724
+ }
725
+
726
+ .spot-econ-cell[data-tone="bad"] {
727
+ border-color: color-mix(in srgb, var(--bad) calc(var(--tint) + 8%), transparent);
728
+ background: color-mix(in srgb, var(--bad) var(--tint), var(--card));
729
+ }
730
+
731
+ .spot-econ-cell[data-empty="true"] {
732
+ justify-content: center;
733
+ align-items: center;
734
+ background: transparent;
735
+ border-style: dashed;
736
+ font-size: 12px;
737
+ }
738
+
739
+ .spot-econ-net {
740
+ font-size: 17px;
741
+ font-weight: 600;
742
+ letter-spacing: -0.01em;
743
+ color: var(--ink-1);
744
+ }
745
+
746
+ .spot-econ-cell[data-tone="ok"] .spot-econ-net {
747
+ color: var(--ok);
748
+ }
749
+
750
+ .spot-econ-cell[data-tone="bad"] .spot-econ-net {
751
+ color: var(--bad);
752
+ }
753
+
754
+ .spot-econ-facts {
755
+ display: flex;
756
+ flex-wrap: wrap;
757
+ gap: 2px 14px;
758
+ margin: 0;
759
+ }
760
+
761
+ .spot-econ-facts > div {
762
+ display: flex;
763
+ align-items: baseline;
764
+ gap: 5px;
765
+ }
766
+
767
+ .spot-econ-facts dt {
768
+ font-size: 11px;
769
+ color: var(--ink-3);
770
+ }
771
+
772
+ .spot-econ-facts dd {
773
+ margin: 0;
774
+ font-size: 11.5px;
775
+ color: var(--ink-1);
776
+ }
777
+
778
+ .spot-econ-scale {
779
+ display: inline-flex;
780
+ align-items: center;
781
+ gap: 8px;
782
+ font-size: 11px;
783
+ color: var(--ink-3);
784
+ }
785
+
786
+ .spot-econ-ramp {
787
+ width: 88px;
788
+ height: 6px;
789
+ border-radius: 3px;
790
+ background: linear-gradient(
791
+ 90deg,
792
+ color-mix(in srgb, var(--bad) 70%, var(--card)),
793
+ var(--raised) 50%,
794
+ color-mix(in srgb, var(--ok) 70%, var(--card))
795
+ );
796
+ }
797
+
798
+ /* --------------------------------------------------------------------------
799
+ Which cuts pay (reuses the economics cells)
800
+ -------------------------------------------------------------------------- */
801
+ .spot-steps-scroll,
802
+ .spot-econ-scroll {
803
+ overflow-x: auto;
804
+ }
805
+
806
+ .spot-steps {
807
+ min-width: 720px;
808
+ }
809
+
810
+ .spot-steps thead th:first-child,
811
+ .spot-steps tbody th {
812
+ width: 10rem;
813
+ }
814
+
815
+ .spot-steps thead th:not(:first-child) {
816
+ font-variant-numeric: tabular-nums;
817
+ }
818
+
819
+ /* "All sizes" sums the row: a hairline keeps it apart from the size bins. */
820
+ .spot-steps tr > :last-child:not([colspan]) {
821
+ border-left: 1px solid var(--line-2);
822
+ padding-left: 6px;
823
+ }
824
+
825
+ .spot-steps-tool th {
826
+ padding: 10px 4px 0;
827
+ }
828
+
829
+ .spot-steps-tool:first-child th {
830
+ padding-top: 0;
831
+ }
832
+
833
+ .spot-steps-name {
834
+ padding-left: 22px;
835
+ font-family: var(--font-mono);
836
+ font-size: 11.5px;
837
+ font-weight: 400;
838
+ color: var(--ink-1);
839
+ overflow-wrap: anywhere;
840
+ }
841
+
842
+ .spot-steps .spot-econ-cell {
843
+ gap: 4px;
844
+ min-height: 0;
845
+ padding: 8px 11px;
846
+ }
847
+
848
+ .spot-steps .spot-econ-cell[data-empty="true"] {
849
+ min-height: 58px;
850
+ }
851
+
852
+ .spot-steps .spot-econ-net {
853
+ font-size: 15px;
854
+ }
855
+
856
+ .spot-steps-unit {
857
+ font-size: 11px;
858
+ font-weight: 500;
859
+ opacity: 0.75;
860
+ }
861
+
862
+ .spot-econ-cell[data-thin="true"] {
863
+ opacity: 0.45;
864
+ }
865
+
866
+ /* --------------------------------------------------------------------------
867
+ Time cost
868
+ -------------------------------------------------------------------------- */
869
+ .spot-time {
870
+ display: flex;
871
+ flex-direction: column;
872
+ margin: 0;
873
+ padding: 0;
874
+ list-style: none;
875
+ }
876
+
877
+ .spot-time-row {
878
+ display: grid;
879
+ grid-template-columns: 9rem minmax(0, 1fr) 52px 22rem;
880
+ align-items: center;
881
+ gap: 14px;
882
+ min-height: 36px;
883
+ font-size: 12.5px;
884
+ }
885
+
886
+ .spot-time-track {
887
+ display: flex;
888
+ height: 10px;
889
+ border-radius: 3px;
890
+ overflow: hidden;
891
+ background: var(--line-1);
892
+ }
893
+
894
+ .spot-time-fill {
895
+ height: 100%;
896
+ }
897
+
898
+ .spot-time-share {
899
+ text-align: right;
900
+ color: var(--ink-1);
901
+ }
902
+
903
+ .spot-time-detail {
904
+ font-size: 12px;
905
+ font-weight: 400;
906
+ color: var(--ink-2);
907
+ white-space: nowrap;
908
+ }
909
+
910
+ @media (max-width: 900px) {
911
+ .spot-time-row {
912
+ grid-template-columns: 8rem minmax(0, 1fr) 52px;
913
+ padding: 6px 0;
914
+ }
915
+
916
+ .spot-time-detail {
917
+ grid-column: 1 / -1;
918
+ white-space: normal;
919
+ }
920
+ }
921
+
922
+ /* --------------------------------------------------------------------------
923
+ Not shaped yet
924
+ -------------------------------------------------------------------------- */
925
+ .spot-coverage-summary {
926
+ display: flex;
927
+ flex-direction: column;
928
+ gap: 8px;
929
+ margin-bottom: 16px;
930
+ }
931
+
932
+ .spot-coverage-headline {
933
+ font-size: 13px;
934
+ color: var(--ink-2);
935
+ }
936
+
937
+ .spot-coverage-headline .num {
938
+ font-size: 20px;
939
+ font-weight: 600;
940
+ letter-spacing: -0.02em;
941
+ color: var(--ink-1);
942
+ }
943
+
944
+ .spot-coverage .bar-list-label {
945
+ gap: 8px;
946
+ }
947
+
948
+ .spot-coverage-tool {
949
+ font-family: var(--font-mono);
950
+ font-size: 12px;
951
+ color: var(--ink-1);
952
+ }
953
+
954
+ /* The toggle under a per-tool section that lists only the top tools. */
955
+ .spot-more-tools {
956
+ display: flex;
957
+ margin-top: 10px;
958
+ }
959
+
960
+ /* --------------------------------------------------------------------------
961
+ How soon it comes back
962
+ -------------------------------------------------------------------------- */
963
+ .spot-gaps {
964
+ display: grid;
965
+ grid-template-columns: repeat(3, minmax(0, 1fr));
966
+ gap: 22px 32px;
967
+ }
968
+
969
+ .spot-gap-title {
970
+ gap: 6px;
971
+ }
972
+
973
+ .spot-gap-title svg {
974
+ color: var(--ink-3);
975
+ }
976
+
977
+ .spot-gap-title .dim {
978
+ margin-left: auto;
979
+ font-size: 11px;
980
+ font-weight: 400;
981
+ }
982
+
983
+ .spot-gap-bins {
984
+ display: grid;
985
+ grid-template-columns: repeat(5, minmax(0, 1fr));
986
+ gap: 6px;
987
+ margin-top: 8px;
988
+ }
989
+
990
+ .spot-gap-bin {
991
+ display: flex;
992
+ flex-direction: column;
993
+ align-items: stretch;
994
+ gap: 6px;
995
+ }
996
+
997
+ .spot-gap-bars {
998
+ display: flex;
999
+ align-items: flex-end;
1000
+ justify-content: center;
1001
+ gap: 3px;
1002
+ height: 132px;
1003
+ padding-top: 16px;
1004
+ border-bottom: 1px solid var(--line-2);
1005
+ }
1006
+
1007
+ .spot-gap-bar {
1008
+ position: relative;
1009
+ display: flex;
1010
+ flex-direction: column;
1011
+ justify-content: flex-end;
1012
+ align-items: center;
1013
+ width: min(22px, 42%);
1014
+ height: 100%;
1015
+ }
1016
+
1017
+ .spot-gap-fill {
1018
+ width: 100%;
1019
+ min-height: 1px;
1020
+ border-radius: 3px 3px 0 0;
1021
+ background: var(--spot-applied);
1022
+ transition: height var(--dur-3) var(--ease-out);
1023
+ }
1024
+
1025
+ .spot-gap-bar[data-group="holdout"] .spot-gap-fill {
1026
+ background: color-mix(in srgb, var(--spot-holdout) 14%, transparent);
1027
+ box-shadow: inset 0 0 0 1.5px var(--spot-holdout);
1028
+ }
1029
+
1030
+ .spot-gap-bar[data-empty="true"] .spot-gap-fill {
1031
+ display: none;
1032
+ }
1033
+
1034
+ .spot-gap-value {
1035
+ margin-bottom: 3px;
1036
+ font-size: 9.5px;
1037
+ color: var(--ink-3);
1038
+ white-space: nowrap;
1039
+ }
1040
+
1041
+ .spot-gap-label {
1042
+ font-size: 10.5px;
1043
+ text-align: center;
1044
+ color: var(--chart-axis);
1045
+ }
1046
+
1047
+ .spot-gap-empty {
1048
+ display: grid;
1049
+ place-items: center;
1050
+ height: 150px;
1051
+ font-size: 12px;
1052
+ }
1053
+
1054
+ @media (max-width: 1100px) {
1055
+ .spot-gaps {
1056
+ grid-template-columns: minmax(0, 1fr);
1057
+ }
1058
+ }
1059
+
1060
+ /* --------------------------------------------------------------------------
1061
+ Overhead: the failure caveat
1062
+ -------------------------------------------------------------------------- */
1063
+ .spot-callout {
1064
+ --tone: var(--warn);
1065
+ display: flex;
1066
+ align-items: flex-start;
1067
+ gap: 12px;
1068
+ margin: 4px 16px 12px;
1069
+ padding: 12px 14px;
1070
+ border-radius: var(--r-control);
1071
+ border: 1px solid color-mix(in srgb, var(--tone) 32%, transparent);
1072
+ background: color-mix(in srgb, var(--tone) 9%, var(--card));
1073
+ }
1074
+
1075
+ .spot-callout[data-tone="bad"] {
1076
+ --tone: var(--bad);
1077
+ }
1078
+
1079
+ .spot-callout > svg {
1080
+ flex: none;
1081
+ margin-top: 2px;
1082
+ color: var(--tone);
1083
+ }
1084
+
1085
+ .spot-callout-head {
1086
+ font-size: 14px;
1087
+ font-weight: 600;
1088
+ color: var(--ink-1);
1089
+ }
1090
+
1091
+ .spot-callout-head .num {
1092
+ color: var(--tone);
1093
+ }
1094
+
1095
+ .spot-callout-copy {
1096
+ margin: 3px 0 0;
1097
+ font-size: 12.5px;
1098
+ line-height: 1.55;
1099
+ color: var(--ink-2);
1100
+ text-wrap: pretty;
1101
+ }
1102
+
1103
+ /* --------------------------------------------------------------------------
1104
+ Panel titles
1105
+ -------------------------------------------------------------------------- */
1106
+ .spot-panel-title {
1107
+ margin-bottom: 4px;
1108
+ font-size: 12.5px;
1109
+ font-weight: 550;
1110
+ color: var(--ink-1);
1111
+ }
1112
+
1113
+ /* --------------------------------------------------------------------------
1114
+ Recent results
1115
+ -------------------------------------------------------------------------- */
1116
+ .spot-result {
1117
+ display: flex;
1118
+ align-items: center;
1119
+ gap: 12px;
1120
+ min-width: 0;
1121
+ max-width: min(46vw, 620px);
1122
+ }
1123
+
1124
+ .spot-tool {
1125
+ display: grid;
1126
+ place-items: center;
1127
+ width: 28px;
1128
+ height: 28px;
1129
+ flex: none;
1130
+ border-radius: 7px;
1131
+ border: 1px solid var(--line-1);
1132
+ background: var(--raised);
1133
+ color: var(--ink-2);
1134
+ }
1135
+
1136
+ .spot-result-text {
1137
+ gap: 2px;
1138
+ }
1139
+
1140
+ .spot-target {
1141
+ font-family: var(--font-mono);
1142
+ font-size: 12.5px;
1143
+ color: var(--ink-1);
1144
+ }
1145
+
1146
+ .spot-result-meta {
1147
+ gap: 10px;
1148
+ font-size: 11.5px;
1149
+ }
1150
+
1151
+ .spot-shrink {
1152
+ display: inline-flex;
1153
+ flex-direction: column;
1154
+ align-items: flex-end;
1155
+ gap: 5px;
1156
+ }
1157
+
1158
+ .spot-shrink-bar {
1159
+ position: relative;
1160
+ width: 96px;
1161
+ height: 4px;
1162
+ border-radius: 2px;
1163
+ overflow: hidden;
1164
+ background: repeating-linear-gradient(-45deg, var(--line-3) 0 1.5px, transparent 1.5px 4px);
1165
+ }
1166
+
1167
+ .spot-shrink-kept {
1168
+ position: absolute;
1169
+ inset: 0 auto 0 0;
1170
+ min-width: 2px;
1171
+ border-radius: 2px;
1172
+ background: var(--spot-gross);
1173
+ }
1174
+
1175
+ /* A would-be cut: the bar is an outline, nothing was actually removed. */
1176
+ .spot-shrink[data-holdout="true"] .spot-shrink-kept {
1177
+ background: transparent;
1178
+ box-shadow: inset 0 0 0 1px var(--ink-3);
1179
+ }
1180
+
1181
+ .spot-shrink[data-holdout="true"] > .num {
1182
+ color: var(--ink-2);
1183
+ }
1184
+
1185
+ .spot-result-meta .badge {
1186
+ height: 17px;
1187
+ padding: 0 6px;
1188
+ font-size: 10.5px;
1189
+ }
1190
+
1191
+ .spot-would-save {
1192
+ white-space: nowrap;
1193
+ color: var(--ink-2);
1194
+ }
1195
+
1196
+ .spot-kinds {
1197
+ gap: 4px;
1198
+ }
1199
+
1200
+ /* --------------------------------------------------------------------------
1201
+ Recovery drawer
1202
+ -------------------------------------------------------------------------- */
1203
+ .spot-drawer-title {
1204
+ display: -webkit-box;
1205
+ -webkit-box-orient: vertical;
1206
+ -webkit-line-clamp: 2;
1207
+ line-clamp: 2;
1208
+ overflow: hidden;
1209
+ font-family: var(--font-mono);
1210
+ font-size: 13.5px;
1211
+ font-weight: 500;
1212
+ overflow-wrap: anywhere;
1213
+ }
1214
+
1215
+ .spot-drawer-call {
1216
+ color: var(--ink-1);
1217
+ }
1218
+
1219
+ .spot-drawer-subtitle {
1220
+ flex-wrap: wrap;
1221
+ gap: 8px;
1222
+ margin-top: 4px;
1223
+ }
1224
+
1225
+ .spot-drawer-summary {
1226
+ display: grid;
1227
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1228
+ gap: 1px;
1229
+ border: 1px solid var(--line-1);
1230
+ border-radius: var(--r-card);
1231
+ background: var(--line-1);
1232
+ overflow: hidden;
1233
+ }
1234
+
1235
+ .spot-drawer-summary > div {
1236
+ padding: 12px 14px;
1237
+ background: var(--card);
1238
+ }
1239
+
1240
+ .spot-drawer-figure {
1241
+ margin-top: 2px;
1242
+ font-size: 22px;
1243
+ font-weight: 600;
1244
+ letter-spacing: -0.02em;
1245
+ }
1246
+
1247
+ .spot-timeline {
1248
+ display: flex;
1249
+ flex-direction: column;
1250
+ }
1251
+
1252
+ .spot-timeline-item {
1253
+ position: relative;
1254
+ display: grid;
1255
+ grid-template-columns: 24px minmax(0, 1fr);
1256
+ gap: 12px;
1257
+ padding-bottom: 18px;
1258
+ }
1259
+
1260
+ .spot-timeline-item:last-child {
1261
+ padding-bottom: 0;
1262
+ }
1263
+
1264
+ .spot-timeline-item:not(:last-child)::before {
1265
+ content: "";
1266
+ position: absolute;
1267
+ left: 11.5px;
1268
+ top: 26px;
1269
+ bottom: 2px;
1270
+ width: 1px;
1271
+ background: var(--line-2);
1272
+ }
1273
+
1274
+ .spot-timeline-node {
1275
+ display: grid;
1276
+ place-items: center;
1277
+ width: 24px;
1278
+ height: 24px;
1279
+ border-radius: 50%;
1280
+ border: 1px solid var(--line-2);
1281
+ background: var(--raised);
1282
+ color: var(--ink-2);
1283
+ }
1284
+
1285
+ .spot-timeline-item[data-kind="cut"] .spot-timeline-node {
1286
+ --kind: var(--spot-gross);
1287
+ }
1288
+
1289
+ .spot-timeline-item[data-kind="holdout"] .spot-timeline-node {
1290
+ --kind: var(--spot-reference);
1291
+ }
1292
+
1293
+ .spot-timeline-item[data-kind="net"] .spot-timeline-node {
1294
+ --kind: var(--spot-net);
1295
+ background: var(--accent-gradient);
1296
+ border-color: transparent;
1297
+ transform: scale(0.5);
1298
+ }
1299
+
1300
+ .spot-timeline-item:is(
1301
+ [data-kind="cut"],
1302
+ [data-kind="holdout"],
1303
+ [data-kind="artifact"],
1304
+ [data-kind="reread"],
1305
+ [data-kind="rerun"]
1306
+ )
1307
+ .spot-timeline-node {
1308
+ color: var(--kind);
1309
+ border-color: color-mix(in srgb, var(--kind) 40%, transparent);
1310
+ background: color-mix(in srgb, var(--kind) 12%, var(--card));
1311
+ }
1312
+
1313
+ .spot-timeline-body {
1314
+ display: flex;
1315
+ flex-direction: column;
1316
+ gap: 6px;
1317
+ min-width: 0;
1318
+ padding-top: 1px;
1319
+ }
1320
+
1321
+ .spot-timeline-head {
1322
+ gap: 8px;
1323
+ min-height: 22px;
1324
+ }
1325
+
1326
+ .spot-timeline-spacer {
1327
+ flex: 1;
1328
+ }
1329
+
1330
+ .spot-timeline-target {
1331
+ display: block;
1332
+ max-height: 120px;
1333
+ overflow: auto;
1334
+ padding: 8px 10px;
1335
+ border-radius: var(--r-control);
1336
+ border: 1px solid var(--line-1);
1337
+ background: var(--card);
1338
+ font-size: 12px;
1339
+ color: var(--ink-1);
1340
+ white-space: pre-wrap;
1341
+ overflow-wrap: anywhere;
1342
+ }
1343
+
1344
+ /* --------------------------------------------------------------------------
1345
+ Empty state
1346
+ -------------------------------------------------------------------------- */
1347
+ .spot-empty {
1348
+ display: flex;
1349
+ flex-direction: column;
1350
+ align-items: center;
1351
+ gap: 10px;
1352
+ padding: 56px 24px 60px;
1353
+ text-align: center;
1354
+ }
1355
+
1356
+ .spot-empty-icon {
1357
+ display: grid;
1358
+ place-items: center;
1359
+ width: 44px;
1360
+ height: 44px;
1361
+ border-radius: 12px;
1362
+ background: var(--accent-soft);
1363
+ color: var(--accent);
1364
+ }
1365
+
1366
+ .spot-empty-title {
1367
+ font-size: 15px;
1368
+ font-weight: 600;
1369
+ text-wrap: balance;
1370
+ }
1371
+
1372
+ .spot-empty-hint {
1373
+ max-width: 58ch;
1374
+ font-size: 13px;
1375
+ line-height: 1.65;
1376
+ color: var(--ink-2);
1377
+ text-wrap: pretty;
1378
+ }
1379
+
1380
+ .spot-empty-hint code {
1381
+ padding: 1px 6px;
1382
+ border-radius: 5px;
1383
+ border: 1px solid var(--line-1);
1384
+ background: var(--raised);
1385
+ font-size: 12px;
1386
+ color: var(--ink-1);
1387
+ }