@matware/e2e-runner 1.3.1 → 1.5.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 (47) hide show
  1. package/.claude-plugin/marketplace.json +4 -4
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/README.md +110 -21
  4. package/agents/test-creator.md +4 -2
  5. package/agents/test-improver.md +5 -3
  6. package/bin/cli.js +80 -17
  7. package/package.json +3 -2
  8. package/skills/e2e-testing/SKILL.md +3 -2
  9. package/skills/e2e-testing/references/action-types.md +22 -4
  10. package/skills/e2e-testing/references/test-json-format.md +23 -0
  11. package/src/actions.js +170 -14
  12. package/src/config.js +6 -0
  13. package/src/dashboard.js +135 -4
  14. package/src/db.js +11 -0
  15. package/src/mcp-tools.js +8 -2
  16. package/src/module-analysis.js +247 -0
  17. package/src/module-resolver.js +35 -2
  18. package/src/narrate.js +14 -1
  19. package/src/pool-manager.js +46 -1
  20. package/src/pool.js +177 -20
  21. package/src/runner.js +77 -10
  22. package/src/visual-diff.js +69 -0
  23. package/src/websocket.js +14 -3
  24. package/src/wizard.js +184 -0
  25. package/templates/build-dashboard.js +3 -0
  26. package/templates/dashboard/js/api.js +60 -3
  27. package/templates/dashboard/js/init.js +46 -0
  28. package/templates/dashboard/js/keyboard.js +8 -7
  29. package/templates/dashboard/js/quicksearch.js +277 -0
  30. package/templates/dashboard/js/state.js +61 -7
  31. package/templates/dashboard/js/toast.js +1 -1
  32. package/templates/dashboard/js/view-live.js +235 -42
  33. package/templates/dashboard/js/view-runs.js +379 -37
  34. package/templates/dashboard/js/view-tests.js +157 -16
  35. package/templates/dashboard/js/view-tools.js +234 -0
  36. package/templates/dashboard/js/view-watch.js +2 -2
  37. package/templates/dashboard/js/websocket.js +33 -3
  38. package/templates/dashboard/styles/base.css +489 -53
  39. package/templates/dashboard/styles/components.css +719 -84
  40. package/templates/dashboard/styles/view-live.css +459 -78
  41. package/templates/dashboard/styles/view-runs.css +779 -177
  42. package/templates/dashboard/styles/view-tests.css +440 -77
  43. package/templates/dashboard/styles/view-tools.css +206 -0
  44. package/templates/dashboard/styles/view-watch.css +198 -41
  45. package/templates/dashboard/template.html +354 -56
  46. package/templates/dashboard.html +5173 -711
  47. package/templates/docker-compose-lightpanda.yml +7 -0
