@matware/e2e-runner 1.3.1 → 1.5.1

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 (50) hide show
  1. package/.claude-plugin/marketplace.json +4 -4
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/LICENSE +1 -1
  4. package/README.md +491 -225
  5. package/agents/test-creator.md +4 -2
  6. package/agents/test-improver.md +7 -4
  7. package/bin/cli.js +93 -19
  8. package/package.json +4 -3
  9. package/skills/e2e-testing/SKILL.md +5 -3
  10. package/skills/e2e-testing/references/action-types.md +35 -18
  11. package/skills/e2e-testing/references/test-json-format.md +23 -0
  12. package/skills/e2e-testing/references/troubleshooting.md +2 -26
  13. package/src/actions.js +181 -15
  14. package/src/config.js +6 -0
  15. package/src/dashboard.js +185 -9
  16. package/src/db.js +26 -0
  17. package/src/mcp-tools.js +238 -69
  18. package/src/module-analysis.js +247 -0
  19. package/src/module-resolver.js +35 -2
  20. package/src/narrate.js +33 -1
  21. package/src/pool-manager.js +46 -1
  22. package/src/pool.js +177 -20
  23. package/src/runner.js +144 -19
  24. package/src/visual-diff.js +74 -4
  25. package/src/websocket.js +14 -3
  26. package/src/wizard.js +184 -0
  27. package/templates/build-dashboard.js +3 -0
  28. package/templates/dashboard/js/api.js +60 -3
  29. package/templates/dashboard/js/init.js +46 -0
  30. package/templates/dashboard/js/keyboard.js +8 -7
  31. package/templates/dashboard/js/quicksearch.js +277 -0
  32. package/templates/dashboard/js/state.js +61 -7
  33. package/templates/dashboard/js/toast.js +1 -1
  34. package/templates/dashboard/js/utils.js +23 -2
  35. package/templates/dashboard/js/view-live.js +235 -42
  36. package/templates/dashboard/js/view-runs.js +469 -42
  37. package/templates/dashboard/js/view-tests.js +157 -16
  38. package/templates/dashboard/js/view-tools.js +234 -0
  39. package/templates/dashboard/js/view-watch.js +2 -2
  40. package/templates/dashboard/js/websocket.js +33 -3
  41. package/templates/dashboard/styles/base.css +489 -53
  42. package/templates/dashboard/styles/components.css +736 -84
  43. package/templates/dashboard/styles/view-live.css +459 -78
  44. package/templates/dashboard/styles/view-runs.css +826 -177
  45. package/templates/dashboard/styles/view-tests.css +440 -77
  46. package/templates/dashboard/styles/view-tools.css +206 -0
  47. package/templates/dashboard/styles/view-watch.css +198 -41
  48. package/templates/dashboard/template.html +356 -58
  49. package/templates/dashboard.html +5354 -722
  50. package/templates/docker-compose-lightpanda.yml +7 -0
@@ -1,117 +1,769 @@
1
+ /* ═══════════════════════════════════════════════════════════════════
2
+ COMPONENTS — buttons, cards, tables, badges, toasts, modals
3
+ ═══════════════════════════════════════════════════════════════════ */
4
+
1
5
  /* ── Buttons ── */
2
- .btn{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border-radius:var(--r);font-family:var(--mono);font-size:11px;font-weight:500;cursor:pointer;border:1px solid var(--border);background:var(--surface2);color:var(--text);transition:all .15s;white-space:nowrap}
3
- .btn:hover{background:var(--surface3);border-color:var(--border-hi)}
4
- .btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
5
- .btn.primary:hover{background:#2563eb}
6
- .btn.danger{background:var(--red-dim);border-color:rgba(239,68,68,.3);color:var(--red)}
7
- .btn:disabled{opacity:.4;cursor:not-allowed}
8
- .btn.sm{padding:4px 10px;font-size:10px}
6
+ .btn{
7
+ display:inline-flex;align-items:center;gap:6px;
8
+ padding:8px 14px;
9
+ border-radius:var(--r);
10
+ font-family:var(--mono);
11
+ font-size:10px;font-weight:600;
12
+ letter-spacing:.14em;text-transform:uppercase;
13
+ cursor:pointer;
14
+ border:1px solid var(--border);
15
+ background:var(--surface);
16
+ color:var(--text2);
17
+ transition:all .15s ease;
18
+ white-space:nowrap;
19
+ position:relative;
20
+ }
21
+ .btn:hover{background:var(--surface2);border-color:var(--border-hi);color:var(--text)}
22
+ .btn:active{transform:translateY(1px)}
23
+ .btn.primary{
24
+ background:var(--ui-accent);
25
+ border-color:var(--ui-accent);
26
+ color:#06121a;
27
+ text-shadow:none;
28
+ box-shadow:0 0 16px var(--ui-accent-dim);
29
+ }
30
+ .btn.primary:hover{
31
+ filter:brightness(1.08);
32
+ box-shadow:0 0 22px var(--ui-accent-dim);
33
+ }
34
+ .btn.danger{background:var(--crimson-dim);border-color:rgba(255,77,77,.4);color:var(--crimson)}
35
+ .btn.danger:hover{background:rgba(255,77,77,.18);color:var(--crimson)}
36
+ .btn:disabled{opacity:.35;cursor:not-allowed;filter:grayscale(.5)}
37
+ .btn.sm{padding:5px 10px;font-size:9px;letter-spacing:.12em}
9
38
 
10
39
  /* ── Cards ── */
11
- .card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:16px;margin-bottom:16px}
12
- .card-label{font-size:9px;font-weight:600;color:var(--text3);letter-spacing:.1em;text-transform:uppercase;margin-bottom:10px}
40
+ .card{
41
+ background:var(--surface);
42
+ border:1px solid var(--border);
43
+ border-radius:var(--r);
44
+ padding:18px;
45
+ margin-bottom:16px;
46
+ position:relative;
47
+ }
48
+ .card::before{
49
+ content:'';position:absolute;top:0;left:16px;width:22px;height:1px;
50
+ background:var(--phosphor);opacity:.5;
51
+ }
52
+ .card-label{
53
+ font-size:10px;font-weight:700;color:var(--text3);
54
+ letter-spacing:.14em;text-transform:uppercase;
55
+ margin-bottom:12px;
56
+ display:flex;align-items:center;gap:8px;
57
+ }
58
+ .card-label::after{content:'';flex:1;height:1px;background:var(--border)}
13
59
 
