@azure-id/orc 1.4.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/CHANGELOG.md +3154 -2907
  2. package/README-id.md +39 -2
  3. package/README.md +647 -631
  4. package/bin/cli.js +42495 -36866
  5. package/bin/mockrun-catalog.js +4 -0
  6. package/bin/verify-contracts.js +4475 -4410
  7. package/bin/verify-package.js +21 -2
  8. package/bin/webui/api.js +1388 -1283
  9. package/bin/webui/app.html +9 -0
  10. package/bin/webui/css/04-motion.css +18 -0
  11. package/bin/webui/css/06-responsive.css +17 -1
  12. package/bin/webui/css/panels/hookui.css +220 -41
  13. package/bin/webui/css/panels/test.css +132 -0
  14. package/bin/webui/fixtures/index.js +23 -1
  15. package/bin/webui/fixtures/test.js +547 -0
  16. package/bin/webui/i18n/en/common.json +1 -0
  17. package/bin/webui/i18n/en/hookui.json +17 -3
  18. package/bin/webui/i18n/en/nav.json +1 -0
  19. package/bin/webui/i18n/en/overview.json +4 -0
  20. package/bin/webui/i18n/en/test.json +141 -0
  21. package/bin/webui/i18n/en/tour.json +1 -1
  22. package/bin/webui/i18n/id/common.json +1 -0
  23. package/bin/webui/i18n/id/hookui.json +17 -3
  24. package/bin/webui/i18n/id/nav.json +1 -0
  25. package/bin/webui/i18n/id/overview.json +4 -0
  26. package/bin/webui/i18n/id/test.json +141 -0
  27. package/bin/webui/i18n/id/tour.json +1 -1
  28. package/bin/webui/js/01-i18n.js +1 -0
  29. package/bin/webui/js/panels/challenge.js +8 -3
  30. package/bin/webui/js/panels/hookui.js +586 -208
  31. package/bin/webui/js/panels/overview.js +10 -0
  32. package/bin/webui/js/panels/test.js +733 -0
  33. package/bin/webui/serve.js +572 -557
  34. package/mock-run/orc-test.md +327 -0
  35. package/package.json +1 -1
  36. package/templates/agents/MODEL-MAPPING.md +2 -0
  37. package/templates/agents/orc-test-designer-opus-5-high.md +158 -0
  38. package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -0
  39. package/templates/commands/orc-test.md +66 -0
  40. package/templates/hooks/README.md +8 -1
  41. package/templates/hooks/orc-statusline.js +15 -4
  42. package/templates/hooks/orc-subagent-line.js +5 -2
  43. package/templates/skills/_shared/extra-dispatch.md +1346 -1337
  44. package/templates/skills/_shared/live-target.md +188 -0
  45. package/templates/skills/_shared/phases/trace.md +2 -2
  46. package/templates/skills/_shared/wait.md +241 -240
  47. package/templates/skills/orc-test/SKILL.md +233 -0
@@ -42,6 +42,7 @@
42
42
  <link rel="stylesheet" href="css/panels/challenge.css">
43
43
  <link rel="stylesheet" href="css/panels/docs.css">
44
44
  <link rel="stylesheet" href="css/panels/extra.css">
45
+ <link rel="stylesheet" href="css/panels/test.css">
45
46
  <link rel="stylesheet" href="css/06-responsive.css">
46
47
  <link rel="stylesheet" href="css/04-motion.css">
47
48
  </head>
@@ -97,6 +98,13 @@
97
98
  -->
98
99
  <li><a href="#/docs" data-panel="docs" data-idx="d" data-i18n="nav.docs">Docs</a></li>
99
100
  <li><a href="#/challenge" data-panel="challenge" data-idx="c" data-i18n="nav.challenge">Challenge</a></li>
101
+ <!--
102
+ v1.5.0. Test sits directly under Challenge because it is the same kind
103
+ of thing one step further on: Challenge grades what you WROTE, this
104
+ reports what a running system actually DID. Both stop and hand back
105
+ rather than fixing what they measured.
106
+ -->
107
+ <li><a href="#/test" data-panel="test" data-idx="t" data-i18n="nav.test">Test</a></li>
100
108
  <li><a href="#/pact" data-panel="pact" data-idx="p" data-i18n="nav.pact">Promises</a></li>