@@ -1,96 +1,459 @@
1
- /* ── Suite Cards ── */
2
- .suite-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:10px;padding:16px}
3
- .suite-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);overflow:hidden;transition:border-color .2s,box-shadow .2s}
4
- .suite-card:hover{border-color:var(--border-hi);box-shadow:0 2px 12px rgba(0,0,0,.25)}
5
- .suite-card-head{display:flex;align-items:center;gap:12px;padding:14px 16px;border-bottom:1px solid var(--border);background:var(--surface2)}
6
- .suite-card-icon{width:32px;height:32px;border-radius:6px;background:var(--accent-dim);display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--accent);flex-shrink:0}
1
+ /* ═══════════════════════════════════════════════════════════════════
2
+ VIEW · TESTS — Suites, Modules, Variables
3
+ ═══════════════════════════════════════════════════════════════════ */
4
+
5
+ /* ── Suites toolbar (search + expand/collapse) ── */
6
+ .suites-toolbar{
7
+ display:flex;align-items:center;gap:12px;
8
+ margin:6px 0 14px;
9
+ padding:10px 12px;
10
+ background:var(--surface);
11
+ border:1px solid var(--border);
12
+ border-radius:var(--r);
13
+ }
14
+ .suites-toolbar input{
15
+ flex:1;min-width:0;
16
+ padding:8px 12px;
17
+ border-radius:var(--r);
18
+ border:1px solid var(--border);
19
+ background:var(--bg);
20
+ color:var(--text);
21
+ font-family:var(--mono);font-size:12px;
22
+ }
23
+ .suites-toolbar input:focus{
24
+ outline:none;
25
+ border-color:var(--phosphor);
26
+ box-shadow:0 0 0 1px var(--phosphor-dim);
27
+ }
28
+ .suites-toolbar input::placeholder{color:var(--text3)}
29
+ .suites-toolbar-actions{
30
+ display:flex;align-items:center;gap:8px;flex-shrink:0;
31
+ }
32
+ .suites-toolbar-count{
33
+ font-size:10px;color:var(--text3);
34
+ font-family:var(--mono);
35
+ letter-spacing:.06em;
36
+ min-width:0;white-space:nowrap;
37
+ }
38
+
39
+ /* ── Suite grid ── */
40
+ .suite-grid{
41
+ display:grid;
42
+ grid-template-columns:repeat(auto-fill,minmax(340px,1fr));
43
+ gap:12px;padding:14px 2px;
44
+ }
45
+ .suite-card{
46
+ background:var(--surface);
47
+ border:1px solid var(--border);
48
+ border-radius:var(--r);
49
+ overflow:hidden;
50
+ transition:border-color .22s,box-shadow .22s,transform .22s;
51
+ position:relative;
52
+ }
53
+ .suite-card::before{
54
+ content:'';position:absolute;top:0;left:0;right:0;height:2px;
55
+ background:linear-gradient(90deg,var(--phosphor) 0,transparent 30%);
56
+ opacity:.55;
57
+ }
58
+ .suite-card:hover{
59
+ border-color:var(--border-hi);
60
+ transform:translateY(-1px);
61
+ box-shadow:0 0 0 1px var(--border-hi),0 14px 30px rgba(0,0,0,.32);
62
+ }
63
+
64
+ .suite-card-head{
65
+ display:flex;align-items:center;gap:14px;
66
+ padding:16px 18px;
67
+ border-bottom:1px solid var(--border);
68
+ background:var(--bg-2);
69
+ }
70
+ .suite-card-icon{
71
+ width:36px;height:36px;border-radius:var(--r);
72
+ background:var(--phosphor-dim);
73
+ display:flex;align-items:center;justify-content:center;
74
+ font-size:14px;color:var(--phosphor);
75
+ flex-shrink:0;
76
+ border:1px solid rgba(158,242,106,.25);
77
+ box-shadow:0 0 10px var(--phosphor-glow);
78
+ }
7
79
  .suite-card-info{flex:1;min-width:0}