14
60
  /* ── Stats Row ── */
15
61
  .stats{display:flex;gap:24px;margin-bottom:20px}
16
62
  .stat-block{text-align:center;min-width:80px}
17
- .stat-val{font-size:26px;font-weight:700}
18
- .stat-lbl{font-size:9px;color:var(--text3);text-transform:uppercase;letter-spacing:.1em;margin-top:2px}
19
- .stat-val.green{color:var(--green)}
20
- .stat-val.red{color:var(--red)}
21
- .stat-val.accent{color:var(--accent)}
22
- .stat-val.purple{color:var(--purple)}
63
+ .stat-val{font-family:var(--display);font-size:34px;font-weight:400;line-height:1;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
64
+ .stat-lbl{font-size:10px;color:var(--text3);text-transform:uppercase;letter-spacing:.14em;margin-top:6px;font-weight:700}
65
+ .stat-val.green{color:var(--phosphor);text-shadow:0 0 14px var(--phosphor-glow)}
66
+ .stat-val.red{color:var(--crimson)}
67
+ .stat-val.accent{color:var(--beacon)}
68
+ .stat-val.purple{color:var(--radio);text-shadow:0 0 14px var(--radio-glow)}
23
69
 
24
70
  /* ── Tables ── */
25
71
  .tbl-wrap{overflow-x:auto}
26
- table{width:100%;border-collapse:collapse;font-size:12px}
27
- th{text-align:left;font-size:9px;font-weight:600;color:var(--text3);letter-spacing:.1em;text-transform:uppercase;padding:8px 12px;border-bottom:1px solid var(--border)}
28
- td{padding:8px 12px;border-bottom:1px solid var(--border)}
29
- tbody tr{cursor:pointer;transition:background .1s}
72
+ table{width:100%;border-collapse:collapse;font-size:11px;font-family:var(--mono)}
73
+ th{
74
+ text-align:left;
75
+ font-size:9.5px;font-weight:700;
76
+ color:var(--text3);
77
+ letter-spacing:.14em;text-transform:uppercase;
78
+ padding:10px 14px;
79
+ border-bottom:1px solid var(--border);
80
+ background:var(--bg-2);
81
+ position:relative;
82
+ }
83
+ td{
84
+ padding:10px 14px;
85
+ border-bottom:1px solid var(--border);
86
+ font-variant-numeric:tabular-nums;
87
+ }
88
+ tbody tr{cursor:pointer;transition:background .12s}
30
89
  tbody tr:hover td{background:var(--surface2)}
31
- tbody tr.selected td{background:var(--accent-dim)}
90
+ tbody tr:hover td:first-child{box-shadow:inset 3px 0 0 var(--border-hi)}
91
+ tbody tr.selected td{
92
+ background:var(--ui-accent-dim);
93
+ color:var(--text);
94
+ box-shadow:inset 3px 0 0 var(--ui-accent);
95
+ }
32
96
 
33
97
  /* ── Badges ── */
34
- .badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:600}
35
- .badge.pass{background:var(--green-dim);color:var(--green)}
36
- .badge.fail{background:var(--red-dim);color:var(--red)}
37
- .badge.flaky{background:var(--amber-dim);color:var(--amber)}
38
- .badge.run{background:var(--purple-dim);color:var(--purple)}
98
+ .badge{
99
+ display:inline-flex;align-items:center;
100
+ padding:3px 9px;border-radius:999px;
101
+ font-size:9px;font-weight:700;
102
+ letter-spacing:.1em;text-transform:uppercase;
103
+ font-family:var(--mono);
104
+ border:1px solid transparent;
105
+ }
106
+ .badge.pass,.badge.passed{background:var(--phosphor-dim);color:var(--phosphor);border-color:rgba(158,242,106,.3)}
107
+ .badge.fail,.badge.failed{background:var(--crimson-dim);color:var(--crimson);border-color:rgba(255,77,77,.35)}
108
+ .badge.flaky{background:var(--amber-dim);color:var(--amber);border-color:rgba(255,179,71,.3)}
109
+ .badge.run,.badge.running{background:var(--purple-dim);color:var(--purple);border-color:rgba(167,139,250,.35);animation:badgePulse 1.6s ease-in-out infinite}
110
+ .badge.idle{background:transparent;color:var(--text3);border-color:var(--border)}
111
+ @keyframes badgePulse{
112
+ 0%,100%{box-shadow:0 0 0 0 rgba(167,139,250,.3)}
113
+ 50%{box-shadow:0 0 0 5px rgba(167,139,250,0)}
114
+ }
115
+
116
+ /* ── Top bar ── */
117
+ .topbar{
118
+ display:grid;align-items:center;
119
+ grid-template-columns:1fr auto 1fr;
120
+ gap:14px;
121
+ padding:9px 22px;
122
+ margin:-22px -22px 18px;
123
+ background:var(--bg-2);
124
+ border-bottom:1px solid var(--border);
125
+ position:sticky;top:0;z-index:20;
126
+ backdrop-filter:blur(8px);
127
+ }
128
+ .topbar-breadcrumb{justify-self:start;min-width:0}
129
+ .topbar-actions{justify-self:end;display:flex;gap:10px;align-items:center}
130
+ .topbar-breadcrumb{
131
+ display:flex;align-items:center;gap:8px;
132
+ font-family:var(--mono);font-size:11px;
133
+ color:var(--text3);letter-spacing:.06em;
134
+ }
135
+ .topbar-section{
136
+ color:var(--text);font-weight:600;
137
+ text-transform:uppercase;letter-spacing:.16em;
138
+ font-size:11px;
139
+ }
140
+ .topbar-sep{color:var(--text3);opacity:.6}
141
+ .topbar-subsection{color:var(--text2);text-transform:uppercase;letter-spacing:.12em;font-size:10px}
142
+ .topbar-actions{display:flex;align-items:center;gap:10px}
143
+ .topbar-live{
144
+ display:inline-flex;align-items:center;gap:7px;
145
+ padding:5px 12px;border-radius:999px;
146
+ cursor:pointer;user-select:none;
147
+ border:1px solid var(--border);
148
+ background:transparent;
149
+ font-family:var(--mono);font-size:10px;font-weight:700;
150
+ letter-spacing:.16em;text-transform:uppercase;
151
+ transition:all .18s;
152
+ }
153
+ .topbar-live:hover{border-color:var(--border-hi);background:var(--surface)}
154
+ .topbar-live-dot{
155
+ width:7px;height:7px;border-radius:50%;
156
+ background:var(--text3);
157
+ }
158
+ .topbar-live-label{color:var(--text2)}
159
+ .topbar-live-count{
160
+ min-width:20px;text-align:center;
161
+ font-variant-numeric:tabular-nums;
162
+ }
163
+ .topbar-live.idle{opacity:.55}
164
+ .topbar-live.running{
165
+ border-color:var(--purple);background:var(--purple-dim);
166
+ }
167
+ .topbar-live.running .topbar-live-dot{
168
+ background:var(--purple);box-shadow:0 0 10px var(--purple);
169
+ animation:livePulse 1.2s ease-in-out infinite;
170
+ }
171
+ .topbar-live.running .topbar-live-label,
172
+ .topbar-live.running .topbar-live-count{color:var(--purple)}
173
+ .topbar-live.failed{border-color:var(--crimson);background:var(--crimson-dim)}
174
+ .topbar-live.failed .topbar-live-dot{background:var(--crimson)}
175
+ .topbar-live.failed .topbar-live-label,
176
+ .topbar-live.failed .topbar-live-count{color:var(--crimson)}
177
+ .topbar-live.passed{border-color:rgba(158,242,106,.3);background:var(--phosphor-dim)}
178
+ .topbar-live.passed .topbar-live-dot{background:var(--phosphor)}
179
+ .topbar-live.passed .topbar-live-label,
180
+ .topbar-live.passed .topbar-live-count{color:var(--phosphor)}
181
+ @keyframes livePulse{
182
+ 0%,100%{transform:scale(1);opacity:1}
183
+ 50%{transform:scale(1.4);opacity:.7}
184
+ }
185
+
186
+ /* ── Network sub-tab table (Investigate › Network) ── */
187
+ .net-row{
188
+ display:grid;
189
+ grid-template-columns:60px 70px 60px 1fr 80px;
190
+ gap:12px;align-items:center;
191
+ padding:8px 14px;
192
+ border-bottom:1px solid var(--border);
193
+ font-family:var(--mono);font-size:11px;
194
+ }
195
+ .net-row:last-child{border-bottom:none}
196
+ .net-row.clickable{cursor:pointer;transition:background .12s}
197
+ .net-row.clickable:hover{background:var(--surface2)}
198
+ .net-row.net-head{
199
+ background:var(--bg-2);font-size:9px;font-weight:700;
200
+ color:var(--text3);text-transform:uppercase;letter-spacing:.18em;
201
+ padding:10px 14px;
202
+ }
203
+ .net-col-run{color:var(--text3)}
204
+ .net-col-method{font-weight:700;text-transform:uppercase;font-size:10px}
205
+ .net-col-method.m-get{color:var(--phosphor)}
206
+ .net-col-method.m-post{color:var(--amber)}
207
+ .net-col-method.m-put,.net-col-method.m-patch{color:var(--radio)}
208
+ .net-col-method.m-delete{color:var(--crimson)}
209
+ .net-col-status{font-weight:700;font-variant-numeric:tabular-nums}
210
+ .net-col-status.st-s2xx{color:var(--phosphor)}
211
+ .net-col-status.st-s3xx{color:var(--beacon)}
212
+ .net-col-status.st-s4xx{color:var(--amber)}
213
+ .net-col-status.st-s5xx{color:var(--crimson)}
214
+ .net-col-url{color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
215
+ .net-col-dur{color:var(--text3);text-align:right;font-variant-numeric:tabular-nums}
39
216
 
40
217
  /* ── Empty ── */
41
- .empty{text-align:center;padding:48px 24px;color:var(--text3)}
42
- .empty-icon{font-size:36px;margin-bottom:8px;opacity:.5}
218
+ .empty{
219
+ text-align:center;padding:64px 24px;color:var(--text2);
220
+ font-family:var(--mono);font-size:12px;
221
+ border:1px dashed var(--border-hi);
222
+ border-radius:var(--r);
223
+ background:
224
+ repeating-linear-gradient(135deg,transparent 0 18px,rgba(168,245,122,.025) 18px 19px),
225
+ var(--surface);
226
+ }
227
+ .empty-icon{
228
+ font-size:44px;margin-bottom:14px;opacity:.6;
229
+ color:var(--phosphor);
230
+ display:block;
231
+ text-shadow:0 0 18px var(--phosphor-glow);
232
+ }
233
+ .empty p{letter-spacing:.06em;line-height:1.6}
234
+ .empty code{color:var(--phosphor);background:var(--bg-2);padding:1px 6px;border-radius:2px;border:1px solid var(--border)}
43
235
 
44
- /* ── Modal ── */
45
- .modal{position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:200;display:none;align-items:center;justify-content:center;padding:24px;cursor:pointer}
236
+ /* ── Modal (image lightbox) ── */
237
+ .modal{
238
+ position:fixed;inset:0;
239
+ background:rgba(10,11,8,.92);
240
+ backdrop-filter:blur(6px);
241
+ z-index:200;display:none;
242
+ align-items:center;justify-content:center;padding:32px;cursor:pointer;
243
+ }
46
244
  .modal.open{display:flex}
47
- .modal img{max-width:100%;max-height:90vh;border-radius:var(--r);cursor:default}
48
-
49
- /* ── Toast Notifications ── */
50
- .toast-container{position:fixed;bottom:24px;right:24px;z-index:300;display:flex;flex-direction:column-reverse;gap:8px;pointer-events:none}
51
- .toast{padding:10px 16px;border-radius:var(--r);font-family:var(--mono);font-size:11px;font-weight:500;color:#fff;pointer-events:auto;animation:toastIn .3s ease;min-width:200px;max-width:380px;box-shadow:0 8px 24px rgba(0,0,0,.4);display:flex;align-items:center;gap:8px}
52
- .toast.success{background:var(--green);border:1px solid rgba(255,255,255,.15)}
53
- .toast.error{background:var(--red);border:1px solid rgba(255,255,255,.15)}
54
- .toast.info{background:var(--accent);border:1px solid rgba(255,255,255,.15)}
55
- .toast.fade-out{animation:toastOut .3s ease forwards}
56
- @keyframes toastIn{from{opacity:0;transform:translateX(24px)}to{opacity:1;transform:translateX(0)}}
57
- @keyframes toastOut{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(24px)}}
245
+ .modal img{
246
+ max-width:100%;max-height:90vh;
247
+ border:1px solid var(--border);border-radius:var(--r);
248
+ cursor:default;
249
+ box-shadow:0 0 0 1px rgba(158,242,106,.12),0 40px 80px rgba(0,0,0,.6);
250
+ }
251
+ .modal pre{
252
+ max-width:min(900px,100%);max-height:90vh;overflow:auto;
253
+ margin:0;padding:20px 24px;
254
+ background:var(--bg-2);
255
+ border:1px solid var(--border);border-radius:var(--r);
256
+ font-family:var(--mono);font-size:12px;line-height:1.6;
257
+ color:var(--text);cursor:text;user-select:text;
258
+ box-shadow:0 0 0 1px rgba(158,242,106,.12),0 40px 80px rgba(0,0,0,.6);
259
+ }
260
+ .modal pre[hidden],.modal img[hidden]{display:none}
261
+
262
+ /* ── JSON syntax highlighting (modal + network body panels) ── */
263
+ .jn-key{color:var(--beacon)}
264
+ .jn-str{color:var(--amber)}
265
+ .jn-num{color:var(--phosphor)}
266
+ .jn-bool{color:var(--red);font-weight:600}
267
+ .jn-null{color:var(--red);opacity:.65;font-style:italic}
268
+
269
+ /* ── Toasts ── */
270
+ .toast-container{
271
+ position:fixed;bottom:24px;right:24px;z-index:300;
272
+ display:flex;flex-direction:column-reverse;gap:8px;pointer-events:none;
273
+ }
274
+ .toast{
275
+ padding:10px 14px 10px 16px;
276
+ border-radius:var(--r);
277
+ font-family:var(--mono);
278
+ font-size:11px;font-weight:500;
279
+ color:#0b0c09;
280
+ pointer-events:auto;
281
+ animation:toastIn .28s cubic-bezier(.2,.9,.3,1.2);
282
+ min-width:240px;max-width:380px;
283
+ box-shadow:0 0 0 1px rgba(0,0,0,.4),0 12px 30px rgba(0,0,0,.45);
284
+ display:flex;align-items:center;gap:10px;
285
+ position:relative;overflow:hidden;
286
+ letter-spacing:.03em;
287
+ }
288
+ .toast::before{
289
+ content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
290
+ background:currentColor;opacity:.7;
291
+ }
292
+ .toast.success{background:var(--phosphor);color:#0b0c09}
293
+ .toast.error{background:var(--crimson);color:#fff}
294
+ .toast.info{background:var(--beacon);color:#0b0c09}
295
+ .toast.fade-out{animation:toastOut .25s ease forwards}
296
+ @keyframes toastIn{
297
+ from{opacity:0;transform:translateX(28px) scale(.96)}
298
+ to{opacity:1;transform:translateX(0) scale(1)}
299
+ }
300
+ @keyframes toastOut{
301
+ from{opacity:1;transform:translateX(0)}
302
+ to{opacity:0;transform:translateX(28px)}
303
+ }
58
304
  .toast.clickable{cursor:pointer}
59
- .toast.clickable:hover{filter:brightness(1.1)}
305
+ .toast.clickable:hover{filter:brightness(1.08)}
60
306
 
61
307
  /* ── Copy Button ── */
62
- .copy-btn{display:inline-flex;align-items:center;gap:3px;padding:2px 8px;border-radius:4px;font-size:9px;font-family:var(--mono);font-weight:500;color:var(--text3);background:transparent;border:1px solid transparent;cursor:pointer;transition:all .15s;user-select:none;white-space:nowrap;flex-shrink:0}
63
- .copy-btn:hover{color:var(--accent);border-color:var(--accent);background:var(--accent-dim)}
64
- .copy-btn.copied{color:var(--green);border-color:var(--green);background:var(--green-dim)}
65
-
66
- /* ── Screenshot Hash Badge ── */
67
- .ss-hash{display:inline-flex;align-items:center;gap:4px;padding:2px 7px;border-radius:10px;font-family:var(--mono);font-size:9px;font-weight:500;background:var(--surface3);border:1px solid var(--border);color:var(--text2);cursor:pointer;transition:all .15s;user-select:none;white-space:nowrap;vertical-align:middle}
68
- .ss-hash:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-dim)}
69
- .ss-hash.copied{border-color:var(--green);color:var(--green);background:var(--green-dim)}
308
+ .copy-btn{
309
+ display:inline-flex;align-items:center;gap:3px;
310
+ padding:2px 8px;border-radius:2px;
311
+ font-size:9px;font-family:var(--mono);font-weight:600;
312
+ letter-spacing:.1em;text-transform:uppercase;
313
+ color:var(--text3);background:transparent;
314
+ border:1px solid transparent;
315
+ cursor:pointer;transition:all .15s;user-select:none;white-space:nowrap;flex-shrink:0;
316
+ }
317
+ .copy-btn:hover{color:var(--beacon);border-color:var(--beacon);background:var(--beacon-dim)}
318
+ .copy-btn.copied{color:var(--phosphor);border-color:var(--phosphor);background:var(--phosphor-dim)}
319
+
320
+ /* ── Screenshot hash badge ── */
321
+ .ss-hash{
322
+ display:inline-flex;align-items:center;gap:4px;
323
+ padding:2px 8px;border-radius:999px;
324
+ font-family:var(--mono);font-size:9px;font-weight:500;
325
+ letter-spacing:.04em;
326
+ background:var(--surface3);
327
+ border:1px solid var(--border);
328
+ color:var(--text2);cursor:pointer;
329
+ transition:all .15s;user-select:none;white-space:nowrap;vertical-align:middle;
330
+ }
331
+ .ss-hash:hover{border-color:var(--beacon);color:var(--beacon);background:var(--beacon-dim)}
332
+ .ss-hash.copied{border-color:var(--phosphor);color:var(--phosphor);background:var(--phosphor-dim)}
70
333
  .ss-hash .ss-icon{font-size:10px;line-height:1}
71
334
 
72
- /* ── Trigger Source Badges ── */
73
- .trigger-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:600;font-family:var(--mono);white-space:nowrap}
74
- .trigger-badge.src-dashboard{background:rgba(127,140,162,.10);color:var(--text2)}
75
- .trigger-badge.src-mcp{background:var(--purple-dim);color:var(--purple)}
76
- .trigger-badge.src-cli{background:var(--accent-dim);color:var(--accent)}
77
- .trigger-badge.src-unknown{background:rgba(70,75,98,.15);color:var(--text3)}
78
- .trigger-badge .trig-icon{font-size:11px;line-height:1}
79
-
80
- /* ── Driver Badges ── */
81
- .driver-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:600;font-family:var(--mono);white-space:nowrap}
82
- .driver-badge.drv-browserless{background:var(--accent-dim)}
83
- .driver-badge.drv-cdp{background:var(--purple-dim)}
84
- .driver-badge.drv-steel{background:var(--amber-dim)}
85
- .driver-badge .drv-icon{font-size:11px;line-height:1}
335
+ /* ── Trigger & Driver Badges ── */
336
+ .trigger-badge,.driver-badge{
337
+ display:inline-flex;align-items:center;gap:4px;
338
+ padding:2px 8px;border-radius:999px;
339
+ font-size:9px;font-weight:700;font-family:var(--mono);
340
+ letter-spacing:.1em;text-transform:uppercase;
341
+ white-space:nowrap;
342
+ border:1px solid transparent;
343
+ }
344
+ .trigger-badge.src-dashboard{background:rgba(150,144,119,.1);color:var(--text2);border-color:var(--border)}
345
+ .trigger-badge.src-mcp{background:var(--radio-dim);color:var(--radio);border-color:rgba(255,45,141,.35)}
346
+ .trigger-badge.src-cli{background:var(--beacon-dim);color:var(--beacon);border-color:rgba(125,211,252,.35)}
347
+ .trigger-badge.src-unknown{background:rgba(91,87,68,.15);color:var(--text3)}
348
+ .trigger-badge .trig-icon{font-size:10px;line-height:1}
349
+
350
+ .driver-badge.drv-browserless{background:var(--beacon-dim);color:var(--beacon);border-color:rgba(125,211,252,.3)}
351
+ .driver-badge.drv-cdp{background:var(--radio-dim);color:var(--radio);border-color:rgba(255,45,141,.3)}
352
+ .driver-badge.drv-steel{background:var(--amber-dim);color:var(--amber);border-color:rgba(255,179,71,.3)}
353
+ .driver-badge .drv-icon{font-size:10px;line-height:1}
86
354
 
