@matware/e2e-runner 1.3.0 → 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 (56) hide show
  1. package/.claude-plugin/marketplace.json +37 -6
  2. package/.claude-plugin/plugin.json +17 -3
  3. package/LICENSE +190 -0
  4. package/README.md +151 -527
  5. package/agents/test-creator.md +4 -2
  6. package/agents/test-improver.md +5 -3
  7. package/bin/cli.js +84 -20
  8. package/commands/capture.md +45 -0
  9. package/package.json +3 -2
  10. package/skills/e2e-testing/SKILL.md +3 -2
  11. package/skills/e2e-testing/references/action-types.md +22 -4
  12. package/skills/e2e-testing/references/test-json-format.md +23 -0
  13. package/src/actions.js +321 -14
  14. package/src/ai-generate.js +81 -0
  15. package/src/app-pool.js +339 -0
  16. package/src/config.js +131 -7
  17. package/src/dashboard.js +209 -11
  18. package/src/db.js +74 -7
  19. package/src/index.js +6 -4
  20. package/src/learner-sqlite.js +154 -0
  21. package/src/learner.js +70 -3
  22. package/src/mcp-tools.js +259 -34
  23. package/src/module-analysis.js +247 -0
  24. package/src/module-resolver.js +35 -2
  25. package/src/narrate.js +42 -1
  26. package/src/pool-manager.js +68 -17
  27. package/src/pool.js +464 -37
  28. package/src/reporter.js +4 -1
  29. package/src/runner.js +410 -63
  30. package/src/visual-diff.js +515 -0
  31. package/src/websocket.js +14 -3
  32. package/src/wizard.js +184 -0
  33. package/templates/build-dashboard.js +3 -0
  34. package/templates/dashboard/js/api.js +62 -3
  35. package/templates/dashboard/js/init.js +46 -0
  36. package/templates/dashboard/js/keyboard.js +8 -7
  37. package/templates/dashboard/js/quicksearch.js +277 -0
  38. package/templates/dashboard/js/state.js +61 -7
  39. package/templates/dashboard/js/toast.js +1 -1
  40. package/templates/dashboard/js/utils.js +20 -0
  41. package/templates/dashboard/js/view-live.js +240 -9
  42. package/templates/dashboard/js/view-runs.js +540 -94
  43. package/templates/dashboard/js/view-tests.js +157 -16
  44. package/templates/dashboard/js/view-tools.js +234 -0
  45. package/templates/dashboard/js/view-watch.js +2 -2
  46. package/templates/dashboard/js/websocket.js +36 -0
  47. package/templates/dashboard/styles/base.css +489 -53
  48. package/templates/dashboard/styles/components.css +719 -77
  49. package/templates/dashboard/styles/view-live.css +463 -59
  50. package/templates/dashboard/styles/view-runs.css +793 -155
  51. package/templates/dashboard/styles/view-tests.css +440 -77
  52. package/templates/dashboard/styles/view-tools.css +206 -0
  53. package/templates/dashboard/styles/view-watch.css +198 -41
  54. package/templates/dashboard/template.html +369 -56
  55. package/templates/dashboard.html +5375 -901
  56. package/templates/docker-compose-lightpanda.yml +7 -0