101
109
  <li><a href="#/boundary" data-panel="boundary" data-idx="b" data-i18n="nav.boundary">Boundary</a></li>
102
110
  <li><a href="#/wait" data-panel="wait" data-idx="w" data-i18n="nav.wait">Wait</a></li>
@@ -206,6 +214,7 @@
206
214
  <script src="js/panels/extra.js"></script>
207
215
  <script src="js/panels/wait.js"></script>
208
216
  <script src="js/panels/hookui.js"></script>
217
+ <script src="js/panels/test.js"></script>
209
218
  <script src="js/90-tour.js"></script>
210
219
  <script src="js/91-shortcuts.js"></script>
211
220
  <script src="js/99-boot.js"></script>
@@ -74,6 +74,24 @@
74
74
  }
75
75
  button.hk-pick-row:hover { transform: translateX(3px); }
76
76
 
77
+ /* NOTHING ARRIVES ON A REPAINT (v1.4.2). The CLI Hook Interface rebuilds its
78
+ whole panel when a change is STAGED — no request, no navigation, the same
79
+ cards with one value different — and the entrance animations above replayed
80
+ every time, on a 30ms stagger. With the network tab empty it read exactly
81
+ like the page reloading, on every keystroke.
82
+
83
+ `hk-quiet` is added by `hkPaint` from the SECOND paint onward and by the part
84
+ editor before every rebuild. It removes the ENTRANCES only: the transitions
85
+ further up are about the pointer rather than about arriving, so hover, the
86
+ drop marker and the staged edge are untouched. It must load after the rules
87
+ it switches off, which is why it is here and not in the panel's own file. */
88
+ .hk-quiet > *,
89
+ .hk-quiet .hk-chip,
90
+ .hk-quiet .hk-chip-new,
91
+ .hk-quiet .hk-pick-row {
92
+ animation: none;
93
+ }
94
+
77
95
  /* ---------------------------------------------------------- REDUCED MOTION */
78
96
  /* Non-negotiable: every animation and transition above is off. */
79
97
 
@@ -76,6 +76,20 @@
76
76
  band template here would put the target under the caret. */
77
77
  .ex-slot-head { grid-template-columns: minmax(0, 40%) minmax(0, 1fr) 16px; }
78
78
  .ex-slot-when { grid-column: 1 / -1; }
79
+ /* v1.5.0 — /orc-test. Every grid here DECLARES its columns, so every one of
80
+ them collapses explicitly rather than inheriting a template it no longer
81
+ has the width for. The route, the case row and the OWASP row all keep the
82
+ SAME child count in every state (that is the `.ex-tool` lesson), so the
83
+ collapse is a template change and never a hidden child. */
84
+ .ts-route { grid-template-columns: 56px minmax(0, 1fr); }
85
+ .ts-route > .chip { grid-column: 2; justify-self: start; }
86
+ .ts-where { grid-column: 1 / -1; }
87
+ .ts-case { grid-template-columns: 56px minmax(0, 1fr); }
88
+ .ts-case > .chip { grid-column: 2; justify-self: start; }
89
+ .ts-case-mid { grid-column: 1 / -1; }
90
+ .ts-case-tail { grid-column: 1 / -1; justify-content: flex-start; }
91
+ .ts-owasp { grid-template-columns: 56px minmax(0, 1fr); }
92
+ .ts-owasp-mid { grid-column: 1 / -1; }
79
93
  .ex-band-chips { grid-column: 1 / -1; justify-content: flex-start; }
80
94
  .ex-route-controls { align-items: stretch; }
81
95
  .ex-route-controls .btn { width: 100%; }
@@ -124,12 +138,14 @@
124
138
  way. The PREVIEW never collapses: it is a monospaced grid and squeezing it
125
139
  would misreport the width the user is deciding. It scrolls instead. */
126
140
  .hk-degrade-row,
141
+ .hk-compare-row,
127
142
  .hk-field,
128
143
  .hk-check {
129
144
  grid-template-columns: 1fr;
130
145
  gap: 4px;
131
146
  }