87
355
  /* ── Filter Bar ── */
88
- .filter-bar{display:flex;align-items:center;gap:8px;margin-bottom:16px;flex-wrap:wrap}
89
- .filter-btn{padding:5px 12px;border-radius:var(--r);border:1px solid var(--border);background:var(--surface2);color:var(--text2);font-family:var(--mono);font-size:11px;cursor:pointer;transition:all .15s}
90
- .filter-btn:hover{background:var(--surface3);border-color:var(--border-hi)}
91
- .filter-btn.active{background:var(--accent-dim);border-color:var(--accent);color:var(--accent)}
92
- .filter-bar input{padding:5px 10px;border-radius:var(--r);border:1px solid var(--border);background:var(--surface2);color:var(--text);font-family:var(--mono);font-size:11px;max-width:200px}
93
- .filter-bar input:focus{outline:none;border-color:var(--accent)}
94
- .filter-bar input::placeholder{color:var(--text3)}
356
+ .filter-bar{
357
+ display:flex;align-items:center;gap:6px;
358
+ margin-bottom:16px;flex-wrap:wrap;
359
+ padding:8px 10px;
360
+ background:var(--bg-2);
361
+ border:1px solid var(--border);
362
+ border-radius:var(--r);
363
+ }
364
+ .filter-btn{
365
+ padding:5px 12px;border-radius:var(--r);
366
+ border:1px solid var(--border);
367
+ background:transparent;
368
+ color:var(--text2);font-family:var(--mono);
369
+ font-size:10px;font-weight:600;
370
+ letter-spacing:.1em;text-transform:uppercase;
371
+ cursor:pointer;transition:all .15s;
372
+ }
373
+ .filter-btn:hover{background:var(--surface2);border-color:var(--border-hi);color:var(--text)}
374
+ .filter-btn.active{
375
+ background:var(--ui-accent-dim);
376
+ border-color:var(--ui-accent);
377
+ color:var(--ui-accent);
378
+ }
379
+ .filter-bar input{
380
+ padding:6px 12px;border-radius:var(--r);
381
+ border:1px solid var(--border);
382
+ background:var(--surface);
383
+ color:var(--text);
384
+ font-family:var(--mono);font-size:11px;
385
+ max-width:220px;
386
+ margin-left:auto;
387
+ }
388
+ .filter-bar input:focus{outline:none;border-color:var(--ui-accent);box-shadow:0 0 0 1px var(--ui-accent-dim)}
389
+ .filter-bar input::placeholder{color:var(--text3);letter-spacing:.04em}
95
390
 