@@ -0,0 +1,206 @@
1
+ /* ═══════════════════════════════════════════════════════════════════
2
+ VIEW · TOOLS — Module analysis, capture, analyze, agent prompts
3
+ ═══════════════════════════════════════════════════════════════════ */
4
+
5
+ .tool-card{
6
+ background:var(--surface);
7
+ border:1px solid var(--border);
8
+ border-radius:var(--r);
9
+ padding:18px 20px 16px;
10
+ margin-bottom:16px;
11
+ position:relative;
12
+ }
13
+ .tool-card::before{
14
+ content:'';position:absolute;top:0;left:18px;width:24px;height:1px;
15
+ background:var(--phosphor);opacity:.5;
16
+ }
17
+ .tool-card-head{
18
+ display:flex;align-items:center;justify-content:space-between;
19
+ gap:14px;margin-bottom:10px;
20
+ }
21
+ .tool-card-title{
22
+ font-family:var(--display);
23
+ font-size:18px;font-weight:400;letter-spacing:-.005em;
24
+ color:var(--text);
25
+ display:flex;align-items:center;gap:10px;
26
+ }
27
+ .tool-card-icon{
28
+ font-size:14px;opacity:.7;color:var(--phosphor);
29
+ }
30
+ .tool-card-actions{display:flex;gap:8px;align-items:center}
31
+ .tool-card-desc{
32
+ font-family:var(--mono);font-size:11px;
33
+ color:var(--text2);
34
+ letter-spacing:.01em;line-height:1.55;
35
+ margin-bottom:14px;
36
+ padding-bottom:12px;
37
+ border-bottom:1px solid var(--border);
38
+ }
39
+ .tool-card-desc code{
40
+ font-family:var(--mono);font-size:10.5px;
41
+ background:var(--bg-2);
42
+ padding:1px 6px;border-radius:2px;
43
+ color:var(--phosphor);
44
+ }
45
+ .tool-card-body{padding-top:4px}
46
+
47
+ .tool-empty{
48
+ font-family:var(--mono);font-size:11px;color:var(--text3);
49
+ padding:18px 6px;text-align:center;letter-spacing:.04em;
50
+ }
51
+
52
+ .tool-form-row{
53
+ display:flex;align-items:center;gap:10px;margin-bottom:10px;
54
+ }
55
+ .tool-form-row input[type="text"]{
56
+ flex:1;
57
+ padding:8px 12px;
58
+ background:var(--bg-2);border:1px solid var(--border);
59
+ border-radius:var(--r);
60
+ font-family:var(--mono);font-size:11px;
61
+ color:var(--text);outline:none;
62
+ transition:border-color .15s,background .15s;
63
+ }
64
+ .tool-form-row input[type="text"]:focus{
65
+ border-color:var(--phosphor);background:var(--surface);
66
+ }
67
+ .tool-form-row input[type="text"]::placeholder{color:var(--text3);font-style:italic}
68
+ .tool-form-check{
69
+ display:inline-flex;align-items:center;gap:6px;
70
+ font-family:var(--mono);font-size:10px;
71
+ color:var(--text2);letter-spacing:.06em;
72
+ text-transform:uppercase;font-weight:600;
73
+ user-select:none;cursor:pointer;
74
+ padding:0 4px;
75
+ }
76
+ .tool-form-check input{margin:0;accent-color:var(--phosphor)}
77
+ .tool-result{
78
+ margin-top:10px;
79
+ font-family:var(--mono);font-size:11px;
80
+ color:var(--text2);
81
+ }
82
+ .tool-result.is-error{color:var(--crimson)}
83
+ .tool-result img{
84
+ max-width:100%;border:1px solid var(--border);border-radius:var(--r);
85
+ margin-top:8px;display:block;
86
+ }
87
+ .tool-result pre{
88
+ background:var(--bg-2);border:1px solid var(--border);border-radius:var(--r);
89
+ padding:10px 12px;font-family:var(--mono);font-size:10.5px;
90
+ color:var(--text);max-height:300px;overflow:auto;
91
+ white-space:pre-wrap;word-break:break-word;
92
+ }
93
+
94
+ /* ─── Module analysis layout ───────────────────────────────────── */
95
+ .mod-summary{
96
+ display:grid;grid-template-columns:repeat(4,1fr);gap:10px;
97
+ margin-bottom:18px;
98
+ }
99
+ .mod-summary-cell{
100
+ background:var(--bg-2);border:1px solid var(--border);border-radius:var(--r);
101
+ padding:12px 14px;
102
+ }
103
+ .mod-summary-cell-lbl{
104
+ font-family:var(--mono);font-size:8px;font-weight:700;
105
+ color:var(--text3);letter-spacing:.24em;text-transform:uppercase;
106
+ margin-bottom:6px;
107
+ }
108
+ .mod-summary-cell-val{
109
+ font-family:var(--display);font-size:26px;font-weight:400;
110
+ color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.01em;
111
+ }
112
+ .mod-summary-cell.warn .mod-summary-cell-val{color:var(--amber)}
113
+ .mod-summary-cell.signal .mod-summary-cell-val{color:var(--phosphor);text-shadow:0 0 12px var(--phosphor-glow)}
114
+
115
+ .mod-section-title{
116
+ font-family:var(--mono);font-size:9px;font-weight:700;
117
+ color:var(--text3);letter-spacing:.24em;text-transform:uppercase;
118
+ margin:20px 0 10px;
119
+ padding-bottom:6px;border-bottom:1px solid var(--border);
120
+ display:flex;align-items:center;gap:10px;
121
+ }
122
+ .mod-section-title .count{
123
+ font-family:var(--mono);font-size:10px;font-weight:500;
124
+ color:var(--text);background:var(--bg-2);border:1px solid var(--border);
125
+ padding:1px 8px;border-radius:999px;letter-spacing:.04em;
126
+ }
127
+
128
+ .mod-row{
129
+ display:flex;align-items:flex-start;gap:14px;
130
+ padding:10px 12px;
131
+ border:1px solid var(--border);border-radius:var(--r);
132
+ background:var(--bg-2);
133
+ margin-bottom:8px;
134
+ }
135
+ .mod-row.unused{border-color:rgba(255,179,71,.3);background:var(--amber-dim)}
136
+ .mod-row-main{flex:1;min-width:0}
137
+ .mod-row-name{
138
+ font-family:var(--mono);font-size:12px;color:var(--text);
139
+ font-weight:600;margin-bottom:4px;
140
+ }
141
+ .mod-row-desc{
142
+ font-family:var(--mono);font-size:10px;color:var(--text2);
143
+ margin-bottom:4px;line-height:1.45;
144
+ }
145
+ .mod-row-meta{
146
+ font-family:var(--mono);font-size:9.5px;color:var(--text3);
147
+ letter-spacing:.04em;
148
+ display:flex;gap:14px;flex-wrap:wrap;
149
+ }
150
+ .mod-row-usage{
151
+ font-family:var(--mono);font-size:10px;color:var(--phosphor);
152
+ font-weight:600;font-variant-numeric:tabular-nums;
153
+ white-space:nowrap;align-self:center;
154
+ }
155
+ .mod-row.unused .mod-row-usage{color:var(--amber)}
156
+
157
+ .cand-row{
158
+ border:1px solid var(--border);border-radius:var(--r);
159
+ background:var(--bg-2);
160
+ padding:12px 14px;margin-bottom:8px;
161
+ }
162
+ .cand-row-head{
163
+ display:flex;align-items:center;gap:14px;
164
+ margin-bottom:8px;
165
+ }
166
+ .cand-name{
167
+ font-family:var(--mono);font-size:12px;color:var(--text);font-weight:600;
168
+ }
169
+ .cand-stats{
170
+ margin-left:auto;
171
+ font-family:var(--mono);font-size:9.5px;
172
+ color:var(--text3);letter-spacing:.04em;
173
+ display:flex;gap:14px;
174
+ }
175
+ .cand-stats strong{color:var(--phosphor);font-variant-numeric:tabular-nums}
176
+ .cand-actions-preview{
177
+ font-family:var(--mono);font-size:10px;
178
+ color:var(--text2);
179
+ background:var(--surface);border:1px solid var(--border);border-radius:var(--r);
180
+ padding:8px 10px;
181
+ white-space:pre-wrap;word-break:break-word;
182
+ margin-bottom:6px;line-height:1.55;
183
+ }
184
+ .cand-used-by{
185
+ font-family:var(--mono);font-size:9.5px;color:var(--text3);
186
+ letter-spacing:.02em;line-height:1.6;
187
+ }
188
+ .cand-used-by strong{color:var(--text2);font-weight:500}
189
+
190
+ /* ─── Agent prompt rows ──────────────────────────────────────── */
191
+ .agent-prompt-row{
192
+ display:flex;align-items:center;gap:14px;
193
+ padding:10px 12px;
194
+ border:1px solid var(--border);border-radius:var(--r);
195
+ background:var(--bg-2);
196
+ margin-bottom:8px;
197
+ }
198
+ .agent-prompt-info{flex:1;display:flex;flex-direction:column;gap:2px}
199
+ .agent-prompt-info strong{
200
+ font-family:var(--mono);font-size:11px;color:var(--phosphor);
201
+ letter-spacing:.04em;text-transform:none;
202
+ }
203
+ .agent-prompt-info span{
204
+ font-family:var(--mono);font-size:10px;color:var(--text2);
205
+ line-height:1.45;
206
+ }
@@ -1,53 +1,210 @@
1
- /* ── Watch View: Project Cards ── */
2
- .watch-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;margin-bottom:24px}
3
- .watch-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:16px;transition:border-color .2s,box-shadow .2s}
4
- .watch-card:hover{border-color:var(--border-hi);box-shadow:0 2px 12px rgba(0,0,0,.25)}
5
- .watch-card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
6
- .watch-card-name{font-family:var(--sans);font-size:14px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}
7
- .watch-card-icons{display:flex;gap:6px;flex-shrink:0;margin-left:8px}
8
- .watch-card-icons .btn{padding:3px 8px;font-size:10px}
9
-
10
- /* ── Sparkline ── */
11
- .watch-sparkline{height:40px;margin-bottom:10px}
1
+ /* ═══════════════════════════════════════════════════════════════════
2
+ VIEW · WATCH — Project Telemetry Cards + Event Log
3
+ ═══════════════════════════════════════════════════════════════════ */
4
+
5
+ .watch-grid{
6
+ display:grid;
7
+ grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
8
+ gap:14px;margin-bottom:28px;
9
+ }
10
+
11
+ .watch-card{
12
+ background:var(--surface);
13
+ border:1px solid var(--border);
14
+ border-radius:var(--r);
15
+ padding:18px 18px 16px;
16
+ transition:border-color .25s,box-shadow .25s,transform .25s;
17
+ position:relative;overflow:hidden;
18
+ }
19
+ /* phosphor corner tick */
20
+ .watch-card::before{
21
+ content:'';position:absolute;top:0;left:0;
22
+ width:18px;height:1px;background:var(--phosphor);opacity:.55;
23
+ }
24
+ .watch-card::after{
25
+ content:'';position:absolute;top:0;left:0;
26
+ width:1px;height:18px;background:var(--phosphor);opacity:.55;
27
+ }
28
+ .watch-card:hover{
29
+ border-color:var(--border-hi);
30
+ transform:translateY(-1px);
31
+ box-shadow:0 0 0 1px var(--border-hi),0 10px 30px rgba(0,0,0,.35);
32
+ }
33
+
34
+ .watch-card-header{
35
+ display:flex;align-items:center;justify-content:space-between;
36
+ margin-bottom:14px;
37
+ }
38
+ .watch-card-name{
39
+ font-family:var(--display);
40
+ font-size:18px;font-weight:400;
41
+ letter-spacing:-.01em;
42
+ color:var(--text);
43
+ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
44
+ flex:1;min-width:0;line-height:1.1;
45
+ }
46
+ .watch-card-icons{display:flex;gap:6px;flex-shrink:0;margin-left:10px}
47
+ .watch-card-icons .btn{padding:3px 8px;font-size:9px;letter-spacing:.1em}
48
+
49
+ /* Sparkline */
50
+ .watch-sparkline{
51
+ height:44px;margin-bottom:12px;
52
+ padding:4px 0;
53
+ border-top:1px dashed var(--border);
54
+ border-bottom:1px dashed var(--border);
55
+ background:
56
+ repeating-linear-gradient(90deg,transparent 0 24px,rgba(158,242,106,.04) 24px 25px);
57
+ }
12
58
  .watch-sparkline svg{width:100%;height:100%;display:block}