132
- .hk-degrade-label {
147
+ .hk-degrade-label,
148
+ .hk-compare-label {
133
149
  text-align: left;
134
150
  }
135
151
  .hk-gallery {
@@ -20,7 +20,7 @@
20
20
  margin: 0;
21
21
  padding: 10px 12px;
22
22
  border-radius: 8px;
23
- background: var(--bg-sunken);
23
+ background: var(--surface-2);
24
24
  border: 1px solid var(--line);
25
25
  /* A wide line SCROLLS inside its own box. The page body must never scroll
26
26
  sideways — and squeezing a status line to fit would misreport its width,
@@ -57,22 +57,184 @@
57
57
  margin-bottom: 10px;
58
58
  }
59
59
 
60
- .hk-degrade {
60
+ /* ── the terminal window (v1.4.2) ──────────────────────────────────────── */
61
+ /* The preview is a claim about what a terminal will print, so it is drawn as a
62
+ terminal. The chrome is not decoration: the title bar states the width the
63
+ picture was rendered at, and the ruler under it shows where that width falls.
64
+ Everything inside stays on the same monospaced grid - anything proportional
65
+ here would misrepresent every width decision the user makes. */
66
+ .hk-term {
67
+ border: 1px solid var(--line);
68
+ border-radius: 10px;
69
+ overflow: hidden;
70
+ background: var(--surface-2);
71
+ }
72
+ .hk-term-bar {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 10px;
76
+ padding: 6px 10px;
77
+ border-bottom: 1px solid var(--line);
78
+ background: var(--surface-3);
79
+ }
80
+ .hk-term-dots {
81
+ display: flex;
82
+ gap: 5px;
83
+ flex: 0 0 auto;
84
+ }
85
+ .hk-term-dot {
86
+ width: 9px;
87
+ height: 9px;
88
+ border-radius: 50%;
89
+ background: var(--line);
90
+ }
91
+ .hk-term-title {
92
+ font-size: 11px;
93
+ color: var(--text-dim);
94
+ flex: 1 1 auto;
95
+ min-width: 0;
96
+ overflow: hidden;
97
+ text-overflow: ellipsis;
98
+ white-space: nowrap;
99
+ }
100
+ .hk-term-tags {
101
+ display: flex;
102
+ gap: 6px;
103
+ flex: 0 0 auto;
104
+ }
105
+ /* The colour set and the symbol set the picture was drawn with. The words are
106
+ the CLI's own and are printed verbatim. */
107
+ .hk-term-tag {
108
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
109
+ font-size: 10px;
110
+ color: var(--text-dim);
111
+ border: 1px solid var(--line);
112
+ border-radius: 999px;
113
+ padding: 1px 7px;
114
+ }
115
+ .hk-term-screen {
116
+ padding: 10px 12px;
117
+ overflow-x: auto;
118
+ scrollbar-width: thin;
119
+ scrollbar-color: var(--line) transparent;
120
+ }
121
+ .hk-term-screen::-webkit-scrollbar {
122
+ height: 8px;
123
+ }
124
+ .hk-term-screen::-webkit-scrollbar-track {
125
+ background: transparent;
126
+ }
127
+ .hk-term-screen::-webkit-scrollbar-thumb {
128
+ background: var(--line);
129
+ border-radius: 4px;
130
+ }
131
+ /* The line inside a window has no box of its own: the window IS the box, and a
132
+ second border around the same string reads as a second thing. */
133
+ .hk-preview-flat {
134
+ border: none;
135
+ background: transparent;
136
+ padding: 0;
137
+ overflow-x: visible;
138
+ }
139
+ .hk-term-sm .hk-term-screen {
140
+ padding: 7px 10px;
141
+ }
142
+ .hk-term-sm .hk-preview {
143
+ font-size: 12px;
144
+ }
145
+ .hk-ruler {
146
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
147
+ font-size: 13px;
148
+ line-height: 1.55;
149
+ white-space: pre;
150
+ color: var(--text-dim);
151
+ opacity: 0.55;
152
+ border-bottom: 1px solid var(--line);
153
+ margin-bottom: 6px;
154
+ padding-bottom: 2px;
155
+ }
156
+ .hk-widths {
157
+ margin-top: 8px;
158
+ }
159
+
160
+ /* ── the comparison drawer ─────────────────────────────────────────────── */
161
+ /* Eleven more terminals is a wall of them, and it pushed the board off the
162
+ screen. One drawer, closed by default, fetched on the first open. */
163
+ .hk-compare {
61
164
  margin-top: 14px;
165
+ border: 1px solid var(--line);
166
+ border-radius: 10px;
167
+ overflow: hidden;
168
+ }
169
+ .hk-compare-head {
170
+ display: flex;
171
+ align-items: center;
172
+ gap: 10px;
173
+ width: 100%;
174
+ text-align: left;
175
+ padding: 9px 12px;
176
+ border: none;
177
+ background: var(--surface-3);
178
+ color: var(--text);
179
+ cursor: pointer;
180
+ font: inherit;
181
+ }
182
+ .hk-compare-head .tier-caret {
183
+ color: var(--text-dim);
184
+ }
185
+ .hk-compare-open .hk-compare-head .tier-caret {
186
+ transform: rotate(90deg);
187
+ }
188
+ .hk-compare-title {
189
+ font-weight: 600;
190
+ font-size: 13px;
191
+ }
192
+ .hk-compare-body {
193
+ display: none;
194
+ padding: 12px;
195
+ gap: 10px;
196
+ }
197
+ .hk-compare-open .hk-compare-body {
62
198
  display: grid;
63
- gap: 6px;
64
199
  }
65
- .hk-degrade-row {
200
+ .hk-compare-group {
201
+ font-size: 11px;
202
+ letter-spacing: 0.06em;
203
+ text-transform: uppercase;
204
+ color: var(--text-dim);
205
+ margin-top: 4px;
206
+ }
207
+ .hk-compare-row {
66
208
  display: grid;
67
- grid-template-columns: 90px 1fr;
209
+ grid-template-columns: 110px 1fr;
68
210
  gap: 10px;
69
211
  align-items: center;
212
+ min-width: 0;
70
213
  }
71
- .hk-degrade-label {
214
+ .hk-compare-label {
215
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
72
216
  font-size: 11px;
73
- color: var(--fg-dim);
217
+ color: var(--text-dim);
74
218
  text-align: right;
75
219
  }
220
+ .hk-compare-row .hk-term-bar {
221
+ display: none;
222
+ }
223
+ /* A control this SHAPE cannot use. It keeps its slot and carries the reason —
224
+ "this shape cannot use it" and "we forgot to offer it" must never look the
225
+ same, and a value already set has to stay readable. */
226
+ .hk-inert {
227
+ display: grid;
228
+ gap: 4px;
229
+ }
230
+ .hk-inert > :first-child {
231
+ opacity: 0.45;
232
+ pointer-events: none;
233
+ }
234
+ .hk-editor-live {
235
+ display: grid;
236
+ gap: 6px;
237
+ }
76
238
 
77
239
  /* ── cautions ──────────────────────────────────────────────────────────── */
78
240
  .hk-caution {
@@ -110,11 +272,11 @@
110
272
  .hk-line-name {
111
273
  font-size: 12px;
112
274
  font-weight: 600;
113
- color: var(--fg-dim);
275
+ color: var(--text-dim);
114
276
  }
115
277
  .hk-line-count {
116
278
  font-size: 11px;
117
- color: var(--fg-dim);
279
+ color: var(--text-dim);
118
280
  }
119
281
  .hk-full {
120
282
  color: var(--warn);
@@ -135,7 +297,7 @@
135
297
  .hk-zone-hot {
136
298
  border-color: var(--accent);
137
299
  border-style: solid;
138
- background: var(--bg-sunken);
300
+ background: var(--surface-2);
139
301
  }
140
302
  .hk-zone-why {
141
303
  flex-basis: 100%;
@@ -149,8 +311,8 @@
149
311
  45deg,
150
312
  transparent,
151
313
  transparent 6px,
152
- var(--bg-sunken) 6px,
153
- var(--bg-sunken) 12px
314
+ var(--surface-2) 6px,
315
+ var(--surface-2) 12px
154
316
  );
155
317
  }
156
318
  .hk-blocked {
@@ -158,7 +320,7 @@
158
320
  gap: 8px;
159
321
  align-items: center;
160
322
  font-size: 12px;
161
- color: var(--fg-dim);
323
+ color: var(--text-dim);
162
324
  padding: 8px;
163
325
  }
164
326
 
@@ -173,7 +335,7 @@
173
335
  padding: 9px 10px;
174
336
  border: 1px solid var(--line);
175
337
  border-radius: 9px;
176
- background: var(--bg-raised);
338
+ background: var(--surface-3);
177
339
  min-width: 150px;
178
340
  max-width: 280px;
179
341
  cursor: grab;
@@ -214,7 +376,7 @@
214
376
  min-height: 24px;
215
377
  }
216
378
  .hk-grip {
217
- color: var(--fg-dim);
379
+ color: var(--text-dim);
218
380
  font-size: 14px;
219
381
  line-height: 1;
220
382
  cursor: grab;
@@ -223,14 +385,14 @@
223
385
  .hk-chip-id {
224
386
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
225
387
  font-size: 11px;
226
- color: var(--fg-dim);
388
+ color: var(--text-dim);
227
389
  }
228
390
  /* "What is this thing" is the first question anybody asks of a bar full of
229
391
  symbols, and until v1.4.1 the answer lived only in a tooltip. */
230
392
  .hk-chip-desc {
231
393
  font-size: 11px;
232
394
  line-height: 1.45;
233
- color: var(--fg-dim);
395
+ color: var(--text-dim);
234
396
  }
235
397
  .hk-chip-acts {
236
398
  display: flex;
@@ -243,13 +405,13 @@
243
405
  padding: 3px 8px;
244
406
  border: 1px solid var(--line);
245
407
  border-radius: 5px;
246
- background: var(--bg-sunken);
247
- color: var(--fg-dim);
408
+ background: var(--surface-2);
409
+ color: var(--text-dim);
248
410
  cursor: pointer;
249
411
  }
250
412
  .hk-act:hover {
251
413
  border-color: var(--accent);
252
- color: var(--fg);
414
+ color: var(--text);
253
415
  }
254
416
  .hk-act-remove:hover {
255
417
  border-color: var(--bad);
@@ -259,7 +421,7 @@
259
421
  .hk-add {
260
422
  border: 1px dashed var(--line);
261
423
  background: none;
262
- color: var(--fg-dim);
424
+ color: var(--text-dim);
263
425
  border-radius: 9px;
264
426
  padding: 10px 18px;
265
427
  cursor: pointer;
@@ -268,7 +430,7 @@
268
430
  }
269
431
  .hk-add:hover:not(:disabled) {
270
432
  border-color: var(--accent);
271
- color: var(--fg);
433
+ color: var(--text);
272
434
  }
273
435
  .hk-add:disabled {
274
436
  cursor: not-allowed;
@@ -287,10 +449,27 @@
287
449
  padding: 4px 8px;
288
450
  border: 1px solid var(--line);
289
451
  border-radius: 6px;
290
- background: var(--bg-sunken);
291
- color: var(--fg);
452
+ background: var(--surface-2);
453
+ color: var(--text);
292
454
  max-width: 260px;
293
455
  }
456
+ /* THE OPEN LIST IS NOT THE CLOSED BOX (v1.4.2). A native <select> popup is
457
+ drawn by the platform, and it inherits the control's `color` while taking its
458
+ background from the system - so a light `--fg` on a dark panel arrived as
459
+ near-white text on the platform's near-white menu, and the values could not
460
+ be read at all. `color-scheme` tells the platform which menu to draw, and the
461
+ option rule states both halves rather than leaving one of them to chance. */
462
+ .hk-select {
463
+ color-scheme: light dark;
464
+ }
465
+ .hk-select option,
466
+ .hk-select optgroup {
467
+ background: var(--surface-3);
468
+ color: var(--text);
469
+ }
470
+ .hk-select option:disabled {
471
+ color: var(--text-dim);
472
+ }
294
473
 
295
474
  /* ── the part picker ───────────────────────────────────────────────────── */
296
475
  .hk-picker {
@@ -339,14 +518,14 @@
339
518
  padding: 9px 11px;
340
519
  border: 1px solid var(--line);
341
520
  border-radius: 8px;
342
- background: var(--bg-raised);
521
+ background: var(--surface-3);
343
522
  text-align: left;
344
523
  cursor: pointer;
345
524
  color: inherit;
346
525
  }
347
526
  button.hk-pick-row:hover {
348
527
  border-color: var(--accent);
349
- background: var(--bg-sunken);
528
+ background: var(--surface-2);
350
529
  }
351
530
  .hk-pick-row-off {
352
531
  cursor: default;
@@ -362,7 +541,7 @@ button.hk-pick-row:hover {
362
541
  .hk-pick-desc {
363
542
  font-size: 12px;
364
543
  line-height: 1.5;
365
- color: var(--fg-dim);
544
+ color: var(--text-dim);
366
545
  }
367
546
 
368
547
  /* ── move ──────────────────────────────────────────────────────────────── */
@@ -390,7 +569,7 @@ button.hk-pick-row:hover {
390
569
  position: sticky;
391
570
  top: 0;
392
571
  z-index: 1;
393
- background: var(--bg-raised);
572
+ background: var(--surface-3);
394
573
  padding-bottom: 4px;
395
574
  }
396
575
  /* The editor is a flex COLUMN that stretches its children, which turned a small
@@ -408,7 +587,7 @@ button.hk-pick-row:hover {
408
587
  font-size: 11px;
409
588
  text-transform: uppercase;
410
589
  letter-spacing: 0.06em;
411
- color: var(--fg-dim);
590
+ color: var(--text-dim);
412
591
  border-bottom: 1px solid var(--line);
413
592
  padding-bottom: 3px;
414
593
  }
@@ -428,7 +607,7 @@ button.hk-pick-row:hover {
428
607
  padding: 6px 8px;
429
608
  border: 1px solid var(--line);
430
609
  border-radius: 6px;
431
- background: var(--bg-sunken);
610
+ background: var(--surface-2);
432
611
  cursor: pointer;
433
612
  text-align: left;
434
613
  }
@@ -437,12 +616,12 @@ button.hk-pick-row:hover {
437
616
  }
438
617
  .hk-sample-on {
439
618
  border-color: var(--accent);
440
- background: var(--bg-raised);
619
+ background: var(--surface-3);
441
620
  }
442
621
  .hk-sample-id {
443
622
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
444
623
  font-size: 10px;
445
- color: var(--fg-dim);
624
+ color: var(--text-dim);
446
625
  }
447
626
 
448
627
  /* A control, its name, and the sentence that says what it does. The sentence is
@@ -462,7 +641,7 @@ button.hk-pick-row:hover {
462
641
  .hk-field-name {
463
642
  font-size: 12px;
464
643
  font-weight: 600;
465
- color: var(--fg);
644
+ color: var(--text);
466
645
  }
467
646
  .hk-picks {
468
647
  display: flex;
@@ -475,8 +654,8 @@ button.hk-pick-row:hover {
475
654
  padding: 3px 7px;
476
655
  border: 1px solid var(--line);
477
656
  border-radius: 5px;
478
- background: var(--bg-sunken);
479
- color: var(--fg-dim);
657
+ background: var(--surface-2);
658
+ color: var(--text-dim);
480
659
  cursor: pointer;
481
660
  }
482
661
  .hk-pick:hover {
@@ -484,8 +663,8 @@ button.hk-pick-row:hover {
484
663
  }
485
664
  .hk-pick-on {
486
665
  border-color: var(--accent);
487
- color: var(--fg);
488
- background: var(--bg-raised);
666
+ color: var(--text);
667
+ background: var(--surface-3);
489
668
  }
490
669
  .hk-checks {
491
670
  display: grid;
@@ -525,7 +704,7 @@ button.hk-pick-row:hover {
525
704
  .hk-prow-desc {
526
705
  font-size: 12px;
527
706
  line-height: 1.5;
528
- color: var(--fg-dim);
707
+ color: var(--text-dim);
529
708
  }
530
709
  .hk-prow-why {
531
710
  flex-basis: 100%;
@@ -562,7 +741,7 @@ button.hk-pick-row:hover {
562
741
  padding: 8px 10px;
563
742
  border: 1px solid var(--line);
564
743
  border-radius: 8px;
565
- background: var(--bg-sunken);
744
+ background: var(--surface-2);
566
745
  cursor: pointer;
567
746
  text-align: left;
568
747
  color: inherit;
@@ -572,13 +751,13 @@ button.hk-pick-row:hover {
572
751
  }
573
752
  .hk-theme-on {
574
753
  border-color: var(--accent);
575
- background: var(--bg-raised);
754
+ background: var(--surface-3);
576
755
  }
577
756
  .hk-theme-name {
578
757
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
579
758
  font-size: 12px;
580
759
  font-weight: 600;
581
- color: var(--fg);
760
+ color: var(--text);
582
761
  }
583
762
 
584
763
  /* A number field is a NUMBER field: wide enough for three digits and its
@@ -0,0 +1,132 @@
1
+ /* panels/test.css — the Test panel (v1.5.0).
2
+
3
+ /orc-test: five tabs' worth of surface. Loaded by app.html in the order its
4
+ <link> sits in that manifest, and for CSS the load order IS the cascade
5
+ order — which is why 06-responsive and 04-motion come after every panel
6
+ sheet.
7
+
8
+ NO COLOUR TOKEN IS DEFINED HERE. Every one of them is declared once, on bare
9
+ :root, in 00-tokens.css.
10
+
11
+ NO MOTION IS DEFINED HERE either. The run rows reuse `.run-row` / `.run-card`
12
+ from panels/runs.css, so the fold and its reduced-motion behaviour are
13
+ already one implementation rather than two. */
14
+
15
+ /* --- the header strip ---------------------------------------------------- */
16
+ /* Above the tabs, on every one of them: what this run measured, in one line.
17
+ Every value is the CLI's. */
18
+ .ts-strip {
19
+ display: flex;
20
+ flex-wrap: wrap;
21
+ gap: var(--sp-4);
22
+ padding: var(--sp-3);
23
+ border: 1px solid var(--line-soft);
24
+ border-radius: var(--radius-sm);
25
+ margin-bottom: var(--sp-3);
26
+ }
27
+ .ts-strip-item { display: grid; gap: 2px; }
28
+ .ts-strip-value { font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; }
29
+ .ts-strip-label { font-size: 11px; color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em; }
30
+ .ts-strip-item.ts-ok .ts-strip-value { color: var(--ok); }
31
+ .ts-strip-item.ts-warn .ts-strip-value { color: var(--warn); }
32
+ .ts-strip-item.ts-bad .ts-strip-value { color: var(--bad); }
33
+
34
+ /* --- the caution --------------------------------------------------------- */
35
+ /* OUTSIDE the tabs, because a caution you must hunt for is a caution nobody
36
+ reads. It fires only on something the run actually MEASURED. */
37
+ .ts-caution {
38
+ padding: var(--sp-3);
39
+ border: 1px solid var(--bad);
40
+ border-radius: var(--radius-sm);
41
+ background: var(--surface-2);
42
+ margin-bottom: var(--sp-3);
43
+ }
44
+ .ts-caution-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
45
+
46
+ /* --- the authorization block --------------------------------------------- */
47
+ /* It renders ALWAYS and verbatim. A statement nobody filled in is a STATE, and
48
+ it is drawn as one — never as an empty row. */
49
+ .ts-auth {
50
+ display: grid;
51
+ gap: 2px;
52
+ padding: var(--sp-3);
53
+ border-left: 3px solid var(--ok);
54
+ background: var(--surface-2);
55
+ border-radius: var(--radius-sm);
56
+ margin: var(--sp-3) 0;
57
+ }
58
+ .ts-auth-empty { border-left-color: var(--warn); }
59
+ .ts-auth-label { font-size: 11px; color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em; }
60
+ .ts-auth-value { font-size: 14px; }
61
+ .ts-auth-empty .ts-auth-value { color: var(--warn); }
62
+
63
+ /* The hand-back. ORC does not repair the system it is testing, and the sentence
64
+ that says so is not decoration. */
65
+ .ts-handback {
66
+ padding: var(--sp-2) var(--sp-3);
67
+ border-left: 3px solid var(--warn);
68
+ background: var(--surface-2);
69
+ border-radius: var(--radius-sm);
70
+ font-size: 13px;
71
+ margin: var(--sp-2) 0;
72
+ }
73
+
74
+ .ts-label { font-size: 11px; color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em; }
75
+ .ts-where { color: var(--text-dim); font-family: var(--mono); font-size: 12px; }
76
+
77
+ /* --- the surface --------------------------------------------------------- */
78
+ /* A ROUTE ROW DECLARES ITS COLUMNS. Every route carries the same five children
79
+ in every state — method, path, two chips, and where it came from — so the
80
+ template is fixed and a chip can never land in a slack row. */
81
+ .ts-route {
82
+ display: grid;
83
+ grid-template-columns: 60px minmax(0, 1fr) auto auto minmax(0, 1fr);
84
+ align-items: center;
85
+ gap: var(--sp-2);
86
+ padding: var(--sp-2) 0;
87
+ border-top: 1px solid var(--line-soft);
88
+ }
89
+ .ts-route:first-of-type { border-top: 0; }
90
+ .ts-method { font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--accent); }
91
+ .ts-path { font-family: var(--mono); font-size: 13px; overflow-wrap: anywhere; }
92
+ .ts-route-min { font-family: var(--mono); font-size: 12px; color: var(--text-dim); padding: 2px 0; overflow-wrap: anywhere; }
93
+ .ts-bad { color: var(--bad); }
94
+
95
+ /* --- the case matrix ----------------------------------------------------- */
96
+ /* Same rule as the route row: FIXED columns, and the tail is a container that
97
+ is always present even when it holds nothing. A card whose child count
98
+ changes with its state must not declare its rows (`.ex-tool`'s 250px
99
+ ellipse), so the count here does not change. */
100
+ .ts-case {
101
+ display: grid;
102
+ grid-template-columns: 64px auto auto minmax(0, 1fr) auto;
103
+ align-items: start;
104
+ gap: var(--sp-2);
105
+ padding: var(--sp-2) 0;
106
+ border-top: 1px solid var(--line-soft);
107
+ }
108
+ .ts-case:first-of-type { border-top: 0; }
109
+ .ts-case-id { font-family: var(--mono); font-size: 12px; font-weight: 600; }
110
+ .ts-case-mid { display: grid; gap: 2px; min-width: 0; }
111
+ .ts-case-target { font-family: var(--mono); font-size: 13px; overflow-wrap: anywhere; }
112
+ .ts-case-why { font-size: 12px; color: var(--text-dim); overflow-wrap: anywhere; }
113
+ .ts-case-gap { font-size: 12px; color: var(--warn); overflow-wrap: anywhere; }
114
+ .ts-case-ev { font-family: var(--mono); font-size: 11px; color: var(--text-faint); overflow-wrap: anywhere; }
115
+ .ts-case-tail { display: flex; flex-wrap: wrap; gap: var(--sp-1); justify-content: flex-end; }
116
+
117
+ /* --- the closed OWASP set ------------------------------------------------ */
118
+ /* TEN ROWS, ALWAYS. An `unchecked` row keeps its slot and carries its reason;
119
+ it is drawn quieter than a FOUND row and it is never drawn as absent. */
120
+ .ts-owasp {
121
+ display: grid;
122
+ grid-template-columns: 64px auto minmax(0, 1fr);
123
+ align-items: start;
124
+ gap: var(--sp-2);
125
+ padding: var(--sp-2) 0;
126
+ border-top: 1px solid var(--line-soft);
127
+ }
128
+ .ts-owasp:first-of-type { border-top: 0; }
129
+ .ts-owasp-id { font-family: var(--mono); font-size: 12px; font-weight: 600; }
130
+ .ts-owasp-mid { display: grid; gap: 3px; min-width: 0; }
131
+ .ts-owasp-name { font-size: 13px; }
132
+ .ts-owasp-unchecked { font-size: 12px; color: var(--text-dim); overflow-wrap: anywhere; }