96
391
  /* ── Inner Tabs ── */
97
- .tab-bar{display:flex;gap:0;border-bottom:1px solid var(--border);margin-bottom:20px}
98
- .tab-btn{padding:8px 16px;font-family:var(--mono);font-size:11px;font-weight:500;color:var(--text3);cursor:pointer;border:none;background:transparent;border-bottom:2px solid transparent;transition:all .15s}
99
- .tab-btn:hover{color:var(--text2);background:var(--surface2)}
100
- .tab-btn.active{color:var(--accent);border-bottom-color:var(--accent)}
392
+ .tab-bar{
393
+ display:flex;gap:0;
394
+ border-bottom:1px solid var(--border);
395
+ margin-bottom:22px;
396
+ position:relative;
397
+ }
398
+ .tab-btn{
399
+ padding:10px 18px;
400
+ font-family:var(--mono);
401
+ font-size:10px;font-weight:700;
402
+ letter-spacing:.18em;text-transform:uppercase;
403
+ color:var(--text2);cursor:pointer;
404
+ border:none;background:transparent;
405
+ border-bottom:2px solid transparent;
406
+ transition:color .15s,border-color .15s,background .15s;
407
+ position:relative;
408
+ }
409
+ .tab-btn:hover{color:var(--text);background:var(--surface2)}
410
+ .tab-btn.active{
411
+ color:var(--ui-accent);
412
+ border-bottom-color:var(--ui-accent);
413
+ }
414
+ .tab-btn.active::before{
415
+ content:'▸';position:absolute;left:6px;top:50%;transform:translateY(-50%);
416
+ font-size:9px;color:var(--ui-accent);
417
+ }
101
418
  .tab-pane{display:none}