13
59
 
14
- /* ── Card Footer ── */
15
- .watch-card-footer{display:flex;align-items:center;justify-content:space-between;font-size:11px}
16
- .watch-card-status{display:flex;align-items:center;gap:6px}
17
- .watch-card-status .status-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
18
- .watch-card-status .status-dot.green{background:var(--green);box-shadow:0 0 6px var(--green)}
19
- .watch-card-status .status-dot.red{background:var(--red);box-shadow:0 0 6px var(--red)}
20
- .watch-card-status .status-dot.amber{background:var(--amber);box-shadow:0 0 6px var(--amber)}
60
+ /* Footer */
61
+ .watch-card-footer{
62
+ display:flex;align-items:center;justify-content:space-between;
63
+ font-size:10px;
64
+ text-transform:uppercase;letter-spacing:.14em;
65
+ font-weight:600;
66
+ }
67
+ .watch-card-status{display:flex;align-items:center;gap:8px}
68
+ .watch-card-status .status-dot{
69
+ width:8px;height:8px;border-radius:50%;flex-shrink:0;
70
+ position:relative;
71
+ }
72
+ .watch-card-status .status-dot.green{
73
+ background:var(--phosphor);
74
+ box-shadow:0 0 8px var(--phosphor-glow),0 0 2px var(--phosphor);
75
+ }
76
+ .watch-card-status .status-dot.red{
77
+ background:var(--crimson);
78
+ box-shadow:0 0 8px rgba(255,77,77,.5),0 0 2px var(--crimson);
79
+ }
80
+ .watch-card-status .status-dot.amber{
81
+ background:var(--amber);
82
+ box-shadow:0 0 8px rgba(255,179,71,.5);
83
+ }
21
84
  .watch-card-status .status-dot.dim{background:var(--text3)}