8
- .suite-card-name{font-family:var(--sans);font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
9
- .suite-card-file{font-size:10px;color:var(--text3);margin-top:1px;font-family:var(--mono)}
10
- .suite-card-count{flex-shrink:0;display:flex;flex-direction:column;align-items:center;justify-content:center;min-width:40px;height:40px;border-radius:var(--r);background:var(--surface3);border:1px solid var(--border)}
11
- .suite-card-count-num{font-size:16px;font-weight:700;color:var(--text);line-height:1}
12
- .suite-card-count-lbl{font-size:8px;color:var(--text3);text-transform:uppercase;letter-spacing:.06em;line-height:1;margin-top:2px}
80
+ .suite-card-name{
81
+ font-family:var(--display);
82
+ font-weight:400;font-size:17px;
83
+ letter-spacing:-.01em;color:var(--text);
84
+ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.1;
85
+ }
86
+ .suite-card-file{
87
+ font-size:9px;color:var(--text3);
88
+ margin-top:4px;font-family:var(--mono);
89
+ letter-spacing:.08em;text-transform:uppercase;
90
+ }
91
+ .suite-card-count{
92
+ flex-shrink:0;display:flex;flex-direction:column;
93
+ align-items:center;justify-content:center;
94
+ min-width:46px;height:46px;border-radius:var(--r);
95
+ background:var(--surface);
96
+ border:1px solid var(--border);
97
+ position:relative;
98
+ }
99
+ .suite-card-count::before{
100
+ content:'';position:absolute;top:-1px;left:6px;right:6px;height:1px;
101
+ background:var(--phosphor);opacity:.5;
102
+ }
103
+ .suite-card-count-num{
104
+ font-family:var(--display);
105
+ font-size:22px;font-weight:400;
106
+ color:var(--text);line-height:1;letter-spacing:-.02em;
107
+ font-variant-numeric:tabular-nums;
108
+ }
109
+ .suite-card-count-lbl{
110
+ font-size:7px;color:var(--text3);
111
+ text-transform:uppercase;letter-spacing:.18em;
112
+ line-height:1;margin-top:3px;font-weight:700;
113
+ }
114
+
13
115
  .suite-card-body{padding:0}
14
- .suite-card-tests{list-style:none;max-height:180px;overflow-y:auto}
15
- .suite-card-tests::-webkit-scrollbar{width:4px}
16
- .suite-card-tests::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}
17
- .suite-card-tests li{font-size:11px;color:var(--text2);padding:6px 16px 6px 30px;position:relative;cursor:pointer;transition:all .15s;border-bottom:1px solid rgba(35,39,56,.5)}
116
+ .suite-card-tests{
117
+ list-style:none;
118
+ max-height:200px;overflow-y:auto;
119
+ }
120
+ .suite-card-tests li{
121
+ font-size:11px;color:var(--text2);
122
+ padding:8px 18px 8px 34px;
123
+ position:relative;cursor:pointer;
124
+ transition:all .15s;
125
+ border-bottom:1px solid rgba(42,43,32,.5);
126
+ }
18
127
  .suite-card-tests li:last-child{border-bottom:none}
19
- .suite-card-tests li:hover{color:var(--text);background:var(--surface2)}
20
- .suite-card-tests li::before{content:"\25B8";position:absolute;left:14px;color:var(--text3);font-size:9px;top:7px;transition:transform .15s}
21
- .suite-card-tests li.expanded{color:var(--accent);background:var(--accent-dim)}
22
- .suite-card-tests li.expanded::before{content:"\25BE";color:var(--accent)}
23
- .suite-test-steps{padding:8px 0 8px 14px;border-left:2px solid var(--accent-dim);margin:6px 0 4px 6px}
24
- .suite-card-footer{padding:10px 16px;border-top:1px solid var(--border);display:flex;justify-content:flex-end;background:var(--surface)}
128
+ .suite-card-tests li:hover{color:var(--text);background:rgba(158,242,106,.035)}
129
+ .suite-card-tests li::before{
130
+ content:"▸";
131
+ position:absolute;left:16px;color:var(--text3);
132
+ font-size:10px;top:8px;transition:transform .15s,color .15s;
133
+ }
134
+ .suite-card-tests li.expanded{color:var(--phosphor);background:var(--phosphor-dim)}
135
+ .suite-card-tests li.expanded::before{content:"▾";color:var(--phosphor)}
136
+
137
+ .suite-test-steps{
138
+ padding:10px 0 10px 16px;
139
+ border-left:2px solid var(--phosphor);
140
+ margin:8px 0 4px 6px;
141
+ background:rgba(158,242,106,.04);
142
+ }
143
+
144
+ .suite-card-footer{
145
+ padding:12px 18px;
146
+ border-top:1px solid var(--border);
147
+ display:flex;justify-content:flex-end;
148
+ background:var(--surface);
149
+ }
25
150
 
26
- /* ── Suite Detail Modal ── */
27
- .suite-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:200;display:none;align-items:flex-start;justify-content:center;padding:32px 24px;overflow-y:auto;backdrop-filter:blur(4px)}
151
+ /* ═══════════════════ Suite Detail Modal ═══════════════════ */
152
+ .suite-modal-overlay{
153
+ position:fixed;inset:0;
154
+ background:rgba(8,9,6,.82);
155
+ backdrop-filter:blur(8px);
156
+ z-index:200;display:none;
157
+ align-items:flex-start;justify-content:center;
158
+ padding:40px 24px;overflow-y:auto;
159
+ }
28
160
  .suite-modal-overlay.open{display:flex}