102
- .tab-pane.active{display:block}
419
+ .tab-pane.active{display:block;animation:paneIn .25s ease}
420
+ @keyframes paneIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
103
421
 
104
422
  /* ── Keyboard Shortcuts Modal ── */
105
- .kb-modal{position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:250;display:none;align-items:center;justify-content:center;padding:24px}
423
+ .kb-modal{
424
+ position:fixed;inset:0;
425
+ background:rgba(10,11,8,.9);
426
+ backdrop-filter:blur(6px);
427
+ z-index:250;display:none;
428
+ align-items:center;justify-content:center;padding:24px;
429
+ }
106
430
  .kb-modal.open{display:flex}
107
- .kb-modal-content{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:24px;max-width:420px;width:100%;max-height:80vh;overflow-y:auto}
108
- .kb-modal-content h2{font-family:var(--sans);font-size:16px;font-weight:700;margin-bottom:16px;color:var(--text)}
109
- .kb-row{display:flex;align-items:center;justify-content:space-between;padding:6px 0;border-bottom:1px solid var(--border)}
431
+ .kb-modal-content{
432
+ background:var(--surface);
433
+ border:1px solid var(--border);
434
+ border-radius:var(--r);
435
+ padding:28px 28px 22px;
436
+ max-width:460px;width:100%;max-height:80vh;overflow-y:auto;
437
+ position:relative;
438
+ box-shadow:0 0 0 1px rgba(158,242,106,.12),0 40px 80px rgba(0,0,0,.6);
439
+ }
440
+ .kb-modal-content::before{
441
+ content:'KBD · HELP';
442
+ position:absolute;top:-8px;left:20px;
443
+ background:var(--surface);padding:0 8px;
444
+ font-family:var(--mono);font-size:9px;
445
+ letter-spacing:.28em;color:var(--phosphor);font-weight:700;
446
+ }
447
+ .kb-modal-content h2{
448
+ font-family:var(--display);
449
+ font-size:28px;font-weight:400;
450
+ margin-bottom:22px;color:var(--text);letter-spacing:-.01em;
451
+ }
452
+ .kb-row{
453
+ display:flex;align-items:center;justify-content:space-between;
454
+ padding:8px 0;
455
+ border-bottom:1px dashed var(--border);
456
+ }
110
457
  .kb-row:last-child{border-bottom:none}