22
- .watch-card-rate{font-weight:600}
23
- .watch-card-rate.green{color:var(--green)}
85
+
86
+ .watch-card-rate{
87
+ font-family:var(--display);
88
+ font-weight:400;font-size:20px;letter-spacing:-.02em;
89
+ text-transform:none;
90
+ font-variant-numeric:tabular-nums;
91
+ }
92
+ .watch-card-rate.green{color:var(--phosphor);text-shadow:0 0 12px var(--phosphor-glow)}
24
93
  .watch-card-rate.amber{color:var(--amber)}
25
- .watch-card-rate.red{color:var(--red)}
94
+ .watch-card-rate.red{color:var(--crimson)}
26
95
 
27
- .watch-card-meta{display:flex;flex-direction:column;gap:4px;margin-top:10px;font-size:10px;color:var(--text3)}
96
+ .watch-card-meta{
97
+ display:flex;flex-direction:column;gap:5px;
98
+ margin-top:14px;padding-top:12px;
99
+ border-top:1px solid var(--border);
100
+ font-size:10px;color:var(--text3);
101
+ letter-spacing:.04em;
102
+ }
28
103
  .watch-card-meta span{display:flex;align-items:center;gap:6px}
29
- .watch-card-countdown{color:var(--accent);font-weight:500;font-variant-numeric:tabular-nums}
104
+ .watch-card-countdown{
105
+ color:var(--beacon);font-weight:600;
106
+ font-variant-numeric:tabular-nums;
107
+ letter-spacing:.06em;
108
+ }
30
109
  .watch-card-commit{font-family:var(--mono);color:var(--text3)}