29
- .suite-modal{width:100%;max-width:960px;background:var(--surface);border:1px solid var(--border);border-radius:8px;overflow:hidden;animation:suiteModalIn .2s ease}
30
- @keyframes suiteModalIn{from{opacity:0;transform:translateY(-12px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}
31
- .suite-modal-header{display:flex;align-items:center;gap:14px;padding:18px 24px;background:var(--surface2);border-bottom:1px solid var(--border)}
32
- .suite-modal-header .suite-card-icon{width:36px;height:36px;font-size:16px}
161
+ .suite-modal{
162
+ width:100%;max-width:1000px;
163
+ background:var(--surface);
164
+ border:1px solid var(--border);
165
+ border-radius:var(--r);
166
+ overflow:hidden;
167
+ animation:suiteModalIn .25s cubic-bezier(.2,.9,.3,1.15);
168
+ box-shadow:0 0 0 1px rgba(158,242,106,.12),0 40px 80px rgba(0,0,0,.55);
169
+ position:relative;
170
+ }
171
+ .suite-modal::before{
172
+ content:'SUITE·DETAIL';
173
+ position:absolute;top:-9px;left:24px;z-index:2;
174
+ background:var(--surface);padding:0 10px;
175
+ font-family:var(--mono);font-size:9px;font-weight:700;
176
+ letter-spacing:.28em;color:var(--phosphor);
177
+ }
178
+ @keyframes suiteModalIn{
179
+ from{opacity:0;transform:translateY(-16px) scale(.98)}
180
+ to{opacity:1;transform:translateY(0) scale(1)}
181
+ }
182
+ .suite-modal-header{
183
+ display:flex;align-items:center;gap:16px;
184
+ padding:22px 28px;
185
+ background:var(--bg-2);
186
+ border-bottom:1px solid var(--border);
187
+ }
188
+ .suite-modal-header .suite-card-icon{width:42px;height:42px;font-size:18px}
33
189
  .suite-modal-title{flex:1;min-width:0}
34
- .suite-modal-title h2{font-family:var(--sans);font-size:16px;font-weight:700;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
35
- .suite-modal-title span{font-size:10px;color:var(--text3);font-family:var(--mono)}
36
- .suite-modal-actions{display:flex;gap:8px;align-items:center;flex-shrink:0}
37
- .suite-modal-close{width:32px;height:32px;border-radius:var(--r);border:1px solid var(--border);background:var(--surface3);color:var(--text2);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .15s;line-height:1}
38
- .suite-modal-close:hover{background:var(--red-dim);border-color:rgba(239,68,68,.3);color:var(--red)}
190
+ .suite-modal-title h2{
191
+ font-family:var(--display);
192
+ font-size:26px;font-weight:400;
193
+ letter-spacing:-.015em;
194
+ margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
195
+ }
196
+ .suite-modal-title span{
197
+ font-size:10px;color:var(--text3);
198
+ font-family:var(--mono);
199
+ letter-spacing:.1em;text-transform:uppercase;
200
+ }
201
+ .suite-modal-actions{display:flex;gap:10px;align-items:center;flex-shrink:0}
202
+ .suite-modal-close{
203
+ width:34px;height:34px;border-radius:var(--r);
204
+ border:1px solid var(--border);
205
+ background:transparent;color:var(--text2);
206
+ font-size:18px;cursor:pointer;
207
+ display:flex;align-items:center;justify-content:center;
208
+ transition:all .15s;line-height:1;
209
+ }
210
+ .suite-modal-close:hover{
211
+ background:var(--crimson-dim);
212
+ border-color:var(--crimson);
213
+ color:var(--crimson);
214
+ }
39
215
  .suite-modal-body{padding:0}
40
- .suite-modal-loading{padding:32px;text-align:center;color:var(--text3);font-size:12px}
216
+ .suite-modal-loading{
217
+ padding:40px;text-align:center;
218
+ color:var(--text3);font-size:11px;
219
+ letter-spacing:.2em;text-transform:uppercase;
220
+ }
41
221
  .suite-modal-test{border-bottom:1px solid var(--border)}
42
222
  .suite-modal-test:last-child{border-bottom:none}
43
- .suite-modal-test-header{display:flex;align-items:center;gap:10px;padding:12px 24px;cursor:pointer;transition:background .15s;user-select:none}
44
- .suite-modal-test-header:hover{background:var(--surface2)}
45
- .suite-modal-test.open>.suite-modal-test-header{background:var(--surface2)}
46
- .suite-modal-test-chevron{font-size:9px;color:var(--text3);transition:transform .15s;width:14px;text-align:center;flex-shrink:0}
47
- .suite-modal-test.open>.suite-modal-test-header .suite-modal-test-chevron{transform:rotate(90deg);color:var(--accent)}
48
- .suite-modal-test-name{font-size:12px;font-weight:500;color:var(--text);flex:1}
49
- .suite-modal-test-badge{font-size:9px;padding:2px 7px;border-radius:8px;background:var(--surface3);color:var(--text3);flex-shrink:0}
50
- .suite-modal-test-actions{display:none;padding:0 24px 16px 48px}
223
+ .suite-modal-test-header{
224
+ display:flex;align-items:center;gap:12px;
225
+ padding:14px 28px;cursor:pointer;
226
+ transition:background .15s;user-select:none;
227
+ }
228
+ .suite-modal-test-header:hover{background:rgba(158,242,106,.03)}
229
+ .suite-modal-test.open>.suite-modal-test-header{
230
+ background:var(--bg-2);
231
+ border-bottom:1px dashed var(--border);
232
+ }
233
+ .suite-modal-test-chevron{
234
+ font-size:10px;color:var(--text3);
235
+ transition:transform .15s,color .15s;
236
+ width:14px;text-align:center;flex-shrink:0;
237
+ }
238
+ .suite-modal-test.open>.suite-modal-test-header .suite-modal-test-chevron{
239
+ transform:rotate(90deg);color:var(--phosphor);
240
+ }
241
+ .suite-modal-test-name{
242
+ font-family:var(--mono);
243
+ font-size:12px;font-weight:500;
244
+ color:var(--text);flex:1;letter-spacing:.02em;
245
+ }
246
+ .suite-modal-test-badge{
247
+ font-size:8px;font-weight:700;
248
+ padding:3px 8px;border-radius:999px;
249
+ background:transparent;border:1px solid var(--border);
250
+ color:var(--text3);flex-shrink:0;
251
+ letter-spacing:.14em;text-transform:uppercase;
252
+ }
253
+ .suite-modal-test-actions{display:none;padding:0 28px 20px 56px}
51
254
  .suite-modal-test.open>.suite-modal-test-actions{display:block}
52
- .suite-modal-step{display:flex;align-items:flex-start;gap:8px;padding:5px 0;font-size:11px;font-family:var(--mono);border-bottom:1px solid rgba(35,39,56,.3)}
255
+
256
+ .suite-modal-step{
257
+ display:flex;align-items:flex-start;gap:10px;
258
+ padding:6px 0;
259
+ font-size:11px;font-family:var(--mono);
260
+ border-bottom:1px solid rgba(42,43,32,.35);
261
+ }
53
262
  .suite-modal-step:last-child{border-bottom:none}
54
- .suite-modal-step-num{width:22px;text-align:right;color:var(--text3);flex-shrink:0;font-size:10px;padding-top:1px}
55
- .suite-modal-step-type{color:var(--purple);font-weight:600;flex-shrink:0;min-width:120px}
263
+ .suite-modal-step-num{
264
+ width:26px;text-align:right;
265
+ color:var(--text3);flex-shrink:0;
266
+ font-size:10px;padding-top:1px;
267
+ font-variant-numeric:tabular-nums;
268
+ letter-spacing:.04em;
269
+ }
270
+ .suite-modal-step-num::after{content:'·';color:var(--text3);margin-left:2px}
271
+ .suite-modal-step-type{
272
+ color:var(--radio);font-weight:700;flex-shrink:0;
273
+ min-width:130px;
274
+ letter-spacing:.08em;text-transform:uppercase;
275
+ font-size:10px;
276
+ }
56
277
  .suite-modal-step-detail{color:var(--text2);flex:1;min-width:0;word-break:break-word}
57
- .suite-modal-step-detail .step-sel{color:var(--accent)}
58
- .suite-modal-step-detail .step-arrow{color:var(--text3);margin:0 4px}
278
+ .suite-modal-step-detail .step-sel{color:var(--beacon);font-weight:500}
279
+ .suite-modal-step-detail .step-arrow{color:var(--text3);margin:0 5px}
59
280
  .suite-modal-step-detail .step-val{color:var(--text)}
60
- .suite-modal-expect{padding:10px 24px 10px 48px;background:var(--green-dim);border-bottom:1px solid var(--border);font-size:11px;color:var(--green);display:flex;align-items:flex-start;gap:8px}
61
- .suite-modal-expect-label{font-weight:600;flex-shrink:0}
62
281
 
63
- /* ── Project Accordion ── */
64
- .project-accordion{margin-bottom:2px}
65
- .project-accordion-header{display:flex;align-items:center;gap:12px;padding:12px 16px;background:var(--surface);border:1px solid var(--border);border-radius:var(--r);cursor:pointer;transition:all .15s;user-select:none}
66
- .project-accordion-header:hover{background:var(--surface2);border-color:var(--border-hi)}
67
- .project-accordion.open>.project-accordion-header{border-radius:var(--r) var(--r) 0 0;border-bottom-color:transparent;background:var(--surface2)}
68
- .project-accordion-chevron{font-size:10px;color:var(--text3);transition:transform .2s ease;flex-shrink:0;width:16px;text-align:center}
69
- .project-accordion.open>.project-accordion-header .project-accordion-chevron{transform:rotate(90deg);color:var(--accent)}
70
- .project-accordion-name{font-family:var(--sans);font-size:13px;font-weight:600;color:var(--text);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
282
+ .suite-modal-expect{
283
+ padding:12px 28px 12px 56px;
284
+ background:rgba(158,242,106,.06);
285
+ border-top:1px dashed var(--border);
286
+ border-bottom:1px dashed var(--border);
287
+ font-size:11px;color:var(--phosphor);
288
+ display:flex;align-items:flex-start;gap:8px;
289
+ font-family:var(--mono);letter-spacing:.02em;
290
+ }
291
+ .suite-modal-expect-label{
292
+ font-weight:700;flex-shrink:0;
293
+ letter-spacing:.14em;text-transform:uppercase;
294
+ font-size:9px;padding-top:1px;
295
+ }
296
+
297
+ /* ═══════════════════ Project Accordion ═══════════════════ */
298
+ .project-accordion{margin-bottom:4px}
299
+ .project-accordion-header{
300
+ display:flex;align-items:center;gap:12px;
301
+ padding:13px 18px;
302
+ background:var(--surface);
303
+ border:1px solid var(--border);
304
+ border-radius:var(--r);
305
+ cursor:pointer;transition:all .15s;user-select:none;
306
+ position:relative;
307
+ }
308
+ .project-accordion-header:hover{
309
+ background:var(--surface2);
310
+ border-color:var(--border-hi);
311
+ }
312
+ .project-accordion.open>.project-accordion-header{
313
+ border-radius:var(--r) var(--r) 0 0;
314
+ border-bottom-color:var(--phosphor);
315
+ background:var(--bg-2);
316
+ }
317
+ .project-accordion-chevron{
318
+ font-size:11px;color:var(--text3);
319
+ transition:transform .25s ease,color .15s;
320
+ flex-shrink:0;width:16px;text-align:center;
321
+ }
322
+ .project-accordion.open>.project-accordion-header .project-accordion-chevron{
323
+ transform:rotate(90deg);color:var(--phosphor);
324
+ }
325
+ .project-accordion-name{
326
+ font-family:var(--display);
327
+ font-size:18px;font-weight:400;letter-spacing:-.01em;
328
+ color:var(--text);flex:1;min-width:0;
329
+ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
330
+ }
71
331
  .project-accordion-meta{display:flex;align-items:center;gap:10px;flex-shrink:0}
72
- .project-accordion-badge{font-size:10px;font-weight:600;padding:2px 8px;border-radius:10px;background:var(--surface3);color:var(--text2)}
73
- .project-accordion-body{overflow:hidden;max-height:0;transition:max-height .3s ease;border:1px solid var(--border);border-top:none;border-radius:0 0 var(--r) var(--r);background:var(--bg)}
332
+ .project-accordion-badge{
333
+ font-size:9px;font-weight:700;
334
+ padding:3px 9px;border-radius:999px;
335
+ background:transparent;
336
+ border:1px solid var(--border);
337
+ color:var(--text2);
338
+ letter-spacing:.14em;text-transform:uppercase;
339
+ font-variant-numeric:tabular-nums;
340
+ }
341
+ .project-accordion-body{
342
+ overflow:hidden;max-height:0;
343
+ transition:max-height .35s ease;
344
+ border:1px solid var(--border);border-top:none;
345
+ border-radius:0 0 var(--r) var(--r);
346
+ background:var(--bg);
347
+ }
74
348
  .project-accordion.open>.project-accordion-body{max-height:5000px}
75
349
 
76
- /* ── Module Cards ── */
77
- .module-section-title{font-family:var(--sans);font-size:14px;font-weight:600;margin:24px 0 12px;padding-bottom:8px;border-bottom:1px solid var(--border);color:var(--text2);display:flex;align-items:center;gap:8px}
78
- .module-section-title .mod-icon{color:var(--purple)}
79
- .module-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}
80
- .module-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:16px;border-left:3px solid var(--purple);transition:border-color .15s}
81
- .module-card:hover{border-color:var(--border-hi);border-left-color:var(--purple)}
82
- .module-card-name{font-weight:600;font-size:13px;color:var(--purple);margin-bottom:4px}
83
- .module-card-desc{font-size:11px;color:var(--text2);margin-bottom:8px}
84
- .module-card-meta{font-size:10px;color:var(--text3);display:flex;gap:12px}
85
- .module-card-params{list-style:none;font-size:10px;color:var(--text2);margin-top:6px}
86
- .module-card-params li{padding:2px 0}
87
- .module-card-params li::before{content:'$';color:var(--purple);margin-right:4px}
350
+ /* ═══════════════════ Modules ═══════════════════ */
351
+ .module-section-title{
352
+ font-family:var(--display);
353
+ font-size:22px;font-weight:400;letter-spacing:-.01em;
354
+ margin:28px 0 14px;
355
+ padding-bottom:10px;
356
+ border-bottom:1px solid var(--border);
357
+ color:var(--text);
358
+ display:flex;align-items:center;gap:10px;
359
+ position:relative;
360
+ }
361
+ .module-section-title::after{
362
+ content:'';position:absolute;bottom:-1px;left:0;width:80px;height:1px;
363
+ background:var(--radio);box-shadow:0 0 8px var(--radio-glow);
364
+ }
365
+ .module-section-title .mod-icon{color:var(--radio);font-size:16px}
366
+
367
+ .module-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}
368
+ .module-card{
369
+ background:var(--surface);
370
+ border:1px solid var(--border);
371
+ border-radius:var(--r);
372
+ padding:18px;
373
+ border-left:3px solid var(--radio);
374
+ transition:all .2s;
375
+ position:relative;
376
+ }
377
+ .module-card:hover{
378
+ border-color:var(--border-hi);
379
+ border-left-color:var(--radio);
380
+ transform:translateY(-1px);
381
+ box-shadow:0 10px 24px rgba(0,0,0,.3);
382
+ }
383
+ .module-card-name{
384
+ font-family:var(--mono);
385
+ font-weight:700;font-size:13px;
386
+ color:var(--radio);margin-bottom:6px;
387
+ letter-spacing:.02em;
388
+ text-shadow:0 0 12px var(--radio-glow);
389
+ }
390
+ .module-card-desc{
391
+ font-size:11px;color:var(--text2);
392
+ margin-bottom:10px;line-height:1.5;
393
+ }
394
+ .module-card-meta{
395
+ font-size:9px;color:var(--text3);
396
+ display:flex;gap:14px;
397
+ letter-spacing:.14em;text-transform:uppercase;font-weight:600;
398
+ }
399
+ .module-card-params{
400
+ list-style:none;
401
+ font-size:10px;color:var(--text2);
402
+ margin-top:10px;padding-top:10px;
403
+ border-top:1px dashed var(--border);
404
+ }
405
+ .module-card-params li{
406
+ padding:3px 0;font-family:var(--mono);
407
+ display:flex;align-items:center;gap:6px;
408
+ }
409
+ .module-card-params li::before{
410
+ content:'$';color:var(--radio);font-weight:700;
411
+ }
88
412
 
89
- /* ── Variables ── */
413
+ /* ═══════════════════ Variables ═══════════════════ */
90
414
  .var-table{width:100%;border-collapse:collapse;font-size:12px}
91
- .var-table th{text-align:left;font-size:9px;font-weight:600;color:var(--text3);letter-spacing:.08em;text-transform:uppercase;padding:8px 12px;border-bottom:1px solid var(--border)}
92
- .var-table td{padding:8px 12px;border-bottom:1px solid var(--border)}
93
- .var-table td code{background:var(--surface3);padding:1px 5px;border-radius:3px;font-size:11px}
94
- .var-add-form{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:16px;margin-bottom:16px}
95
- .var-add-form input,.var-add-form select{padding:6px 10px;border-radius:var(--r);border:1px solid var(--border);background:var(--surface2);color:var(--text);font-family:var(--mono);font-size:12px}
96
- .var-add-form input:focus,.var-add-form select:focus{outline:none;border-color:var(--accent)}
415
+ .var-table th{
416
+ text-align:left;
417
+ font-size:8px;font-weight:700;
418
+ color:var(--text3);letter-spacing:.14em;text-transform:uppercase;
419
+ padding:10px 14px;border-bottom:1px solid var(--border);
420
+ background:var(--bg-2);
421
+ }
422
+ .var-table td{padding:10px 14px;border-bottom:1px solid var(--border);font-family:var(--mono)}
423
+ .var-table td code{
424
+ background:var(--bg);padding:2px 7px;border-radius:2px;
425
+ font-size:11px;border:1px solid var(--border);
426
+ color:var(--phosphor);
427
+ }
428
+
429
+ .var-add-form{
430
+ background:var(--surface);
431
+ border:1px solid var(--border);
432
+ border-radius:var(--r);
433
+ padding:18px;margin-bottom:16px;
434
+ position:relative;
435
+ }
436
+ .var-add-form::before{
437
+ content:'NEW·VARIABLE';
438
+ position:absolute;top:-8px;left:18px;
439
+ background:var(--bg);padding:0 8px;
440
+ font-family:var(--mono);font-size:9px;font-weight:700;
441
+ letter-spacing:.16em;color:var(--phosphor);
442
+ }
443
+ .var-add-form input,.var-add-form select{
444
+ padding:8px 12px;border-radius:var(--r);
445
+ border:1px solid var(--border);
446
+ background:var(--bg);
447
+ color:var(--text);
448
+ font-family:var(--mono);font-size:12px;
449
+ }
450
+ .var-add-form input:focus,.var-add-form select:focus{
451
+ outline:none;border-color:var(--phosphor);
452
+ box-shadow:0 0 0 1px var(--phosphor-dim);
453
+ }
454
+
455
+ /* In single-project mode the expand/collapse buttons make no sense
456
+ (there are no project accordions to expand) — keep the input visible
457
+ so users can still filter within the project. */
458
+ .suites-toolbar.single-project #btnExpandAllSuites,
459
+ .suites-toolbar.single-project #btnCollapseAllSuites{display:none}