111
- .kb-key{display:inline-flex;align-items:center;justify-content:center;min-width:24px;padding:2px 8px;border-radius:4px;background:var(--surface3);border:1px solid var(--border);font-family:var(--mono);font-size:11px;font-weight:600;color:var(--accent)}
112
- .kb-desc{font-size:12px;color:var(--text2)}
458
+ .kb-key{
459
+ display:inline-flex;align-items:center;justify-content:center;
460
+ min-width:28px;padding:3px 9px;
461
+ border-radius:var(--r);
462
+ background:var(--bg);
463
+ border:1px solid var(--border-hi);
464
+ font-family:var(--mono);font-size:10px;font-weight:700;
465
+ color:var(--phosphor);
466
+ box-shadow:inset 0 -2px 0 rgba(0,0,0,.3);
467
+ letter-spacing:.08em;
468
+ }
469
+ .kb-desc{font-size:11px;color:var(--text2);letter-spacing:.04em}
113
470
 
114
471
  /* ── Serial / Pool Badges ── */
115
- .serial-badge{display:inline-flex;align-items:center;gap:3px;padding:1px 6px;border-radius:8px;font-size:9px;font-weight:600;background:var(--amber-dim);color:var(--amber);vertical-align:middle;margin-left:4px}
116
- .pool-badge{display:inline-flex;align-items:center;gap:3px;padding:1px 6px;border-radius:8px;font-size:9px;font-weight:600;background:rgba(99,102,241,.15);color:#818cf8;vertical-align:middle;margin-left:4px;font-family:var(--mono);letter-spacing:-.3px}
117
- .pool-badge::before{content:'\1F517';font-size:8px}
472
+ .serial-badge{
473
+ display:inline-flex;align-items:center;gap:3px;
474
+ padding:1px 7px;border-radius:999px;
475
+ font-size:9.5px;font-weight:700;
476
+ letter-spacing:.12em;text-transform:uppercase;
477
+ background:var(--amber-dim);color:var(--amber);
478
+ border:1px solid rgba(255,179,71,.3);
479
+ vertical-align:middle;margin-left:4px;
480
+ }
481
+ .pool-badge{
482
+ display:inline-flex;align-items:center;gap:3px;
483
+ padding:1px 7px;border-radius:999px;
484
+ font-size:9.5px;font-weight:700;
485
+ letter-spacing:.06em;
486
+ background:rgba(125,211,252,.12);color:var(--beacon);
487
+ border:1px solid rgba(125,211,252,.3);
488
+ vertical-align:middle;margin-left:4px;
489
+ font-family:var(--mono);
490
+ }
491
+ .pool-badge::before{content:'◈';font-size:7px;margin-right:1px}
492
+
493
+ /* ── Theme toggle ─────────────────────────────────────────────── */
494
+ .theme-toggle{
495
+ margin:10px 12px 14px;
496
+ display:flex;align-items:center;gap:8px;
497
+ padding:7px 10px;
498
+ background:var(--surface2);
499
+ border:1px solid var(--border);
500
+ border-radius:var(--r-2);
501
+ color:var(--text2);
502
+ font-family:var(--mono);
503
+ font-size:10px;letter-spacing:.06em;text-transform:uppercase;
504
+ cursor:pointer;
505
+ transition:background .15s,color .15s,border-color .15s;
506
+ }
507
+ .theme-toggle:hover{background:var(--surface3);color:var(--text);border-color:var(--border-hi)}
508
+ .theme-toggle-icon{font-size:13px;line-height:1;display:none}
509
+ html[data-theme="dark"] .theme-toggle-icon[data-theme-icon="dark"]{display:inline;color:var(--amber)}
510
+ html[data-theme="light"] .theme-toggle-icon[data-theme-icon="light"]{display:inline;color:var(--beacon)}
511
+ .theme-toggle-label{flex:1;text-align:left}
512
+
513
+ /* ── Screenshot Replay Player ─────────────────────────────────── */
514
+ .replay-modal{
515
+ position:fixed;inset:0;z-index:1100;
516
+ display:none;flex-direction:column;
517
+ background:rgba(0,0,0,.92);
518
+ backdrop-filter:blur(4px);
519
+ }
520
+ .replay-modal.open{display:flex}
521
+ .replay-stage{
522
+ flex:1;min-height:0;
523
+ display:flex;align-items:center;justify-content:center;
524
+ padding:24px;position:relative;
525
+ }
526
+ .replay-stage img{
527
+ max-width:100%;max-height:100%;
528
+ object-fit:contain;
529
+ box-shadow:0 8px 40px rgba(0,0,0,.6);
530
+ border:1px solid rgba(255,255,255,.08);
531
+ border-radius:4px;
532
+ }
533
+ .replay-stage img:not([src]),
534
+ .replay-stage img[src=""]{display:none}
535
+ .replay-empty{
536
+ display:none;color:var(--text3);font-family:var(--mono);font-size:11px;
537
+ letter-spacing:.08em;text-transform:uppercase;
538
+ padding:60px;border:1px dashed rgba(255,255,255,.18);border-radius:4px;
539
+ }
540
+ .replay-modal.empty .replay-empty{display:block}
541
+ .replay-modal.empty .replay-stage img{display:none}
542
+ .replay-info{
543
+ background:rgba(0,0,0,.7);
544
+ border-top:1px solid rgba(255,255,255,.08);
545
+ padding:14px 20px 18px;
546
+ font-family:var(--mono);
547
+ }
548
+ .replay-step-line{
549
+ display:flex;align-items:baseline;gap:12px;
550
+ color:var(--text);font-size:12px;
551
+ margin-bottom:10px;
552
+ }
553
+ .replay-step-num{
554
+ font-weight:600;color:var(--text2);
555
+ letter-spacing:.06em;font-variant-numeric:tabular-nums;
556
+ min-width:60px;
557
+ }
558
+ .replay-step-type{
559
+ padding:2px 8px;background:rgba(255,255,255,.08);
560
+ border-radius:3px;font-size:10px;letter-spacing:.06em;
561
+ text-transform:uppercase;color:var(--beacon);
562
+ }
563
+ .replay-step-narr{flex:1;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
564
+ .replay-progress{
565
+ height:3px;background:rgba(255,255,255,.08);
566
+ border-radius:2px;overflow:hidden;margin-bottom:12px;
567
+ }
568
+ .replay-progress-fill{
569
+ height:100%;background:var(--beacon);
570
+ width:0%;transition:width .15s linear;
571
+ }
572
+ .replay-controls{
573
+ display:flex;align-items:center;gap:8px;
574
+ }
575
+ .replay-btn{
576
+ background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.12);
577
+ color:var(--text);
578
+ padding:7px 12px;border-radius:3px;cursor:pointer;
579
+ font-family:var(--mono);font-size:11px;
580
+ transition:background .15s,border-color .15s;
581
+ }
582
+ .replay-btn:hover{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.24)}
583
+ .replay-btn.replay-play{min-width:48px;font-size:13px}
584
+ .replay-speed-group{
585
+ display:flex;align-items:center;gap:4px;margin-left:8px;
586
+ padding-left:12px;border-left:1px solid rgba(255,255,255,.1);
587
+ }
588
+ .replay-label{
589
+ font-size:10px;letter-spacing:.08em;text-transform:uppercase;
590
+ color:var(--text3);margin-right:4px;
591
+ }
592
+ .replay-speed-btn{
593
+ background:transparent;border:1px solid rgba(255,255,255,.12);
594
+ color:var(--text2);
595
+ padding:5px 9px;border-radius:3px;cursor:pointer;
596
+ font-family:var(--mono);font-size:10px;
597
+ transition:background .15s,color .15s,border-color .15s;
598
+ }
599
+ .replay-speed-btn:hover{color:var(--text);border-color:rgba(255,255,255,.24)}
600
+ .replay-speed-btn.active{
601
+ background:var(--beacon);color:var(--bg);border-color:var(--beacon);
602
+ font-weight:600;
603
+ }
604
+ .replay-spacer{flex:1}
605
+ .replay-close{
606
+ background:transparent;border:none;color:var(--text2);
607
+ font-size:24px;cursor:pointer;padding:0 8px;line-height:1;
608
+ }
609
+ .replay-close:hover{color:var(--text)}
610
+ /* Storyline header play button */
611
+ .rd-replay-btn{
612
+ background:rgba(255,255,255,.05);border:1px solid var(--border);
613
+ color:var(--text);
614
+ padding:4px 10px;border-radius:3px;cursor:pointer;
615
+ font-family:var(--mono);font-size:10px;letter-spacing:.06em;
616
+ text-transform:uppercase;
617
+ margin-left:8px;
618
+ transition:background .15s,color .15s,border-color .15s;
619
+ }
620
+ .rd-replay-btn:hover{background:var(--beacon);color:var(--bg);border-color:var(--beacon)}
621
+
622
+ /* ─── Quick Search trigger in topbar ───────────────────────────── */
623
+ .topbar-search-trigger{
624
+ display:inline-flex;align-items:center;gap:10px;
625
+ padding:5px 10px 5px 12px;
626
+ background:var(--surface);
627
+ border:1px solid var(--border);
628
+ border-radius:var(--r);
629
+ color:var(--text2);
630
+ font-family:var(--mono);font-size:10px;
631
+ cursor:pointer;letter-spacing:.06em;
632
+ min-width:200px;
633
+ transition:border-color .15s,background .15s,color .15s;
634
+ }
635
+ .topbar-search-trigger:hover{
636
+ background:var(--surface2);border-color:var(--border-hi);color:var(--text);
637
+ }
638
+ .topbar-search-icon{font-size:11px;opacity:.75}
639
+ .topbar-search-label{flex:1;text-align:left;color:var(--text3);letter-spacing:.04em}
640
+ .topbar-search-kbd{
641
+ font-size:9px;font-weight:700;
642
+ padding:2px 6px;border-radius:2px;
643
+ background:var(--bg-2);border:1px solid var(--border);
644
+ color:var(--text3);letter-spacing:.04em;
645
+ }
646
+ @media(max-width:1100px){
647
+ .topbar-search-label,.topbar-search-kbd{display:none}
648
+ .topbar-search-trigger{min-width:0;padding:5px 10px}
649
+ }
650
+
651
+ /* ─── Quick Search modal ───────────────────────────────────────── */
652
+ .qs-modal{
653
+ position:fixed;inset:0;z-index:1200;
654
+ display:none;align-items:flex-start;justify-content:center;
655
+ padding-top:11vh;
656
+ background:rgba(0,0,0,.55);
657
+ backdrop-filter:blur(3px);
658
+ animation:qs-fade .12s ease-out;
659
+ }
660
+ .qs-modal.open{display:flex}
661
+ @keyframes qs-fade{from{opacity:0}to{opacity:1}}
662
+ .qs-panel{
663
+ width:min(720px,90vw);
664
+ background:var(--surface);
665
+ border:1px solid var(--border-hi);
666
+ border-radius:var(--r-2);
667
+ box-shadow:0 24px 60px rgba(0,0,0,.45),0 0 0 1px rgba(158,242,106,.05);
668
+ overflow:hidden;
669
+ display:flex;flex-direction:column;
670
+ max-height:70vh;
671
+ position:relative;
672
+ }
673
+ .qs-panel::before{
674
+ content:'QUICK·SEARCH';
675
+ position:absolute;top:-8px;left:18px;
676
+ background:var(--bg);padding:0 8px;
677
+ font-family:var(--mono);font-size:8px;font-weight:700;
678
+ letter-spacing:.32em;color:var(--phosphor);
679
+ }
680
+ .qs-input-row{
681
+ display:flex;align-items:center;gap:12px;
682
+ padding:18px 18px 14px;
683
+ border-bottom:1px solid var(--border);
684
+ }
685
+ .qs-input-icon{font-size:14px;color:var(--text3)}
686
+ .qs-input-row input{
687
+ flex:1;
688
+ background:transparent;border:none;outline:none;
689
+ font-family:var(--mono);font-size:14px;
690
+ color:var(--text);
691
+ padding:2px 0;
692
+ letter-spacing:.01em;
693
+ }
694
+ .qs-input-row input::placeholder{color:var(--text3);font-style:italic}
695
+ .qs-input-hint{
696
+ font-family:var(--mono);font-size:9px;
697
+ color:var(--text3);letter-spacing:.06em;
698
+ white-space:nowrap;
699
+ }
700
+ .qs-results{
701
+ flex:1;overflow-y:auto;
702
+ padding:6px 0;
703
+ }
704
+ .qs-group-label{
705
+ font-family:var(--mono);font-size:8.5px;font-weight:700;
706
+ color:var(--text3);letter-spacing:.16em;text-transform:uppercase;
707
+ padding:10px 18px 6px;
708
+ display:flex;align-items:center;gap:8px;
709
+ }
710
+ .qs-group-label::after{
711
+ content:'';flex:1;height:1px;background:var(--border);
712
+ }
713
+ .qs-item{
714
+ display:flex;align-items:center;gap:12px;
715
+ padding:9px 18px;
716
+ cursor:pointer;
717
+ border-left:2px solid transparent;
718
+ transition:background .1s,border-color .1s;
719
+ }
720
+ .qs-item:hover,.qs-item.active{
721
+ background:var(--surface2);
722
+ border-left-color:var(--ui-accent);
723
+ }
724
+ .qs-item-kind{
725
+ font-family:var(--mono);font-size:9px;font-weight:700;
726
+ text-transform:uppercase;letter-spacing:.12em;
727
+ padding:2px 7px;border-radius:2px;
728
+ background:var(--surface3);color:var(--text2);
729
+ min-width:60px;text-align:center;
730
+ }
731
+ .qs-item-kind.suite{background:var(--beacon-dim);color:var(--beacon)}
732
+ .qs-item-kind.module{background:var(--phosphor-dim);color:var(--phosphor)}
733
+ .qs-item-kind.test{background:var(--radio-dim);color:var(--radio)}
734
+ .qs-item-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
735
+ .qs-item-name{
736
+ font-family:var(--mono);font-size:12px;
737
+ color:var(--text);
738
+ white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
739
+ }
740
+ .qs-item-name mark{
741
+ background:transparent;color:var(--ui-accent);font-weight:600;
742
+ }
743
+ .qs-item-sub{
744
+ font-family:var(--mono);font-size:10px;
745
+ color:var(--text3);
746
+ white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
747
+ letter-spacing:.02em;
748
+ }
749
+ .qs-item-meta{
750
+ font-family:var(--mono);font-size:9px;
751
+ color:var(--text3);letter-spacing:.04em;
752
+ white-space:nowrap;
753
+ }
754
+ .qs-empty{
755
+ padding:32px;text-align:center;
756
+ font-family:var(--mono);font-size:11px;
757
+ color:var(--text3);letter-spacing:.04em;
758
+ }
759
+ .qs-modal:not(.has-results) .qs-empty{display:block}
760
+ .qs-modal.has-results .qs-empty{display:none}
761
+
762
+ /* ─── Quick search flash highlight on jump ──────────────────────── */
763
+ .qs-flash{
764
+ animation:qs-flash 1.4s ease-out;
765
+ }
766
+ @keyframes qs-flash{
767
+ 0%{box-shadow:0 0 0 2px var(--ui-accent),0 0 24px var(--ui-accent-dim)}
768
+ 100%{box-shadow:0 0 0 0 transparent,0 0 0 transparent}
769
+ }