31
110
 
32
- /* ── Event Log ── */
33
- .watch-event-log{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);overflow:hidden}
34
- .watch-event-log-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);background:var(--surface2)}
35
- .watch-event-log-header .title{font-family:var(--sans);font-size:13px;font-weight:600}
36
- .watch-event-log-body{max-height:400px;overflow-y:auto}
37
- .watch-event-row{display:grid;grid-template-columns:120px 130px minmax(80px,1fr) 46px 74px 40px 52px 60px;align-items:center;gap:0;padding:7px 16px;border-bottom:1px solid var(--border);font-size:11px;transition:background .1s}
111
+ /* ═══════════════════ Event Log ═══════════════════ */
112
+
113
+ .watch-event-log{
114
+ background:var(--surface);
115
+ border:1px solid var(--border);
116
+ border-radius:var(--r);
117
+ overflow:hidden;
118
+ position:relative;
119
+ margin-top:12px;
120
+ }
121
+ .watch-event-log-header{
122
+ display:flex;align-items:center;justify-content:space-between;
123
+ padding:14px 18px 12px;
124
+ border-bottom:1px solid var(--border);
125
+ background:
126
+ repeating-linear-gradient(180deg,transparent 0 3px,rgba(158,242,106,.015) 3px 4px),
127
+ var(--bg-2);
128
+ position:relative;
129
+ }
130
+ .watch-event-log-header::before{
131
+ content:'LOG·STREAM';
132
+ font-family:var(--mono);font-size:8px;font-weight:700;
133
+ letter-spacing:.3em;color:var(--phosphor);
134
+ text-shadow:0 0 10px var(--phosphor-glow);
135
+ position:absolute;top:6px;right:20px;
136
+ }
137
+ .watch-event-log-header .title{
138
+ font-family:var(--display);
139
+ font-size:20px;font-weight:400;letter-spacing:-.01em;
140
+ margin-top:4px;
141
+ }
142
+ .watch-event-log-body{max-height:420px;overflow-y:auto}
143
+
144
+ .watch-event-row{
145
+ display:grid;
146
+ grid-template-columns:120px 130px minmax(80px,1fr) 46px 74px 40px 52px 60px;
147
+ align-items:center;gap:0;
148
+ padding:8px 18px;
149
+ border-bottom:1px solid var(--border);
150
+ font-size:10px;transition:background .12s;
151
+ }
38
152
  .watch-event-row:last-child{border-bottom:none}
39
- .watch-event-row:hover{background:var(--surface2)}
40
- .watch-event-row.we-header{font-size:9px;font-weight:600;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;padding:6px 16px;background:var(--surface2);border-bottom:1px solid var(--border);position:sticky;top:0;z-index:1}
41
- .watch-event-row.we-header:hover{background:var(--surface2)}
42
- .watch-event-time{color:var(--text3);font-variant-numeric:tabular-nums;font-family:var(--mono);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
43
- .watch-event-project{color:var(--text);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:8px}
44
- .watch-event-suite{color:var(--accent);font-family:var(--mono);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:8px}
153
+ .watch-event-row:hover{background:rgba(158,242,106,.025)}
154
+ .watch-event-row.we-header{
155
+ font-size:8px;font-weight:700;
156
+ color:var(--text3);text-transform:uppercase;letter-spacing:.1em;
157
+ padding:10px 18px;
158
+ background:var(--bg-2);
159
+ border-bottom:1px solid var(--border);
160
+ position:sticky;top:0;z-index:1;
161
+ }
162
+ .watch-event-row.we-header > *{
163
+ padding-right:6px;
164
+ }
165
+ .watch-event-row.we-header:hover{background:var(--bg-2)}
166
+
167
+ .watch-event-time{
168
+ color:var(--text3);
169
+ font-variant-numeric:tabular-nums;
170
+ font-family:var(--mono);font-size:10px;
171
+ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
172
+ letter-spacing:.02em;
173
+ }
174
+ .watch-event-project{
175
+ color:var(--text);font-weight:500;
176
+ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
177
+ padding-right:8px;
178
+ }
179
+ .watch-event-suite{
180
+ color:var(--beacon);
181
+ font-family:var(--mono);font-size:10px;
182
+ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
183
+ padding-right:8px;
184
+ }
45
185
  .watch-event-result{justify-self:center}
46
- .watch-event-counts{font-family:var(--mono);font-size:10px;color:var(--text2);white-space:nowrap;text-align:center}
47
- .watch-event-counts .we-counts-ok{color:var(--green)}
48
- .watch-event-rate{font-weight:600;color:var(--text2);font-variant-numeric:tabular-nums;text-align:right}
49
- .watch-event-duration{color:var(--text3);font-family:var(--mono);font-size:10px;text-align:right}
50
- .we-trigger{color:var(--text3);font-size:9px;padding:1px 6px;border-radius:8px;background:var(--surface3);white-space:nowrap;text-align:center;justify-self:end}
186
+ .watch-event-counts{
187
+ font-family:var(--mono);font-size:10px;color:var(--text2);
188
+ white-space:nowrap;text-align:center;font-variant-numeric:tabular-nums;
189
+ }
190
+ .watch-event-counts .we-counts-ok{color:var(--phosphor)}
191
+ .watch-event-rate{
192
+ font-weight:700;color:var(--text2);
193
+ font-variant-numeric:tabular-nums;text-align:right;
194
+ font-family:var(--mono);
195
+ }
196
+ .watch-event-duration{
197
+ color:var(--text3);font-family:var(--mono);
198
+ font-size:10px;text-align:right;
199
+ font-variant-numeric:tabular-nums;
200
+ }
201
+ .we-trigger{
202
+ color:var(--text3);font-size:8px;font-weight:700;
203
+ padding:2px 7px;border-radius:999px;
204
+ background:transparent;border:1px solid var(--border);
205
+ letter-spacing:.12em;text-transform:uppercase;
206
+ white-space:nowrap;text-align:center;justify-self:end;
207
+ }
51
208
 
52
- /* ── Watch Table (legacy) ── */
209
+ /* legacy watch table */
53
210
  .watch-jobs-table{width:100%;border-collapse:collapse;font-size:11px}