@worca/app 0.1.0 → 1.0.0-rc.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.
- package/LICENSE +21 -0
- package/README.md +186 -364
- package/package.json +1 -2
- package/ui/public/app.js +4159 -964
- package/ui/public/diff-view.mjs +151 -0
- package/ui/public/index.html +366 -136
- package/ui/public/style.css +1114 -143
- package/ui/server.mjs +36 -0
package/ui/public/style.css
CHANGED
|
@@ -25,6 +25,20 @@
|
|
|
25
25
|
--amber-bg:#FCE8C8; --amber:#E6962A; --amber-ink:#A66510;
|
|
26
26
|
--seq:#B7B7BC;
|
|
27
27
|
|
|
28
|
+
/* Question/ask amber wash (design §9, C3). --amber-bg is the SOLID amber; this
|
|
29
|
+
is the pale field it sits on. Task 11 adds --amber-wash-2/--amber-line/
|
|
30
|
+
--radio-ring beside it. */
|
|
31
|
+
--amber-wash:#FEF7EC;
|
|
32
|
+
|
|
33
|
+
/* Question panel (design §9): the remaining literals in the Running mockup that
|
|
34
|
+
no existing token already carries. The two hexes §9 also lists as "new" are
|
|
35
|
+
NOT added — they are already the values of --violet (:24) and --peach-ink
|
|
36
|
+
(:21); use those tokens.
|
|
37
|
+
Do NOT name those two hexes here, or anywhere else in this stylesheet: Task 12
|
|
38
|
+
asserts each appears EXACTLY ONCE, and its regex reads the raw file, so a
|
|
39
|
+
mention inside a comment counts as a second occurrence and reds the test. */
|
|
40
|
+
--amber-wash-2:#FEFAF3; --amber-line:#F5D9A8; --radio-ring:#D6D6D2;
|
|
41
|
+
|
|
28
42
|
--r-card:24px;
|
|
29
43
|
--r-ctrl:14px;
|
|
30
44
|
--shadow:0 6px 28px rgba(25,25,27,.05), 0 1px 2px rgba(25,25,27,.04);
|
|
@@ -188,9 +202,6 @@ body{
|
|
|
188
202
|
.child-q.ok { color: var(--green); font-size: 12px; animation: none; }
|
|
189
203
|
.child-q.bad { color: var(--red); font-size: 12px; animation: none; }
|
|
190
204
|
|
|
191
|
-
/* Overview cards are clickable to focus */
|
|
192
|
-
#run-list .run-card .run-top { cursor: pointer; }
|
|
193
|
-
|
|
194
205
|
.side-project{margin:0 4px 22px;padding-bottom:22px;border-bottom:1px solid var(--line);}
|
|
195
206
|
.side-project .sp-label{display:block;font-size:11px;font-weight:600;letter-spacing:.08em;
|
|
196
207
|
text-transform:uppercase;color:var(--ink-3);margin:0 4px 8px;}
|
|
@@ -209,12 +220,22 @@ body{
|
|
|
209
220
|
|
|
210
221
|
/* ---------- Main ---------- */
|
|
211
222
|
.main{flex:1;min-width:0;padding:26px 32px 40px;overflow-y:auto;}
|
|
212
|
-
/* History
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
223
|
+
/* History becomes a two-screen track: .main stops scrolling and becomes the
|
|
224
|
+
bounded column, the view takes the remainder, and each screen owns its own
|
|
225
|
+
scrollport. Dropping the container's TOP padding is what lets the sticky pills
|
|
226
|
+
toolbar + per-project headers pin flush to the very top of that scrollport —
|
|
227
|
+
without it, .main's 26px top padding leaves a band above the stuck header
|
|
228
|
+
where scrolled cards peek through (the reported bug). The inset is re-applied
|
|
229
|
+
on the topbar (below) so the unscrolled layout is unchanged.
|
|
230
|
+
The compact top-nav (<1080px) is a SIBLING above the views inside .main, so a
|
|
231
|
+
plain height:100% here would push the track past the viewport and
|
|
232
|
+
overflow:hidden would clip both screens' bottoms off-screen. */
|
|
233
|
+
body.view-history .main{display:flex;flex-direction:column;overflow:hidden;padding:0;}
|
|
234
|
+
/* .main's 32px gutter goes with padding:0, so the compact top-nav (<1080px, a
|
|
235
|
+
SIBLING of the views inside .main) must re-apply it or it lands 20px left of
|
|
236
|
+
the list content, which keeps its own 32px on .hist-screen. flex:0 0 auto
|
|
237
|
+
stops the wrapped 12-button nav from being squeezed once .main is a column. */
|
|
238
|
+
body.view-history .topnav{margin:12px 32px 0;flex:0 0 auto;}
|
|
218
239
|
.topbar{display:flex;align-items:flex-start;justify-content:space-between;
|
|
219
240
|
gap:24px;margin-bottom:22px;}
|
|
220
241
|
.topbar h1{font-size:26px;font-weight:700;letter-spacing:-.025em;margin:0 0 4px;}
|
|
@@ -273,7 +294,7 @@ body.view-history .main{padding-top:0;}
|
|
|
273
294
|
.hint{display:block;color:var(--ink-3);font-size:12px;margin-top:7px;line-height:1.45;}
|
|
274
295
|
.hint.err{color:var(--red-ink);}
|
|
275
296
|
|
|
276
|
-
.input,.select,.textarea,
|
|
297
|
+
.input,.select,.textarea,.ta-hl-back,
|
|
277
298
|
input[type="text"],input[type="number"],textarea,select{
|
|
278
299
|
width:100%;font-family:inherit;font-size:14px;color:var(--ink);
|
|
279
300
|
background:var(--field);border:1.5px solid transparent;border-radius:var(--r-ctrl);
|
|
@@ -362,6 +383,78 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
362
383
|
.file .state{color:var(--ink-3);font-size:12.5px;}
|
|
363
384
|
.file-load{display:inline-block;margin-top:8px;}
|
|
364
385
|
|
|
386
|
+
/* extra-file pills: one removable pill per selected file, under the picker */
|
|
387
|
+
.extras-pills{display:flex;flex-wrap:wrap;gap:7px;margin-top:9px;}
|
|
388
|
+
.extra-pill{display:inline-flex;align-items:center;gap:5px;background:var(--field);border:1px solid var(--line-2);
|
|
389
|
+
color:var(--ink-2);font-weight:600;font-size:12px;padding:4px 6px 4px 12px;border-radius:999px;max-width:260px;}
|
|
390
|
+
.extra-pill-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
391
|
+
.extra-pill-x{border:0;background:transparent;color:var(--ink-3);cursor:pointer;font-family:inherit;
|
|
392
|
+
font-size:14px;line-height:1;padding:3px 6px;border-radius:50%;transition:.15s;}
|
|
393
|
+
.extra-pill-x:hover{color:var(--red-ink);background:var(--red-bg);}
|
|
394
|
+
|
|
395
|
+
/* @-mention popup: attached-file completions anchored under the prompt caret */
|
|
396
|
+
.mention-popup{position:fixed;z-index:70;min-width:180px;max-width:320px;max-height:210px;overflow-y:auto;
|
|
397
|
+
background:var(--panel);border:1px solid var(--line-2);border-radius:12px;box-shadow:var(--shadow);padding:5px;}
|
|
398
|
+
.mention-item{display:block;width:100%;text-align:left;border:0;background:transparent;color:var(--ink-2);
|
|
399
|
+
font-family:inherit;font-weight:500;font-size:12.5px;padding:7px 10px;border-radius:8px;cursor:pointer;
|
|
400
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
401
|
+
.mention-item:hover{background:var(--field);}
|
|
402
|
+
.mention-item.sel{background:var(--field);color:var(--ink);}
|
|
403
|
+
|
|
404
|
+
/* @-mention highlighting: a textarea cannot colour part of its own text, so a
|
|
405
|
+
backdrop mirrors the text underneath it and paints the valid mentions. The
|
|
406
|
+
textarea keeps its glyphs (and its caret, selection, spellcheck and undo
|
|
407
|
+
stack) but renders them transparent; the backdrop carries the field fill it
|
|
408
|
+
gave up. .mention-ok sets COLOUR ONLY — any metric-affecting property would
|
|
409
|
+
advance the backdrop's glyphs differently and drift the two layers apart.
|
|
410
|
+
|
|
411
|
+
Two box-model choices, both load-bearing, neither optional:
|
|
412
|
+
|
|
413
|
+
1. The wrapper is inline-block, NOT block. A textarea is inline-block by UA
|
|
414
|
+
default, so the inline margin-top:11px on #prompt/#promptMarkdown does not
|
|
415
|
+
collapse today; a block wrapper would turn it into a collapsible block
|
|
416
|
+
margin that escapes through .source-pane and .field (neither has a border
|
|
417
|
+
or padding to stop it) and merges with the preceding margin-bottom:18px,
|
|
418
|
+
deleting the gap.
|
|
419
|
+
2. It deliberately does NOT set vertical-align. An inline-block with no
|
|
420
|
+
in-flow line boxes takes its baseline from its bottom margin edge
|
|
421
|
+
(CSS 2.1 s10.8.1), and the only in-flow child here is a display:block
|
|
422
|
+
textarea — whose internal content is a separate rendering context and
|
|
423
|
+
contributes no line box to the wrapper. So the wrapper resolves exactly
|
|
424
|
+
where the bare textarea did (whose UA overflow:auto gave it the same
|
|
425
|
+
rule). vertical-align:top would instead align it to the line-box top,
|
|
426
|
+
deleting the strut descent below it and shrinking #prompt-pane and
|
|
427
|
+
#markdown-pane by ~6px. Making the textarea display:block removes the
|
|
428
|
+
line box INSIDE the wrapper, which is what keeps the backdrop's height
|
|
429
|
+
equal to the textarea's. */
|
|
430
|
+
.ta-hl{position:relative;display:inline-block;width:100%;}
|
|
431
|
+
.ta-hl > textarea.textarea,
|
|
432
|
+
.ta-hl > textarea.textarea:focus{display:block;position:relative;z-index:1;
|
|
433
|
+
background:transparent;color:transparent;caret-color:var(--ink);}
|
|
434
|
+
.ta-hl > textarea.textarea::selection{background:rgba(25,25,27,.16);}
|
|
435
|
+
/* font-weight/style/variant/stretch are the ONLY text-layout properties the two
|
|
436
|
+
layers do not already share: Chrome's UA `font: -webkit-small-control`
|
|
437
|
+
shorthand on <textarea> resets them, while this div would inherit them from
|
|
438
|
+
body (Poppins ships 400/500/600/700, so this is not hypothetical). Pin them to
|
|
439
|
+
the textarea's reset values. Do NOT pin letter-spacing/word-spacing/
|
|
440
|
+
text-indent/text-align/text-transform/tab-size — those are outside the font
|
|
441
|
+
shorthand, so both layers inherit them, and pinning would CREATE the
|
|
442
|
+
divergence it means to prevent. */
|
|
443
|
+
.ta-hl-back{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden;
|
|
444
|
+
line-height:1.5;white-space:pre-wrap;overflow-wrap:break-word;border-color:transparent;
|
|
445
|
+
font-weight:400;font-style:normal;font-variant:normal;font-stretch:normal;}
|
|
446
|
+
.ta-hl:focus-within .ta-hl-back{background:#fff;}
|
|
447
|
+
.mention-ok{color:var(--blue-ink);}
|
|
448
|
+
|
|
449
|
+
/* High Contrast forces the textarea's transparent text back to CanvasText while
|
|
450
|
+
its background stays transparent, so both layers' glyphs would paint at once,
|
|
451
|
+
and it flattens --blue-ink to black anyway. Opt the whole trick out. */
|
|
452
|
+
@media (forced-colors: active){
|
|
453
|
+
.ta-hl-back{display:none;}
|
|
454
|
+
.ta-hl > textarea.textarea,
|
|
455
|
+
.ta-hl > textarea.textarea:focus{color:CanvasText;background:Canvas;}
|
|
456
|
+
}
|
|
457
|
+
|
|
365
458
|
/* switch */
|
|
366
459
|
.switch-row{display:flex;align-items:center;gap:12px;}
|
|
367
460
|
.switch{width:44px;height:26px;border-radius:999px;background:var(--line-2);position:relative;
|
|
@@ -546,12 +639,22 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
546
639
|
|
|
547
640
|
/* ---------- Running ---------- */
|
|
548
641
|
.run-list{display:flex;flex-direction:column;gap:18px;}
|
|
642
|
+
|
|
643
|
+
/* "N pipelines are waiting on your answers" — inert status line above the list
|
|
644
|
+
(design D14). Amber family; the circle inverts to --panel so it still reads
|
|
645
|
+
against the pale wash. */
|
|
646
|
+
.run-ask-banner{display:flex;align-items:center;gap:12px;margin:0 0 18px;padding:13px 18px;
|
|
647
|
+
background:var(--amber-wash);border:1px solid var(--amber);border-radius:16px;}
|
|
648
|
+
.run-ask-banner[hidden]{display:none;} /* author display:flex beats the UA [hidden] rule */
|
|
649
|
+
.run-ask-banner .rab-mark{flex:0 0 auto;display:flex;align-items:center;justify-content:center;
|
|
650
|
+
width:26px;height:26px;border-radius:50%;background:var(--panel);
|
|
651
|
+
color:var(--amber-ink);font-weight:700;font-size:14px;}
|
|
652
|
+
.run-ask-banner .rab-text{flex:1;font-weight:500;font-size:13px;color:var(--amber-ink);}
|
|
653
|
+
|
|
549
654
|
.run-card{padding:22px 24px;}
|
|
550
|
-
.run-top{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:18px;}
|
|
551
655
|
.run-title{font-weight:700;font-size:16px;letter-spacing:-.01em;display:flex;align-items:center;gap:10px;}
|
|
552
656
|
.run-title .hash{font-family:var(--mono);font-size:11.5px;color:var(--ink-3);font-weight:500;}
|
|
553
657
|
.run-title.title-provisional{opacity:.65;font-style:italic;}
|
|
554
|
-
.run-meta{display:flex;align-items:center;gap:10px;color:var(--ink-3);font-size:12.5px;margin-top:4px;}
|
|
555
658
|
.pill-run{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;border-radius:999px;
|
|
556
659
|
font-weight:600;font-size:12.5px;white-space:nowrap;}
|
|
557
660
|
.pill-run .pdot{width:7px;height:7px;border-radius:50%;animation:pulse 1.3s ease-in-out infinite;}
|
|
@@ -574,20 +677,15 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
574
677
|
/* empty state for the running list */
|
|
575
678
|
.run-empty{color:var(--ink-3);padding:24px;text-align:center;}
|
|
576
679
|
|
|
577
|
-
.run-foot{display:flex;align-items:center;gap:10px;}
|
|
578
680
|
.chip{background:var(--field);color:var(--ink-2);font-weight:600;font-size:12px;padding:7px 13px;border-radius:999px;}
|
|
579
|
-
.chip.qcount{background:var(--amber-bg);color:var(--amber-ink);}
|
|
580
|
-
.btn-stop.sm{margin-left:auto;padding:8px 15px;font-size:12px;}
|
|
581
|
-
.btn-pause.sm{margin-left:auto;padding:8px 15px;font-size:12px;}
|
|
582
|
-
.btn-resume.sm{margin-left:auto;padding:8px 15px;font-size:12px;}
|
|
583
|
-
.btn-pause.sm + .btn-stop.sm{margin-left:0;}
|
|
584
681
|
|
|
585
682
|
/* expand to live log */
|
|
586
683
|
.btn-expand{margin-left:auto;display:inline-flex;align-items:center;gap:7px;background:var(--field);
|
|
587
684
|
border:none;border-radius:999px;padding:8px 15px;font-family:inherit;font-weight:600;font-size:12px;
|
|
588
685
|
color:var(--ink-2);cursor:pointer;transition:background .15s;}
|
|
589
686
|
.btn-expand:hover{background:var(--line-2);}
|
|
590
|
-
|
|
687
|
+
/* The `.btn-expand + .btn-stop.sm` reset that sat here keyed off a `.btn-stop.sm`
|
|
688
|
+
rule the card redesign removed; nothing emits that pair any more. */
|
|
591
689
|
.btn-expand .chev{transition:transform .2s;}
|
|
592
690
|
.btn-expand[aria-expanded="true"] .chev{transform:rotate(180deg);}
|
|
593
691
|
.run-log{margin-top:16px;}
|
|
@@ -611,7 +709,6 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
611
709
|
/* run card: pills drop to a full-width second row under "Live log" (order puts
|
|
612
710
|
the bar after the autoscroll switch so row 1 stays label ⟷ switch) */
|
|
613
711
|
.run-log-head .log-filters{order:1;flex-basis:100%;}
|
|
614
|
-
.logs-panel .log-filters{margin-top:8px;}
|
|
615
712
|
|
|
616
713
|
/* needs-attention card + paused stage */
|
|
617
714
|
.run-card.attention{border:1.5px solid var(--amber);box-shadow:0 0 0 4px var(--amber-bg),var(--shadow);}
|
|
@@ -619,32 +716,87 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
619
716
|
color:var(--amber-ink);font-size:11px;font-weight:700;padding:3px 9px;border-radius:999px;vertical-align:middle;}
|
|
620
717
|
.attn-flag svg{stroke:var(--amber-ink);}
|
|
621
718
|
|
|
622
|
-
/* ---------- Questions panel ---------- */
|
|
623
|
-
.
|
|
624
|
-
.qpanel
|
|
719
|
+
/* ---------- Questions panel (run card + run detail) ---------- */
|
|
720
|
+
/* The CARD is the base (design §4.3: 19px number circles, 12.5px options); the
|
|
721
|
+
detail screen scales up through `.rd-questions .qpanel …` (§5.4), which wins on
|
|
722
|
+
SPECIFICITY, so this block's position in the file does not matter.
|
|
723
|
+
The legacy `q-`-prefixed twin selectors that used to share every rule here had
|
|
724
|
+
ZERO emitters left in ui/ and test/ and are dropped with this rewrite. They are
|
|
725
|
+
deliberately NOT spelled out below, even though the suite's sweep strips comments
|
|
726
|
+
first — keeping the prose free of them means a future sweep that forgets to
|
|
727
|
+
strip still passes. */
|
|
728
|
+
.qpanel{margin-top:18px;padding:14px 16px 13px;background:var(--amber-wash);
|
|
729
|
+
border:1px solid var(--amber-bg);border-radius:14px;}
|
|
730
|
+
.qpanel-head{display:flex;align-items:center;gap:11px;}
|
|
625
731
|
.qpanel-head svg{stroke:var(--amber-ink);flex:0 0 auto;}
|
|
626
|
-
.qpanel-head b{
|
|
627
|
-
.qpanel-head .qcount{margin-left:auto;background:var(--amber-bg);color:var(--amber-ink);
|
|
628
|
-
font-weight:700;font-size:11.5px;padding:
|
|
629
|
-
.qblock
|
|
630
|
-
.
|
|
631
|
-
|
|
632
|
-
.qtext .qn{flex:0 0 auto;width:
|
|
633
|
-
font-size:
|
|
634
|
-
|
|
635
|
-
.
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
.
|
|
641
|
-
|
|
642
|
-
.
|
|
643
|
-
.
|
|
644
|
-
.
|
|
645
|
-
|
|
646
|
-
.
|
|
647
|
-
.
|
|
732
|
+
.qpanel-head b{flex:1;min-width:0;font-weight:600;font-size:12.5px;color:var(--amber-ink);}
|
|
733
|
+
.qpanel-head .qcount{margin-left:auto;flex:0 0 auto;background:var(--amber-bg);color:var(--amber-ink);
|
|
734
|
+
font-weight:700;font-size:11.5px;padding:4px 10px;border-radius:999px;}
|
|
735
|
+
.qblock{padding:13px 0 0;}
|
|
736
|
+
.qtext{font-weight:500;font-size:13px;margin:0 0 9px;display:flex;align-items:flex-start;
|
|
737
|
+
gap:9px;line-height:1.45;}
|
|
738
|
+
.qtext .qn{flex:0 0 auto;width:19px;height:19px;border-radius:50%;background:var(--ink);color:#fff;
|
|
739
|
+
font-family:var(--mono);font-size:10.5px;font-weight:600;display:grid;place-items:center;margin-top:1px;}
|
|
740
|
+
/* the option column and the free-text field line up under the number circle */
|
|
741
|
+
.qopts{display:flex;flex-direction:column;align-items:stretch;gap:7px;margin:0 0 7px;padding-left:28px;}
|
|
742
|
+
.qopt{display:flex;align-items:center;gap:8px;font-family:inherit;font-weight:500;font-size:12.5px;
|
|
743
|
+
color:var(--ink);background:var(--panel);border:1.5px solid var(--line);border-radius:11px;
|
|
744
|
+
padding:10px 14px;cursor:pointer;transition:.14s;text-align:left;width:100%;}
|
|
745
|
+
/* Radio + white check drawn entirely in CSS: renderClarifyBody keeps emitting a
|
|
746
|
+
bare <button> with one text node (§4.3 — styling only, no markup change), and
|
|
747
|
+
an inline data-URI background needs no extra element and no positioning context. */
|
|
748
|
+
.qopt::before{content:'';flex:0 0 auto;width:15px;height:15px;border-radius:50%;
|
|
749
|
+
border:1.5px solid var(--radio-ring);background:var(--panel);}
|
|
750
|
+
.qopt.sel::before{border-color:var(--green);
|
|
751
|
+
background:var(--green) center/9px 9px no-repeat url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'><path d='M5 13l4 4L19 7'/></svg>");}
|
|
752
|
+
.qopt:hover{border-color:var(--ink-3);}
|
|
753
|
+
.qopt.sel{background:var(--green-bg);color:var(--ink);border-color:var(--green);}
|
|
754
|
+
.qopt:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
755
|
+
.qfree{width:100%;font-family:inherit;font-size:12.5px;color:var(--ink);background:var(--field);
|
|
756
|
+
border:1.5px solid var(--line);border-radius:11px;padding:10px 14px;transition:.14s;}
|
|
757
|
+
.qfree::placeholder{color:var(--ink-3);}
|
|
758
|
+
/* `.has` is toggled by renderClarifyBody's own input handler the moment the field
|
|
759
|
+
holds a non-empty, non-option value — the green border IS that state. */
|
|
760
|
+
.qfree:focus{outline:none;background:var(--panel);border-color:var(--green);}
|
|
761
|
+
.qfree.has{background:var(--panel);border-color:var(--green);}
|
|
762
|
+
.qblock > .qfree{margin-left:28px;width:calc(100% - 28px);}
|
|
763
|
+
.qpanel-foot{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:14px;}
|
|
764
|
+
.qpanel-foot .btn-go{padding:9px 18px;font-size:12px;gap:8px;}
|
|
765
|
+
/* secondary "Open run" — card only (§4.3) */
|
|
766
|
+
.qopen{padding:9px 16px;border:1.5px solid var(--line-2);border-radius:999px;background:var(--panel);
|
|
767
|
+
font-family:inherit;font-weight:600;font-size:12px;color:var(--ink);cursor:pointer;transition:.14s;}
|
|
768
|
+
.qopen:hover{background:var(--field);}
|
|
769
|
+
.qopen:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
770
|
+
|
|
771
|
+
/* ---- run-detail variant: the mockup's larger metrics (design §5.4) ---- */
|
|
772
|
+
/* NO `animation` here: Task 6 already put `animation:wr-rise …` on the
|
|
773
|
+
`.rd-questions` WRAPPER (and neutralizes it under reduced motion). Animating
|
|
774
|
+
the child too nests the two transforms — 20px of travel and opacity squared.
|
|
775
|
+
`margin-top:0` also stays where Task 6 put it (its EOF rule comes LATER in the
|
|
776
|
+
file, so it still wins); this rule must not restate it. */
|
|
777
|
+
.rd-questions .qpanel{padding:22px 24px 20px;background:var(--amber-wash-2);
|
|
778
|
+
border:1.5px solid var(--amber-line);border-radius:var(--r-card);}
|
|
779
|
+
.rd-questions .qpanel-head{gap:12px;padding-bottom:16px;border-bottom:1px solid var(--amber-line);}
|
|
780
|
+
.rd-questions .qpanel-head b{font-size:15px;color:var(--ink);}
|
|
781
|
+
.rd-questions .qpanel-head .qcount{font-weight:600;font-size:11.5px;padding:5px 12px;}
|
|
782
|
+
.rd-questions .qblock{padding-top:18px;}
|
|
783
|
+
.rd-questions .qtext{font-weight:600;font-size:14px;line-height:1.5;gap:11px;margin-bottom:12px;}
|
|
784
|
+
.rd-questions .qtext .qn{width:22px;height:22px;font-size:11.5px;}
|
|
785
|
+
/* the detail panel is wide enough to drop the number-circle indent */
|
|
786
|
+
.rd-questions .qopts{gap:9px;margin:12px 0 0;padding-left:0;}
|
|
787
|
+
.rd-questions .qblock > .qfree{margin-left:0;width:100%;padding:13px 16px;border-radius:13px;font-size:13.5px;}
|
|
788
|
+
.rd-questions .qopt{gap:11px;padding:13px 16px;border-radius:13px;font-size:13.5px;}
|
|
789
|
+
.rd-questions .qopt::before{width:17px;height:17px;}
|
|
790
|
+
.rd-questions .qopt.sel::before{background-size:10px 10px;}
|
|
791
|
+
.rd-questions .qpanel-foot{margin-top:20px;padding-top:16px;border-top:1px solid var(--amber-line);}
|
|
792
|
+
.rd-questions .qpanel-foot .btn-go{padding:13px 22px;font-size:13.5px;gap:9px;}
|
|
793
|
+
|
|
794
|
+
/* "N of M answered" (§5.4): left slot of the footer, submit on the right. The
|
|
795
|
+
base .qpanel-foot is justify-content:flex-end — with a counter present the row
|
|
796
|
+
becomes space-between, and `margin-right:auto` on the counter achieves that
|
|
797
|
+
WITHOUT a second .qpanel-foot rule that the footer test would then contradict. */
|
|
798
|
+
.qanswered{margin-right:auto;font:500 11.5px var(--mono);color:var(--ink-3);}
|
|
799
|
+
.rd-questions .qanswered{font-size:12.5px;}
|
|
648
800
|
|
|
649
801
|
/* ---------- Gate (cycle gate) ---------- */
|
|
650
802
|
.gate-intro{font-size:13px;color:var(--ink-2);margin:0 0 14px;line-height:1.5;}
|
|
@@ -666,15 +818,8 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
666
818
|
.gate-actions{display:flex;gap:10px;flex-wrap:wrap;}
|
|
667
819
|
.gate-actions .btn{flex:1 1 auto;}
|
|
668
820
|
|
|
669
|
-
/*
|
|
670
|
-
.
|
|
671
|
-
.hist-row:first-child{border-top:none;}
|
|
672
|
-
.hist-row .h-meta{flex:1;min-width:0;}
|
|
673
|
-
.hist-row .h-meta b{display:block;font-weight:600;font-size:14.5px;}
|
|
674
|
-
.hist-row .h-meta small{color:var(--ink-3);font-size:12px;}
|
|
675
|
-
.hist-row .hash{font-family:var(--mono);font-size:11.5px;color:var(--ink-3);}
|
|
676
|
-
|
|
677
|
-
/* status badge — shared family colors (app.js historyBadge: green/red/running) */
|
|
821
|
+
/* status badge — shared family colors (green/red/running/waiting/violet), used by
|
|
822
|
+
guardrails-view.mjs, models-view.mjs and the chat-connection state pill */
|
|
678
823
|
.badge{display:inline-flex;align-items:center;font-size:10.5px;font-weight:700;letter-spacing:.06em;
|
|
679
824
|
text-transform:uppercase;padding:5px 10px;border-radius:8px;flex:0 0 auto;white-space:nowrap;
|
|
680
825
|
background:var(--field);color:var(--ink-3);}
|
|
@@ -686,21 +831,19 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
686
831
|
.badge.hist-retained-badge{background:var(--amber-bg);color:var(--amber-ink);}
|
|
687
832
|
.badge.hist-retained-badge[hidden]{display:none;}
|
|
688
833
|
|
|
689
|
-
/* ---------- History cards (
|
|
834
|
+
/* ---------- History cards (navigate to the detail screen) ---------- */
|
|
690
835
|
.hist-card{padding:18px 22px;}
|
|
691
|
-
|
|
836
|
+
/* flex-start, not center: the card is now three stacked lines (title, meta,
|
|
837
|
+
branch) and the icon/aside must pin to the top of that block. */
|
|
838
|
+
.hist-head{display:flex;align-items:flex-start;gap:13px;cursor:pointer;}
|
|
692
839
|
.hist-head:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
693
840
|
.hist-head .h-meta{flex:1;min-width:0;}
|
|
694
|
-
|
|
695
|
-
.hist-head .h-meta
|
|
841
|
+
/* one line, ellipsized (the `flex:1;min-width:0` above is what makes it work). */
|
|
842
|
+
.hist-head .h-meta b{display:block;font-weight:600;font-size:14.5px;
|
|
843
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
696
844
|
.hist-head .hash{font-family:var(--mono);font-size:11.5px;color:var(--ink-3);}
|
|
697
|
-
.hist-head .chev{color:var(--ink-3);transition:transform .2s;flex:0 0 auto;}
|
|
698
|
-
.hist-head[aria-expanded="true"] .chev{transform:rotate(180deg);}
|
|
699
845
|
.hist-head .h-meta b{cursor:pointer;}
|
|
700
846
|
.hist-head .h-meta b:hover{text-decoration:underline;}
|
|
701
|
-
.hist-detail{margin-top:16px;padding-top:16px;border-top:1px solid var(--line);}
|
|
702
|
-
.hist-detail[hidden]{display:none;}
|
|
703
|
-
.hist-detail .detail-error{color:var(--red-ink);font-size:12.5px;}
|
|
704
847
|
.retained-banner{margin:0 0 18px;padding:16px 18px;border:1.5px solid var(--amber);
|
|
705
848
|
border-radius:14px;background:var(--amber-bg);color:var(--amber-ink);font-size:12.5px;line-height:1.55;}
|
|
706
849
|
.retained-banner[hidden]{display:none;}
|
|
@@ -713,15 +856,8 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
713
856
|
white-space:pre-wrap;word-break:break-all;}
|
|
714
857
|
.retained-banner a{color:var(--amber-ink);font-weight:700;}
|
|
715
858
|
.hist-empty{color:var(--ink-3);font-size:13px;padding:22px 4px;text-align:center;}
|
|
716
|
-
.hist-section{margin-top:16px;padding-top:16px;border-top:1px solid var(--line);}
|
|
717
|
-
.hist-section-title{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--ink-3);font-weight:700;margin-bottom:10px;}
|
|
718
|
-
.hist-answer{font-size:12.5px;color:var(--ink-2);margin-top:6px;}
|
|
719
859
|
|
|
720
860
|
/* ---------- History project-filter pills ---------- */
|
|
721
|
-
/* Re-apply (inside the scrolling view) the top inset that body.view-history
|
|
722
|
-
removed from .main, so the unscrolled layout is unchanged while the scroll
|
|
723
|
-
container itself has no top padding for position:sticky to fight. */
|
|
724
|
-
.view[data-view="history"]{padding-top:26px;}
|
|
725
861
|
/* The project-filter pills become a persistent sticky toolbar pinned to the top
|
|
726
862
|
of the scroll area while the list scrolls underneath. Opaque background +
|
|
727
863
|
z-index above the per-project header (z-index:3) so scrolled cards never
|
|
@@ -753,6 +889,17 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
753
889
|
::-webkit-scrollbar-track{background:transparent;}
|
|
754
890
|
|
|
755
891
|
/* ---------- reduced motion ---------- */
|
|
892
|
+
/* DECISION (D7). Spec §8 proposes extending this block to a blanket
|
|
893
|
+
`animation:none`. We do NOT: D7 keeps the Running view behaviorally untouched,
|
|
894
|
+
and the run-graph's own reduced-motion block (1240-1245) already neutralizes
|
|
895
|
+
its pulses with deliberate box-shadow substitutes that a blanket rule would
|
|
896
|
+
leave orphaned. Do not add the History-redesign animations to the list below,
|
|
897
|
+
either — `@media` contributes no specificity, so a (0,1,0) `animation:none`
|
|
898
|
+
here loses on source order to the (0,1,0) `animation:shipit-…` rules appended
|
|
899
|
+
at EOF. The four names below work only because each is declared *before* this
|
|
900
|
+
block. The ship-it animations are neutralized by a second
|
|
901
|
+
`@media (prefers-reduced-motion: reduce)` block placed AFTER them at the end
|
|
902
|
+
of the file. */
|
|
756
903
|
@media (prefers-reduced-motion: reduce){
|
|
757
904
|
.pdot,.cur,.child-dot,.child-q{animation:none;}
|
|
758
905
|
*{transition:none !important;}
|
|
@@ -801,27 +948,42 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
801
948
|
}
|
|
802
949
|
|
|
803
950
|
/* ---------- per-pipeline cost (per-node cost is the graph's .nrun .cost) ---------- */
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
951
|
+
/* The `.run-meta .run-cost` pair that lived here went with `.run-meta` itself:
|
|
952
|
+
the redesigned card emits `.run-cost` inside `.rc-seg`, which owns its own
|
|
953
|
+
type scale and prints its separator as a real `.rc-dot` node. */
|
|
954
|
+
/* Edited IN PLACE, not appended: this selector is (0,2,0) and an appended bare
|
|
955
|
+
`.hist-total{…}` (0,1,0) would never win. The `margin-left:10px` is gone — the
|
|
956
|
+
v2 meta line is a flex row with its own gap. */
|
|
957
|
+
.h-meta .hist-total{font-family:var(--mono);font-size:12.5px;font-weight:700;color:var(--ink);}
|
|
807
958
|
.h-meta .hist-total:empty{display:none;}
|
|
808
959
|
|
|
809
960
|
/* ---------- per-pipeline duration (twin of cost) ---------- */
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
.h-meta .hist-time{font-family:var(--mono);font-size:
|
|
961
|
+
/* `.run-meta .run-time` removed with its cost twin above, for the same reason. */
|
|
962
|
+
/* Same in-place treatment as `.h-meta .hist-total` above. */
|
|
963
|
+
.h-meta .hist-time{font-family:var(--mono);font-size:12.5px;font-weight:700;color:var(--ink);}
|
|
813
964
|
.h-meta .hist-time:empty{display:none;}
|
|
814
965
|
|
|
815
966
|
/* Branch name under the date/cost (left column). */
|
|
816
|
-
.h-meta .hist-branch{display:
|
|
817
|
-
.h-meta .hist-branch
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
.hist-
|
|
967
|
+
.h-meta .hist-branch{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:12px;font-weight:600;color:var(--ink-2);margin-top:4px;}
|
|
968
|
+
.h-meta .hist-branch[hidden]{display:none;} /* author display:flex beats the UA [hidden] rule */
|
|
969
|
+
.hist-branch .hist-branch-src{color:var(--ink-3);font-weight:500;}
|
|
970
|
+
.hist-branch .hist-branch-arrow{flex:0 0 auto;color:var(--ink-3);}
|
|
971
|
+
.hist-branch .hist-branch-arrow[hidden]{display:none;}
|
|
972
|
+
.hist-branch-copy{display:inline-flex;align-items:center;justify-content:center;padding:3px;background:none;border:0;border-radius:6px;color:var(--ink-3);cursor:pointer;}
|
|
973
|
+
.hist-branch-copy:hover{background:var(--line);color:var(--ink);}
|
|
974
|
+
.hist-branch-copy .ico-check{display:none;}
|
|
975
|
+
.hist-branch-copy.copied .ico-copy{display:none;}
|
|
976
|
+
.hist-branch-copy.copied .ico-check{display:block;color:var(--green-ink);}
|
|
977
|
+
|
|
978
|
+
/* Right-side cluster on the card: Create PR + the open-detail chevron button.
|
|
979
|
+
`align-self:center` (not the parent's `align-items:flex-start`) pins the cluster
|
|
980
|
+
to the card's vertical middle, the same escape hatch `.hist-card .hist-sic` uses
|
|
981
|
+
on the other side of the row. */
|
|
982
|
+
.hist-aside{display:flex;align-items:center;align-self:center;gap:10px;flex:0 0 auto;}
|
|
983
|
+
/* Base rule only. The v2 card hosts `.hist-diff` INSIDE `.hist-diff-pill`, whose
|
|
984
|
+
appended `.hist-diff-pill .hist-diff` (0,2,0) outranks this; the tints come from
|
|
985
|
+
the bare `.diff-add`/`.diff-del` rules further down. */
|
|
821
986
|
.hist-diff{display:inline-flex;gap:6px;font-family:var(--mono);font-size:12px;font-weight:700;}
|
|
822
|
-
.hist-diff:empty{display:none;}
|
|
823
|
-
.hist-diff .diff-add{color:var(--green-ink);}
|
|
824
|
-
.hist-diff .diff-del{color:var(--red-ink);}
|
|
825
987
|
|
|
826
988
|
.hist-merge{font-size:10.5px;font-weight:700;letter-spacing:.04em;padding:3px 8px;border-radius:999px;white-space:nowrap;}
|
|
827
989
|
.hist-merge[hidden]{display:none;}
|
|
@@ -831,26 +993,29 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
831
993
|
|
|
832
994
|
.hist-pr{padding:6px 12px;font-size:12px;flex:0 0 auto;}
|
|
833
995
|
.hist-pr[hidden]{display:none;}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
996
|
+
/* These three rules are the ONLY thing that styles a PR link, so the History
|
|
997
|
+
DETAIL header's `.hd-pr-link` joins the selector lists IN PLACE. Appending a
|
|
998
|
+
separate `.hd-pr-link{…}` at EOF instead would ship the detail link as a default
|
|
999
|
+
UA anchor — browser blue, underlined — and MERGED would lose its grey. */
|
|
1000
|
+
.hist-pr-link,.hd-pr-link{font-size:12px;font-weight:600;color:var(--green-ink);text-decoration:none;white-space:nowrap;}
|
|
1001
|
+
.hist-pr-link:hover,.hd-pr-link:hover{text-decoration:underline;}
|
|
1002
|
+
.hist-pr-link.merged,.hd-pr-link.merged{color:var(--muted, #888);}
|
|
1003
|
+
|
|
1004
|
+
/* Discard-worktree button. The class moved from the retired card accordion to the
|
|
1005
|
+
detail screen's banner block; nothing about it was card-position-dependent. */
|
|
842
1006
|
.hist-discard{display:inline-flex;align-items:center;padding:6px 12px;font-size:12px;
|
|
843
1007
|
color:var(--amber-ink);border-color:var(--amber);background:var(--amber-bg);}
|
|
844
1008
|
.hist-discard:hover:not(:disabled){background:var(--amber-bg);filter:brightness(.97);}
|
|
845
1009
|
.hist-discard:disabled{opacity:.6;cursor:default;}
|
|
846
1010
|
.hist-discard[hidden]{display:none;}
|
|
847
|
-
|
|
1011
|
+
/* This block is SHARED with the Plugins view's `.pl-remove`; the retired
|
|
1012
|
+
`.hist-delete` arms were removed from the selector lists, the block stays. */
|
|
1013
|
+
.pl-remove{display:inline-flex;align-items:center;gap:6px;background:var(--red-ink,#d9534f);
|
|
848
1014
|
border:1.5px solid var(--red-ink,#d9534f);color:#fff;font-family:inherit;font-weight:600;
|
|
849
1015
|
font-size:12px;padding:6px 12px;border-radius:8px;cursor:pointer;}
|
|
850
|
-
.
|
|
851
|
-
.
|
|
852
|
-
.
|
|
853
|
-
.hist-delete svg,.pl-remove svg{display:block;}
|
|
1016
|
+
.pl-remove:hover:not(:disabled){filter:brightness(0.95);}
|
|
1017
|
+
.pl-remove:disabled{opacity:.6;cursor:default;}
|
|
1018
|
+
.pl-remove svg{display:block;}
|
|
854
1019
|
|
|
855
1020
|
/* ========================================================================== */
|
|
856
1021
|
/* Pipeline Composer — drag/drop canvas, wires, palette, saved list */
|
|
@@ -1142,53 +1307,29 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
1142
1307
|
.run-flow .node.is-active .fan .fl{color:var(--blue-ink);}
|
|
1143
1308
|
@keyframes sqPulse{0%,100%{opacity:1;}50%{opacity:.38;}}
|
|
1144
1309
|
|
|
1145
|
-
/*
|
|
1146
|
-
.subs-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
.
|
|
1151
|
-
.
|
|
1152
|
-
.
|
|
1153
|
-
.
|
|
1154
|
-
.
|
|
1155
|
-
.
|
|
1156
|
-
.
|
|
1157
|
-
.
|
|
1158
|
-
.subs-panel[hidden]{display:none;}
|
|
1159
|
-
.subs-legend{display:flex;align-items:center;gap:18px;padding:12px 0 4px;font-size:11.5px;font-weight:600;color:var(--ink-3);}
|
|
1160
|
-
.subs-legend .lk{display:flex;align-items:center;gap:7px;}
|
|
1161
|
-
.subs-legend .sq{width:9px;height:9px;border-radius:2px;}
|
|
1162
|
-
.subs-legend .sq.on{background:var(--blue);}
|
|
1163
|
-
.subs-legend .sq.off{background:var(--ink-3);opacity:.5;}
|
|
1164
|
-
.subs-step{padding:13px 0;border-top:1px solid var(--line);}
|
|
1165
|
-
.subs-step:first-of-type{border-top:none;}
|
|
1166
|
-
.subs-step-head{display:flex;align-items:center;gap:10px;}
|
|
1167
|
-
.subs-step-head .dot{width:10px;height:10px;border-radius:50%;flex:0 0 auto;}
|
|
1168
|
-
.subs-step-head b{font-size:13.5px;font-weight:600;letter-spacing:-.01em;}
|
|
1169
|
-
.subs-step-head .subs-stat{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:999px;letter-spacing:.02em;text-transform:uppercase;}
|
|
1170
|
-
.subs-step-head .subs-stat.run{background:var(--blue-bg);color:var(--blue-ink);}
|
|
1171
|
-
.subs-step-head .subs-stat.done{background:var(--green-bg);color:var(--green-ink);}
|
|
1172
|
-
.subs-step-head .subs-stat.stop{background:var(--red-bg);color:var(--red-ink);}
|
|
1173
|
-
.subs-step-head .subs-n{margin-left:auto;font-size:11.5px;font-weight:600;color:var(--ink-3);}
|
|
1174
|
-
.subs-step .subs-empty{margin-top:8px;padding-left:5px;font-size:12px;font-weight:500;color:var(--ink-3);font-style:italic;}
|
|
1175
|
-
.subs-tree{list-style:none;margin:8px 0 0;padding:0 0 0 5px;}
|
|
1176
|
-
.subs-tree li{position:relative;padding:6px 0 6px 28px;font-size:12.5px;font-weight:500;color:var(--ink-2);display:flex;align-items:center;gap:9px;}
|
|
1177
|
-
.subs-tree li::before{content:"";position:absolute;left:5px;top:-3px;height:calc(50% + 3px);width:1.5px;background:var(--line-2);}
|
|
1178
|
-
.subs-tree li::after{content:"";position:absolute;left:5px;top:50%;width:15px;height:1.5px;background:var(--line-2);}
|
|
1179
|
-
.subs-tree li .led{width:7px;height:7px;border-radius:2px;flex:0 0 auto;background:var(--ink-3);opacity:.55;}
|
|
1180
|
-
.subs-tree li .led.on{background:var(--blue);opacity:1;}
|
|
1181
|
-
.subs-tree li .ag-name{min-width:0;}
|
|
1182
|
-
.subs-tree li .st{margin-left:auto;font-family:'JetBrains Mono',monospace;font-size:10px;font-weight:500;padding:2px 8px;border-radius:6px;white-space:nowrap;}
|
|
1183
|
-
.subs-tree li .st.done{background:var(--green-bg);color:var(--green-ink);}
|
|
1184
|
-
.subs-tree li .st.run{background:var(--blue-bg);color:var(--blue-ink);}
|
|
1185
|
-
.subs-tree li .st.stop{background:var(--red-bg);color:var(--red-ink);}
|
|
1310
|
+
/* Selector lists that used to pair the retired run-card tree with the History
|
|
1311
|
+
detail's Agents tab. `.subs-stat` is only ever styled here, so a bare appended
|
|
1312
|
+
`.subs-stat.stop{…}` would tie on specificity and still lose to this rule's
|
|
1313
|
+
ancestor scope — extend in place, never duplicate. Same for `.st`,
|
|
1314
|
+
`.agent-type-pill` and the full-row `.subs-skills` rule below. */
|
|
1315
|
+
.rd-ag-head .subs-stat,.hd-ag-head .subs-stat{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:999px;letter-spacing:.02em;text-transform:uppercase;}
|
|
1316
|
+
.rd-ag-head .subs-stat.run,.hd-ag-head .subs-stat.run{background:var(--blue-bg);color:var(--blue-ink);}
|
|
1317
|
+
.rd-ag-head .subs-stat.done,.hd-ag-head .subs-stat.done{background:var(--green-bg);color:var(--green-ink);}
|
|
1318
|
+
.rd-ag-head .subs-stat.stop,.hd-ag-head .subs-stat.stop{background:var(--red-bg);color:var(--red-ink);}
|
|
1319
|
+
.hd-ag-row .st{margin-left:auto;font-family:'JetBrains Mono',monospace;font-size:10px;font-weight:500;padding:2px 8px;border-radius:6px;white-space:nowrap;}
|
|
1320
|
+
.hd-ag-row .st.done{background:var(--green-bg);color:var(--green-ink);}
|
|
1321
|
+
.hd-ag-row .st.run{background:var(--blue-bg);color:var(--blue-ink);}
|
|
1322
|
+
.hd-ag-row .st.stop{background:var(--red-bg);color:var(--red-ink);}
|
|
1186
1323
|
|
|
1187
1324
|
/* Skill / MCP pills — main-agent group header + per sub-agent row. Flex-wrap so
|
|
1188
1325
|
pills reflow onto multiple lines as the window shrinks (cf. .agent-chips, .fan). */
|
|
1189
1326
|
.subs-skills{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;}
|
|
1190
|
-
.subs-
|
|
1191
|
-
|
|
1327
|
+
/* The BASE .subs-skills rule above is unscoped and reaches the Agents tab on its
|
|
1328
|
+
own; this FULL-ROW rule is not, and buildHdAgents emits skillPillsHtml into
|
|
1329
|
+
BOTH the group head and every row. Without the extension the pills stay inline
|
|
1330
|
+
— and in the head they land to the right of `.hd-ag-meta{margin-left:auto}`,
|
|
1331
|
+
jammed against the card edge. */
|
|
1332
|
+
.hd-ag-head .subs-skills,.rd-ag-head .subs-skills,.hd-ag-row .subs-skills{flex:0 0 100%;margin-top:6px;} /* own full row, aligned under the name cell */
|
|
1192
1333
|
.skill-pill{font-size:10.5px;font-weight:700;letter-spacing:.01em;padding:2px 9px;border-radius:999px;white-space:nowrap;}
|
|
1193
1334
|
.skill-pill.is-skill{background:var(--blue-bg);color:var(--blue-ink);}
|
|
1194
1335
|
.skill-pill.is-mcp{background:var(--green-bg);color:var(--green-ink);box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--green-ink) 18%, transparent);}
|
|
@@ -1204,7 +1345,7 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
1204
1345
|
/* Sub-agent type pill — the raw Task/Agent subagent_type, inline next to the row
|
|
1205
1346
|
name (cf. skill pills). Uses the shared violet token (defined :root, l.24) so it
|
|
1206
1347
|
reads as agent metadata, distinct from the skill (blue) / MCP (green) pills. */
|
|
1207
|
-
.
|
|
1348
|
+
.rd-ag-name .agent-type-pill,.hd-ag-row .agent-type-pill{font-size:10.5px;font-weight:700;letter-spacing:.01em;padding:2px 9px;border-radius:999px;white-space:nowrap;background:var(--violet-bg);color:var(--violet-ink);}
|
|
1208
1349
|
/* graphify-use count badge (amber) — how many times an agent / sub-agent invoked the
|
|
1209
1350
|
graphify CLI. Rendered INLINE: in the phase/node header next to the status, and on a
|
|
1210
1351
|
sub-agent row right after the violet type pill. inline-block + parent flex `gap` size
|
|
@@ -1295,7 +1436,6 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
1295
1436
|
.wf-filter{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px;}
|
|
1296
1437
|
|
|
1297
1438
|
/* Run Results view (Layer 1 mechanical + Layer 2 overview) */
|
|
1298
|
-
.results-section{margin-top:14px;}
|
|
1299
1439
|
.results-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;}
|
|
1300
1440
|
.results-chip{font-size:12px;background:var(--chip-bg,#f1f1f4);border:1px solid var(--line);border-radius:999px;padding:2px 10px;}
|
|
1301
1441
|
.results-clean{color:var(--green-ink,#1a7f37);font-size:13px;padding:6px 0;}
|
|
@@ -1495,7 +1635,9 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
1495
1635
|
.cost-banner .cb-text{color:var(--ink-2);}
|
|
1496
1636
|
.cost-banner .cb-text .mono{font-family:var(--mono);font-weight:600;color:var(--ink);}
|
|
1497
1637
|
.cost-banner .cb-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:10px;}
|
|
1498
|
-
.hist-
|
|
1638
|
+
/* No margin-left: that only made sense when the note trailed .hist-total inline.
|
|
1639
|
+
In the v2 card it is a direct child of .h-meta on its own line. */
|
|
1640
|
+
.hist-pausenote{font-size:11.5px;font-weight:600;color:var(--amber-ink);}
|
|
1499
1641
|
.hist-pausenote.total{color:var(--red-ink);}
|
|
1500
1642
|
|
|
1501
1643
|
@media (max-width:1080px){
|
|
@@ -1555,3 +1697,832 @@ fieldset.source legend{font-weight:600;font-size:13px;padding:0 6px;color:var(--
|
|
|
1555
1697
|
.mvx-env-row .select{flex:0 0 auto;}
|
|
1556
1698
|
.mvx-warn{color:var(--red,#c0392b);}
|
|
1557
1699
|
.pl-baseurl{word-break:break-all;}
|
|
1700
|
+
|
|
1701
|
+
/* ---------- History two-screen shell ---------- */
|
|
1702
|
+
.view[data-view="history"]{flex:1 1 auto;min-height:0;padding:0;position:relative;}
|
|
1703
|
+
.hist-shell{position:relative;height:100%;overflow:hidden;}
|
|
1704
|
+
/* NO top padding on the scroller itself — sticky pills must pin flush to the
|
|
1705
|
+
scrollport top (see the comments at the .main and .hist-filter rules). */
|
|
1706
|
+
.hist-screen{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;padding:0 32px 40px;
|
|
1707
|
+
transition:transform .46s cubic-bezier(.65,.02,.28,1);}
|
|
1708
|
+
.hist-screen-list .topbar{padding-top:26px;}
|
|
1709
|
+
.hist-screen-list{transform:translateX(0);}
|
|
1710
|
+
.hist-screen-detail{transform:translateX(100%);padding:0;background:var(--bg);}
|
|
1711
|
+
.hist-shell.detail-open .hist-screen-list{transform:translateX(-100%);}
|
|
1712
|
+
.hist-shell.detail-open .hist-screen-detail{transform:translateX(0);}
|
|
1713
|
+
.hist-shell.no-anim .hist-screen{transition:none;}
|
|
1714
|
+
|
|
1715
|
+
/* style.css has NO base .mono rule (only ancestor-scoped ones), so class="mono"
|
|
1716
|
+
alone renders in Poppins. Scope a base rule to the new subtrees only — a
|
|
1717
|
+
global one would touch every other view. */
|
|
1718
|
+
.hd .mono,.hist-card .mono,#shipit-modal .mono{font-family:var(--mono);}
|
|
1719
|
+
|
|
1720
|
+
/* Card, not a full-bleed band: same border/radius/shadow language as `.card`, and
|
|
1721
|
+
its own 20px/32px margin box supplies the inset the screen itself cannot —
|
|
1722
|
+
`.hist-screen-detail` keeps `padding:0` so the sticky `.hd-tabs` can still pin
|
|
1723
|
+
flush to the scrollport top. Inner padding drops 32 -> 24 so the title lands a
|
|
1724
|
+
card-like distance from the border instead of 56px from the viewport edge. */
|
|
1725
|
+
.hd-header{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);
|
|
1726
|
+
box-shadow:var(--shadow);margin:20px 32px 0;padding:20px 24px 18px;}
|
|
1727
|
+
.hd-row1{display:flex;align-items:center;gap:14px;}
|
|
1728
|
+
.hd-title{margin:0;min-width:0;flex:1;font:700 22px/1.25 var(--sans);letter-spacing:-.02em;
|
|
1729
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
1730
|
+
.hd-body{padding:0 32px 40px;}
|
|
1731
|
+
.hd-graph{margin-top:18px;}
|
|
1732
|
+
/* History detail only: a run-graph node is a link into the Logs tab's `source`
|
|
1733
|
+
filter (wireHdGraphLogLinks). `.linked` is added only when the run HAS a Logs
|
|
1734
|
+
tab, so an inert graph never shows a pointer, and the Done bookend carries no
|
|
1735
|
+
data-log-source so it stays unstyled. The live Running card renders the same
|
|
1736
|
+
markup and is deliberately untouched by this rule. Specificity (0,4,0) beats
|
|
1737
|
+
`.run-flow .node{cursor:default}` (1114) regardless of source order — that
|
|
1738
|
+
base rule is pinned by test/ui-run-flow-css.test.mjs:55 and must not move. The
|
|
1739
|
+
ring is the stylesheet's standard focus treatment (1940-1952) rather than the
|
|
1740
|
+
node's own --c accent: --c is a pastel set inline by runNode (860) and would
|
|
1741
|
+
sit near 2:1 against the graph's #FBFBF9 field. */
|
|
1742
|
+
.hd-graph.linked .run-node[data-log-source]{cursor:pointer;}
|
|
1743
|
+
.hd-graph.linked .run-node[data-log-source]:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
1744
|
+
.hd-error{margin-top:24px;color:var(--red-ink);font-size:12.5px;}
|
|
1745
|
+
.hd-error[hidden]{display:none;}
|
|
1746
|
+
.hist-sic{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;
|
|
1747
|
+
border-radius:50%;flex:0 0 auto;}
|
|
1748
|
+
.hist-sic .sic[hidden]{display:none;}
|
|
1749
|
+
.hist-sic.st-done{background:var(--green-bg);color:var(--green-ink);}
|
|
1750
|
+
.hist-sic.st-stopped,.hist-sic.st-error{background:var(--red-bg);color:var(--red-ink);}
|
|
1751
|
+
.hist-sic.st-paused{background:var(--amber-bg);color:var(--amber-ink);}
|
|
1752
|
+
|
|
1753
|
+
/* ---------- History detail: meta line, branch row, actions, banners ---------- */
|
|
1754
|
+
/* .diff-add/.diff-del exist ONLY as `.hist-diff .diff-add|.diff-del` (837-838).
|
|
1755
|
+
The detail meta uses those classes OUTSIDE that scope, so promote the colors to
|
|
1756
|
+
bare rules (same values); Task 11 folds the now-redundant scoped pair away. */
|
|
1757
|
+
.diff-add{color:var(--green-ink);}
|
|
1758
|
+
.diff-del{color:var(--red-ink);}
|
|
1759
|
+
|
|
1760
|
+
/* Row 2 = status pip + meta line. The 12px top gap moved here from `.hd-meta`
|
|
1761
|
+
IN PLACE: leaving it on the child would stack under this row's own margin and
|
|
1762
|
+
double the space under the title. */
|
|
1763
|
+
.hd-row2{display:flex;align-items:center;gap:10px;margin-top:12px;}
|
|
1764
|
+
/* Meta line is now a flex CHILD, so it takes the row's leftover width (min-width:0
|
|
1765
|
+
lets it wrap instead of pushing the pip off-row). */
|
|
1766
|
+
.hd-meta{display:flex;align-items:center;flex-wrap:wrap;gap:8px;min-width:0;flex:1;
|
|
1767
|
+
font:400 12.5px var(--mono);color:var(--ink-3);}
|
|
1768
|
+
/* 30px is the row-1 size; on a 12.5px meta line the pip shrinks to match the text. */
|
|
1769
|
+
.hd-row2 .hd-sic{width:24px;height:24px;}
|
|
1770
|
+
.hd-meta .strong{font-weight:700;color:var(--ink);} /* no global .strong rule exists */
|
|
1771
|
+
.hd-diffcounts{display:inline-flex;align-items:center;gap:6px;}
|
|
1772
|
+
.hd-dot{font-weight:700;color:var(--ink);}
|
|
1773
|
+
.hd-status-word{font:600 12.5px var(--sans);}
|
|
1774
|
+
/* shared with the Task-11 list card's .hist-status-word (same st-* families) */
|
|
1775
|
+
.hd-status-word.st-done,.hist-status-word.st-done{color:var(--green-ink);}
|
|
1776
|
+
.hd-status-word.st-stopped,.hd-status-word.st-error,
|
|
1777
|
+
.hist-status-word.st-stopped,.hist-status-word.st-error{color:var(--red-ink);}
|
|
1778
|
+
.hd-status-word.st-paused,.hist-status-word.st-paused{color:var(--amber-ink);}
|
|
1779
|
+
/* 14px -> 6px: the branch chip and the Resume/Archive buttons carry ~8px of their
|
|
1780
|
+
own vertical padding, so the row reads far further from the meta line than the
|
|
1781
|
+
number says. 6px + that padding lands on the same optical gap as row1->row2. */
|
|
1782
|
+
.hd-row3{display:flex;align-items:center;gap:8px;margin-top:6px;min-width:0;}
|
|
1783
|
+
.hd-base{color:var(--ink-3);font-size:12px;white-space:nowrap;}
|
|
1784
|
+
.hd-base[hidden]{display:none;}
|
|
1785
|
+
.hd-branch-copy{display:flex;align-items:center;gap:9px;min-width:0;padding:8px 12px;
|
|
1786
|
+
border:1px solid var(--line);border-radius:9px;background:var(--field);
|
|
1787
|
+
font:700 12px var(--mono);color:var(--ink);cursor:pointer;}
|
|
1788
|
+
.hd-branch-copy[hidden]{display:none;}
|
|
1789
|
+
.hd-branch-copy:hover{border-color:var(--ink-3);background:var(--panel);}
|
|
1790
|
+
.hd-branch-name{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
1791
|
+
.hd-branch-copy .ico-check{display:none;}
|
|
1792
|
+
.hd-branch-copy.copied .ico-copy{display:none;}
|
|
1793
|
+
.hd-branch-copy.copied .ico-check{display:inline;color:var(--green-ink);}
|
|
1794
|
+
/* the design's green "Copied" caption, driven off copyBranchToClipboard's own
|
|
1795
|
+
1200ms .copied window — no extra JS */
|
|
1796
|
+
.hd-copied{display:none;font:500 11.5px var(--sans);color:var(--green-ink);}
|
|
1797
|
+
.hd-branch-copy.copied + .hd-copied{display:inline;}
|
|
1798
|
+
.hd-spacer{flex:1 1 24px;}
|
|
1799
|
+
/* .btn-ghost (388-389) sets no `display` and already gives border-radius:999px —
|
|
1800
|
+
these two icon+label buttons need the flex row themselves or their SVG lands on
|
|
1801
|
+
the text baseline with no gap (unlike .hd-archive below, which ships its own).
|
|
1802
|
+
They also need .btn-ghost's `padding:13px 20px` cut to the compact scale, or the
|
|
1803
|
+
row mixes heights. Every other place this file pairs .btn-ghost with compact
|
|
1804
|
+
controls does the same override (.hist-pr, .ws-actions, .pl-actions,
|
|
1805
|
+
.grv-actions, .mv-card). */
|
|
1806
|
+
.hd-back,.hd-resume{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;}
|
|
1807
|
+
.hd-resume[hidden]{display:none;}
|
|
1808
|
+
/* 9px, not the 8px its siblings use: this one is 12.5px type against .hd-back's
|
|
1809
|
+
13.5px, so equal padding renders it 36px tall in a row of 38px buttons
|
|
1810
|
+
(measured in headless Chrome). The extra pixel per side matches .hd-pr, which
|
|
1811
|
+
is the same type size and already pays it. */
|
|
1812
|
+
.hd-archive{display:flex;align-items:center;gap:8px;padding:9px 15px;border:1.5px solid var(--red-bg);
|
|
1813
|
+
border-radius:999px;background:var(--panel);font:600 12.5px var(--sans);color:var(--red-ink);cursor:pointer;}
|
|
1814
|
+
.hd-archive[hidden]{display:none;}
|
|
1815
|
+
.hd-archive:hover:not([disabled]){background:var(--red-bg);border-color:var(--red);}
|
|
1816
|
+
.hd-archive[disabled]{opacity:.55;cursor:not-allowed;}
|
|
1817
|
+
/* align-items:flex-start, NOT the default stretch: `.badge.hist-retained-badge`
|
|
1818
|
+
(696) and `.hist-discard` (856) are inline-flex with no width, so a stretching
|
|
1819
|
+
column blows both up to the full body width. Only the two BANNERS want the full
|
|
1820
|
+
row — an unstretched `.cost-banner` renders ~738px inside a 1068px column and
|
|
1821
|
+
its own `.cb-actions{justify-content:flex-end}` then right-aligns short of the
|
|
1822
|
+
edge. */
|
|
1823
|
+
.hd-banners{display:flex;flex-direction:column;align-items:flex-start;gap:12px;}
|
|
1824
|
+
/* Both reused banners carry legacy margins from their old hosts —
|
|
1825
|
+
`.retained-banner{margin:0 0 18px}` (714) and `.cost-banner{margin-top:12px}`
|
|
1826
|
+
(1505) — which double up with this column's own `gap:12px`. Zero them here
|
|
1827
|
+
rather than editing the shared rules. */
|
|
1828
|
+
.hd-banners .retained-banner,.hd-banners .cost-banner{align-self:stretch;margin:0;}
|
|
1829
|
+
/* NOT `.hd-banners:empty` — the container always holds three template children
|
|
1830
|
+
(badge, banner, discard button), just hidden, so :empty never matches and the
|
|
1831
|
+
top margin would always apply. Key the margin off "has a visible child". */
|
|
1832
|
+
.hd-banners:has(> :not([hidden])){margin-top:18px;}
|
|
1833
|
+
/* .hist-discard's existing rules (856-860) are card-scoped only by position; keep
|
|
1834
|
+
them and let the detail banner button ride them unchanged. */
|
|
1835
|
+
|
|
1836
|
+
/* Destructive confirm (spec §5.2). The id keeps it out of .btn-primary's way with
|
|
1837
|
+
no !important. confirmModal removes the class on close, so it never leaks. */
|
|
1838
|
+
#confirm-ok.danger{background:var(--red-ink);border-color:var(--red-ink);color:#fff;}
|
|
1839
|
+
|
|
1840
|
+
/* ---------- History detail: section tabs ---------- */
|
|
1841
|
+
.hd-tabs{position:sticky;top:0;z-index:5;display:flex;align-items:center;flex-wrap:wrap;gap:8px;
|
|
1842
|
+
padding:18px 0 14px;background:var(--bg);}
|
|
1843
|
+
.hd-tab{display:flex;align-items:center;gap:9px;padding:10px 17px;border:1.5px solid var(--line);
|
|
1844
|
+
border-radius:999px;background:var(--panel);font:600 13.5px var(--sans);color:var(--ink-2);cursor:pointer;}
|
|
1845
|
+
.hd-tab:hover{border-color:var(--ink-3);color:var(--ink);}
|
|
1846
|
+
.hd-tab.active{background:var(--ink);color:#fff;border-color:var(--ink);}
|
|
1847
|
+
.hd-tab-badge{padding:2px 8px;border-radius:999px;background:var(--field);color:var(--ink-3);
|
|
1848
|
+
font:600 10.5px var(--mono);}
|
|
1849
|
+
.hd-tab.active .hd-tab-badge{background:var(--blue-bg);color:var(--blue-ink);}
|
|
1850
|
+
.hd-sec{margin-top:4px;}
|
|
1851
|
+
/* Explicit twin, not redundancy insurance: the UA [hidden] rule is (0,0,0) and
|
|
1852
|
+
loses to any author `display`, so the moment a later task gives .hd-sec (or a
|
|
1853
|
+
.hd-sec-* body) a display value, the inactive panels would all render at once. */
|
|
1854
|
+
.hd-sec[hidden]{display:none;}
|
|
1855
|
+
|
|
1856
|
+
/* ---------- History detail: Diff tab ---------- */
|
|
1857
|
+
.hd-diff{display:grid;grid-template-columns:minmax(280px,340px) 1fr;gap:18px;align-items:start;}
|
|
1858
|
+
@media (max-width:900px){.hd-diff{grid-template-columns:1fr;}}
|
|
1859
|
+
.hd-diff-list,.hd-diff-pane{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;}
|
|
1860
|
+
.hd-diff-list-head,.hd-diff-pane-head{display:flex;align-items:center;justify-content:space-between;gap:10px;
|
|
1861
|
+
padding:15px 18px;border-bottom:1px solid var(--line);font-size:12.5px;}
|
|
1862
|
+
.hd-diff-rows{padding:6px;max-height:520px;overflow-y:auto;}
|
|
1863
|
+
.hd-diff-proj{padding:8px 12px 2px;color:var(--ink-3);font-size:11px;}
|
|
1864
|
+
.hd-diff-file{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:9px;cursor:pointer;}
|
|
1865
|
+
.hd-diff-file:hover,.hd-diff-file.active{background:var(--field);}
|
|
1866
|
+
.hd-diff-file:focus-visible{outline:2px solid var(--ink);outline-offset:-2px;}
|
|
1867
|
+
.hd-diff-file.deleted .hd-diff-path{opacity:.55;text-decoration:line-through;}
|
|
1868
|
+
.hd-diff-file.new .hd-diff-path{color:var(--green-ink);}
|
|
1869
|
+
/* direction:rtl ellipsizes at the START (the file name matters more than the
|
|
1870
|
+
directory). It also reorders a LEADING NEUTRAL character to the end, so
|
|
1871
|
+
`.github/workflows/ci.yml` would render as `github/workflows/ci.yml.` — the
|
|
1872
|
+
::before LRM (U+200E) is a strong LTR anchor that pins the dot in place while
|
|
1873
|
+
keeping the start-ellipsis. It lives in CSS, not in textContent, so the
|
|
1874
|
+
`/src\/a\.js/` assertions stay clean. */
|
|
1875
|
+
.hd-diff-file .hd-diff-path{flex:1;min-width:0;font-size:12px;color:var(--ink-2);
|
|
1876
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;direction:rtl;text-align:left;}
|
|
1877
|
+
.hd-diff-file .hd-diff-path::before{content:"\200E";}
|
|
1878
|
+
.hd-diff-counts{font-size:11.5px;white-space:nowrap;}
|
|
1879
|
+
/* hdFileCountsHtml's binary chip is a `.hint`, and `.hint` (style.css:283) is
|
|
1880
|
+
`display:block;margin-top:7px` — inside these flex rows it would sit visibly
|
|
1881
|
+
low. Same reset for the pane head. */
|
|
1882
|
+
.hd-diff-counts .hint,.hd-diff-pane-head .hint{display:inline;margin-top:0;}
|
|
1883
|
+
/* The `.hd-diff-path` ellipsis rule is scoped to `.hd-diff-file`, so the SAME class
|
|
1884
|
+
in the pane head is unstyled and WRAPS: measured 49.8px -> 69px on a 78-char
|
|
1885
|
+
path, while the identical path ellipsizes one column to the left. */
|
|
1886
|
+
.hd-diff-pane-head .hd-diff-path{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
1887
|
+
/* The patch is the tall thing on this screen, so it scrolls INSIDE its pane
|
|
1888
|
+
rather than pushing the whole detail screen down — same cap and mechanism as
|
|
1889
|
+
`.hd-diff-rows` opposite it, which keeps the two panes the same height.
|
|
1890
|
+
Uncapped, a real patch measured 7479px and owned the screen's whole scroll.
|
|
1891
|
+
|
|
1892
|
+
The grid is what makes the row TINT correct. `.hd-dl` used to size itself with
|
|
1893
|
+
`width:max-content;min-width:100%`, but max-content is EACH ROW'S OWN content:
|
|
1894
|
+
in a 336-row patch that produced 11 different row widths (708…1015px), so every
|
|
1895
|
+
line shorter than the longest had its --green-bg/--red-bg band stop mid-pane
|
|
1896
|
+
and the padding land against the text instead of the edge. A single column of
|
|
1897
|
+
`minmax(max-content,1fr)` is sized by the WIDEST row (1fr keeps it filling the
|
|
1898
|
+
pane when the patch is narrow) and stretch makes every row match it — measured
|
|
1899
|
+
uniform at 1015px with 0 of 217 tinted rows stopping short. D4 forbids syntax
|
|
1900
|
+
highlighting, so this tint is the pane's only visual signal — it has to hold. */
|
|
1901
|
+
.hd-diff-body{padding:12px 0;font:400 12px/1.85 var(--mono);color:var(--ink-2);
|
|
1902
|
+
display:grid;grid-template-columns:minmax(max-content,1fr);
|
|
1903
|
+
max-height:520px;overflow-x:auto;overflow-y:auto;}
|
|
1904
|
+
.hd-diff-body.hint,.hd-diff-none{padding:18px;}
|
|
1905
|
+
.hd-dl{padding:0 18px;white-space:pre;}
|
|
1906
|
+
.hd-dl-hunk{color:var(--ink-3);background:var(--field);}
|
|
1907
|
+
.hd-dl-add{background:var(--green-bg);}
|
|
1908
|
+
.hd-dl-del{background:var(--red-bg);}
|
|
1909
|
+
.hd-diff-trunc{padding:10px 18px 0;}
|
|
1910
|
+
.hd-diff-empty{margin-top:24px;padding:40px;text-align:center;color:var(--ink-2);
|
|
1911
|
+
background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);}
|
|
1912
|
+
|
|
1913
|
+
/* ---------- History detail: Overview tab ---------- */
|
|
1914
|
+
.hd-ov{display:flex;flex-direction:column;gap:18px;}
|
|
1915
|
+
.hd-ov-verdict{display:flex;align-items:center;gap:12px;padding:16px 20px;background:var(--panel);
|
|
1916
|
+
border:1px solid var(--line);border-radius:var(--r-card);font:500 13.5px var(--sans);}
|
|
1917
|
+
.hd-ov-verdict.clean{color:var(--green-ink);}
|
|
1918
|
+
.hd-ov-verdict.warn{color:var(--amber-ink);}
|
|
1919
|
+
.hd-ov-verdict.none{color:var(--ink-2);} /* the class the results-less arm emits */
|
|
1920
|
+
.hd-ov-chip{padding:5px 12px;border-radius:999px;font:600 11.5px var(--sans);}
|
|
1921
|
+
.hd-ov-chip.clean,.hd-ov-chip.st-done{background:var(--green-bg);color:var(--green-ink);}
|
|
1922
|
+
.hd-ov-chip.warn,.hd-ov-chip.st-paused{background:var(--amber-bg);color:var(--amber-ink);}
|
|
1923
|
+
.hd-ov-chip.st-stopped,.hd-ov-chip.st-error{background:var(--red-bg);color:var(--red-ink);}
|
|
1924
|
+
.hd-ov-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px;}
|
|
1925
|
+
.hd-ov-card{padding:20px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);}
|
|
1926
|
+
.hd-ov-label{font:600 10.5px var(--sans);letter-spacing:.14em;color:var(--ink-3);}
|
|
1927
|
+
.hd-ov-value{margin-top:10px;font-size:22px;color:var(--ink);}
|
|
1928
|
+
.hd-ov-sub{margin-top:6px;font-size:11.5px;color:var(--ink-3);overflow-wrap:anywhere;}
|
|
1929
|
+
.hd-ov-task{padding:22px 24px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);}
|
|
1930
|
+
.hd-ov-task-h{font:600 13px var(--sans);}
|
|
1931
|
+
/* overflow-wrap:anywhere like its sibling .hd-ov-sub — prompts routinely carry
|
|
1932
|
+
absolute paths and URLs, and `.hist-screen{overflow-x:hidden}` would silently
|
|
1933
|
+
CLIP an unbroken token rather than let it scroll. */
|
|
1934
|
+
.hd-ov-task p{margin:10px 0 0;max-width:74ch;font:400 13.5px/1.75 var(--sans);color:var(--ink-2);
|
|
1935
|
+
white-space:pre-wrap;overflow-wrap:anywhere;}
|
|
1936
|
+
.hd-ov-more{margin-top:8px;border:none;background:none;color:var(--blue-ink);font:500 12.5px var(--sans);cursor:pointer;padding:0;}
|
|
1937
|
+
.hd-ov-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px;}
|
|
1938
|
+
.hd-ov-tag{padding:6px 12px;border:1px solid var(--line);border-radius:999px;font-size:11.5px;color:var(--ink-2);}
|
|
1939
|
+
|
|
1940
|
+
/* ---------- History detail: Agents tab ---------- */
|
|
1941
|
+
.hd-ag-group{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);
|
|
1942
|
+
overflow:hidden;margin-bottom:18px;}
|
|
1943
|
+
.hd-ag-head{display:flex;align-items:center;flex-wrap:wrap;gap:12px;padding:15px 20px;
|
|
1944
|
+
border-bottom:1px solid var(--line);font-size:13px;}
|
|
1945
|
+
.hd-ag-meta{color:var(--ink-3);font-size:11.5px;margin-left:auto;}
|
|
1946
|
+
.hd-ag-none{padding:12px 20px;}
|
|
1947
|
+
.hd-ag-row{display:flex;align-items:center;flex-wrap:wrap;gap:10px;padding:12px 20px;border-top:1px solid var(--line);}
|
|
1948
|
+
/* NOT `.hd-ag-row:first-of-type` — `:first-of-type` is per ELEMENT TYPE, and
|
|
1949
|
+
`.hd-ag-head` is the first `div` in the card, so no row would ever match it and
|
|
1950
|
+
the first row's border would double up with the head's `border-bottom`. */
|
|
1951
|
+
.hd-ag-head + .hd-ag-row{border-top:none;}
|
|
1952
|
+
.hd-ag-name{min-width:0;flex:1 1 200px;font:500 13px var(--sans);color:var(--ink);
|
|
1953
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
1954
|
+
/* NO `.hd-ag-row .st{margin-left:auto}` here — the in-place extension of
|
|
1955
|
+
`.hd-ag-row .st` already carries `margin-left:auto` along with the font;
|
|
1956
|
+
a second bare rule is pure duplication. */
|
|
1957
|
+
.hd-ag-dur{width:90px;text-align:right;font-size:11.5px;color:var(--ink-2);}
|
|
1958
|
+
.hd-ag-cost{width:80px;text-align:right;font-size:11.5px;color:var(--ink-2);}
|
|
1959
|
+
|
|
1960
|
+
/* ---------- History detail: Clarify tab ---------- */
|
|
1961
|
+
.hd-cl{display:flex;flex-direction:column;gap:14px;}
|
|
1962
|
+
.hd-cl-card{padding:20px 24px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);}
|
|
1963
|
+
.hd-cl-q,.hd-cl-a{display:flex;gap:12px;align-items:flex-start;}
|
|
1964
|
+
.hd-cl-a{margin-top:12px;color:var(--ink-2);}
|
|
1965
|
+
.hd-cl-q > span:last-child{font:600 13.5px/1.6 var(--sans);}
|
|
1966
|
+
.hd-cl-a > span:last-child{font:400 13.5px/1.7 var(--sans);}
|
|
1967
|
+
.hd-cl-chip{flex:0 0 auto;padding:3px 9px;border-radius:7px;font-size:10.5px;font-weight:600;}
|
|
1968
|
+
.hd-cl-chip.ask{background:var(--field);color:var(--ink-2);}
|
|
1969
|
+
.hd-cl-chip.ans{background:var(--green-bg);color:var(--green-ink);}
|
|
1970
|
+
/* `.hint` (:283) ships `margin-top:7px`; the shorthand replaces it outright so the
|
|
1971
|
+
caption hugs the block it introduces instead of floating mid-gap. */
|
|
1972
|
+
.hd-cl-caption{margin:4px 0 -6px;}
|
|
1973
|
+
|
|
1974
|
+
/* ---------- History detail: Logs tab ---------- */
|
|
1975
|
+
/* History-scoped ONLY: the shared `.log` / `.log-filters` markup is the Running
|
|
1976
|
+
view's, and `.run-log .log` keeps its own sizes there (D7 — the Running view is
|
|
1977
|
+
untouched). Neither rule sets `display`, so `.hd-sec[hidden]` (:1703) still hides
|
|
1978
|
+
the whole panel and no `[hidden]` twin is needed. */
|
|
1979
|
+
.hd-sec-logs .log{background:var(--panel);border:1px solid var(--line);border-radius:16px;
|
|
1980
|
+
min-height:260px;max-height:520px;overflow-y:auto;padding:18px 20px;}
|
|
1981
|
+
.hd-sec-logs .log-filters{margin-bottom:10px;}
|
|
1982
|
+
|
|
1983
|
+
/* ---------- History detail: PR controls + the "Ship it?" modal ---------- */
|
|
1984
|
+
/* Detail-header PR controls (spec §5.2: black pill). `.hd-pr-link` carries no rule
|
|
1985
|
+
of its own — its colour, its removed underline and the MERGED grey all come from
|
|
1986
|
+
the `.hist-pr-link` selector lists at :848-:850, extended in place. */
|
|
1987
|
+
.hd-pr{padding:9px 18px;border:1.5px solid var(--ink);border-radius:999px;background:var(--ink);
|
|
1988
|
+
font:600 12.5px var(--sans);color:#fff;cursor:pointer;flex:0 0 auto;}
|
|
1989
|
+
.hd-pr[hidden]{display:none;}
|
|
1990
|
+
.hd-pr:hover{opacity:.88;}
|
|
1991
|
+
.hd-pr-link{flex:0 0 auto;font:600 12.5px var(--sans);}
|
|
1992
|
+
.hd-pr-link[hidden]{display:none;}
|
|
1993
|
+
|
|
1994
|
+
/* WIDTH GOES ON `#shipit-modal .card`, NOT `.shipit-card`. The markup is
|
|
1995
|
+
`<div class="card shipit-card">` inside `.viewer-modal`, and
|
|
1996
|
+
`.viewer-modal .card{width:min(860px,100%);…}` (:782) is (0,2,0): a bare
|
|
1997
|
+
`.shipit-card{width:…}` (0,1,0) loses no matter where it is appended, and the
|
|
1998
|
+
dialog would ship ~1.5x the design width. Precedents: `.folder-modal .card`
|
|
1999
|
+
(:786) and `.confirm-modal .card` (:1306). Everything else below only ties with
|
|
2000
|
+
`.card` (:263) and wins on source order, so it stays bare. */
|
|
2001
|
+
#shipit-modal .card{width:min(560px,100%);}
|
|
2002
|
+
.shipit-card{padding:32px 28px 24px;text-align:center;
|
|
2003
|
+
animation:shipit-rise .34s cubic-bezier(.2,.7,.3,1) both;}
|
|
2004
|
+
@keyframes shipit-rise{0%{transform:translateY(10px);opacity:0}100%{transform:translateY(0);opacity:1}}
|
|
2005
|
+
.shipit-ico-wrap{position:relative;display:grid;place-items:center;width:74px;height:74px;margin:0 auto;}
|
|
2006
|
+
.shipit-spark{position:absolute;inset:0;border-radius:50%;background:var(--green-bg);
|
|
2007
|
+
animation:shipit-spark .9s ease-out .12s both;}
|
|
2008
|
+
.shipit-ico{position:relative;display:grid;place-items:center;width:60px;height:60px;border-radius:50%;
|
|
2009
|
+
background:var(--green-bg);color:var(--green-ink);animation:shipit-pop .42s cubic-bezier(.2,.8,.25,1) both;}
|
|
2010
|
+
@keyframes shipit-pop{0%{transform:scale(.72);opacity:0}60%{transform:scale(1.06)}100%{transform:scale(1);opacity:1}}
|
|
2011
|
+
@keyframes shipit-spark{0%{transform:scale(.4);opacity:0}45%{opacity:1}100%{transform:scale(1.9);opacity:0}}
|
|
2012
|
+
.shipit-card h2{margin:18px 0 0;font:700 20px/1.25 var(--sans);letter-spacing:-.02em;}
|
|
2013
|
+
.shipit-sub{margin:8px 0 0;font:400 13.5px/1.6 var(--sans);color:var(--ink-2);}
|
|
2014
|
+
.shipit-summary{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:8px;
|
|
2015
|
+
margin-top:18px;padding:14px;background:var(--field);border-radius:14px;font-size:12px;color:var(--ink-2);}
|
|
2016
|
+
.shipit-summary[hidden]{display:none;}
|
|
2017
|
+
/* An empty flex child still eats a `gap`, so a results-less run ("+12 −3", no file
|
|
2018
|
+
count) would render a stray 8px hole. Hide the value spans by NAME — a blanket
|
|
2019
|
+
`> span:empty` would also hide `.shipit-break`, whose whole job is to be an empty
|
|
2020
|
+
full-width line break. Precedent: `.h-meta .hist-total:empty` (:807). */
|
|
2021
|
+
.shipit-files:empty,.shipit-add:empty,.shipit-del:empty,.shipit-base:empty{display:none;}
|
|
2022
|
+
.shipit-files:empty + .shipit-dot{display:none;}
|
|
2023
|
+
.shipit-break{flex-basis:100%;height:0;}
|
|
2024
|
+
.shipit-branch{color:var(--ink);word-break:break-all;}
|
|
2025
|
+
.shipit-actions{display:flex;align-items:center;justify-content:center;gap:10px;margin-top:22px;}
|
|
2026
|
+
.shipit-ok{padding:11px 22px;border:1.5px solid var(--ink);border-radius:999px;background:var(--ink);
|
|
2027
|
+
font:600 13.5px var(--sans);color:#fff;cursor:pointer;}
|
|
2028
|
+
.shipit-err{margin-top:12px;}
|
|
2029
|
+
/* MANDATORY twin: the node is `class="hint err" hidden`, and `.hint` (:283) sets
|
|
2030
|
+
display:block — an author rule always beats the UA `[hidden]{display:none}`.
|
|
2031
|
+
Without this the modal permanently carries an empty 12px-margin block (and a
|
|
2032
|
+
stray node in the a11y tree). */
|
|
2033
|
+
.shipit-err[hidden]{display:none;}
|
|
2034
|
+
|
|
2035
|
+
/* Reduced motion for the three ship-it animations. This block MUST sit AFTER the
|
|
2036
|
+
rules that declare them: `@media` contributes no specificity, so naming
|
|
2037
|
+
`.shipit-card` in the kill list at :763 would tie at (0,1,0) and LOSE on source
|
|
2038
|
+
order — the animation would still play. (The four names already at :763 work
|
|
2039
|
+
only because each is declared before it, and the run-graph block at :1246
|
|
2040
|
+
likewise follows its animations.) */
|
|
2041
|
+
@media (prefers-reduced-motion: reduce){
|
|
2042
|
+
.shipit-card,.shipit-ico{animation:none;}
|
|
2043
|
+
/* `.shipit-spark` needs its END STATE too, not just `animation:none`. Its
|
|
2044
|
+
keyframes are `both`-filled and finish at opacity:0; kill the animation alone
|
|
2045
|
+
and it computes `opacity:1; transform:none` — a permanent 74px --green-bg disc
|
|
2046
|
+
ringing the 60px icon. */
|
|
2047
|
+
.shipit-spark{animation:none;opacity:0;}
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
/* ---------- History list card v2 ---------- */
|
|
2051
|
+
/* Appended at EOF, after every surviving `.hist-*` rule — the History block is not
|
|
2052
|
+
contiguous (it also lives at ~796-862 and ~1516), so a mid-file append would lose
|
|
2053
|
+
the source-order tie against those. Where a redesigned element KEEPS an existing
|
|
2054
|
+
class name (.hist-total, .hist-time, .hist-pausenote, .h-meta b) the rule was
|
|
2055
|
+
edited in place instead; those are never restated here. */
|
|
2056
|
+
/* card icon is 36px; scoped so the detail header's 30px .hd-sic keeps its size */
|
|
2057
|
+
.hist-card .hist-sic{width:36px;height:36px;align-self:center;}
|
|
2058
|
+
.hist-meta-line{display:flex;align-items:center;flex-wrap:wrap;gap:7px;margin-top:5px;}
|
|
2059
|
+
.hist-meta-line .hm-seg{display:inline-flex;align-items:center;gap:7px;}
|
|
2060
|
+
.hist-meta-line .hm-seg[hidden]{display:none;} /* author display beats the UA [hidden] rule */
|
|
2061
|
+
.hm-dot{font:700 16px/1 var(--mono);color:var(--ink);}
|
|
2062
|
+
.hist-status-word{font:600 12px var(--sans);display:inline-flex;align-items:center;gap:7px;}
|
|
2063
|
+
/* the design's 7px status accent dot before the word; currentColor = family ink */
|
|
2064
|
+
.hist-meta-line .hist-status-word::before{content:'';width:7px;height:7px;border-radius:50%;
|
|
2065
|
+
background:currentColor;flex:0 0 auto;}
|
|
2066
|
+
.hist-day,.hist-clock{font:400 12.5px var(--mono);color:var(--ink-3);}
|
|
2067
|
+
.hist-diff-pill{display:inline-flex;align-items:center;gap:8px;padding:4px 11px;
|
|
2068
|
+
border:1px solid var(--line);border-radius:999px;background:var(--panel);font-size:12px;}
|
|
2069
|
+
.hist-diff-pill[hidden]{display:none;}
|
|
2070
|
+
.hist-diff-pill .hist-diff{display:inline-flex;gap:6px;font-weight:700;}
|
|
2071
|
+
.hist-diff-pill .hist-diff[hidden],.hist-nodiff[hidden]{display:none;}
|
|
2072
|
+
.hist-nodiff{color:var(--ink-3);}
|
|
2073
|
+
.hist-open{display:flex;align-items:center;justify-content:center;width:30px;height:30px;
|
|
2074
|
+
border:1px solid var(--line);border-radius:9px;background:var(--panel);color:var(--ink-2);cursor:pointer;}
|
|
2075
|
+
.hist-open:hover{background:var(--ink);color:#fff;border-color:var(--ink);}
|
|
2076
|
+
/* "Copied" caption on the card — same CSS-only mechanism as .hd-copied */
|
|
2077
|
+
.hist-copied{display:none;font:500 11px var(--sans);color:var(--green-ink);}
|
|
2078
|
+
.hist-branch-copy.copied + .hist-copied{display:inline;}
|
|
2079
|
+
|
|
2080
|
+
/* ---------- focus visibility (History redesign) ----------
|
|
2081
|
+
Every other interactive control in this stylesheet carries a ring (.btn,
|
|
2082
|
+
.btn-go, .btn-stop, .nav button, .hist-head, .seg button, .info-tip, .ws-head,
|
|
2083
|
+
.proj-del, .ch-hit); none of the new controls did. `.btn-ghost` declares no
|
|
2084
|
+
ring to inherit and carries no `btn` class, so `.hd-back`, `.hd-resume` and
|
|
2085
|
+
`.shipit-cancel` had nothing at all — which matters most for `.hd-back`, the
|
|
2086
|
+
node openHistDetail focuses programmatically, and for the `.hd-tab` tablist.
|
|
2087
|
+
`.hd-diff-file` already has its own (inset) ring and is not repeated here. */
|
|
2088
|
+
.hd-tab:focus-visible,.hd-back:focus-visible,.hd-resume:focus-visible,
|
|
2089
|
+
.hd-archive:focus-visible,.hd-pr:focus-visible,.hd-pr-link:focus-visible,
|
|
2090
|
+
.hd-branch-copy:focus-visible,.hd-sec:focus-visible,.hist-open:focus-visible,
|
|
2091
|
+
.hist-branch-copy:focus-visible,.shipit-ok:focus-visible,.shipit-cancel:focus-visible{
|
|
2092
|
+
outline:2px solid var(--ink);outline-offset:2px;}
|
|
2093
|
+
|
|
2094
|
+
/* ---------- Running list card v2 (.rc-*) ----------
|
|
2095
|
+
Appended at EOF, after every surviving `.run-*` / `.btn-*` rule — the Running
|
|
2096
|
+
block is not contiguous (it also lives at ~557-600 and ~1109) and .btn-pause /
|
|
2097
|
+
.btn-resume / .btn-stop have base rules at 237-254, so a mid-file append would
|
|
2098
|
+
lose the source-order tie. Same reasoning as the History list card v2 block. */
|
|
2099
|
+
/* margin-bottom replaces `.run-top`'s own 18px, which this task deletes:
|
|
2100
|
+
`.run-flow-wrap` (:1109) has only a BOTTOM margin, so without this the graph
|
|
2101
|
+
would sit flush against the header until Task 4 adds `.rc-detailed{margin-top:18px}`. */
|
|
2102
|
+
.rc-head{display:flex;align-items:flex-start;gap:13px;cursor:pointer;margin-bottom:18px;}
|
|
2103
|
+
.rc-head:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2104
|
+
.rc-sic{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;
|
|
2105
|
+
border-radius:50%;flex:0 0 auto;align-self:center;}
|
|
2106
|
+
.rc-sic .sic[hidden]{display:none;}
|
|
2107
|
+
.rc-sic.st-blue{background:var(--blue-bg);color:var(--blue-ink);}
|
|
2108
|
+
.rc-sic.st-amber{background:var(--amber-bg);color:var(--amber-ink);}
|
|
2109
|
+
.rc-sic.st-green{background:var(--green-bg);color:var(--green-ink);}
|
|
2110
|
+
.rc-sic.st-red{background:var(--red-bg);color:var(--red-ink);}
|
|
2111
|
+
.rc-sic .sic-spin{animation:wr-spin 1.15s linear infinite;transform-origin:50% 50%;}
|
|
2112
|
+
.rc-body{flex:1;min-width:0;}
|
|
2113
|
+
.rc-title{display:block;font-weight:600;font-size:14.5px;letter-spacing:-.01em;
|
|
2114
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
2115
|
+
.rc-meta{display:flex;align-items:center;flex-wrap:wrap;gap:7px;margin-top:5px;
|
|
2116
|
+
color:var(--ink-3);font-size:12.5px;}
|
|
2117
|
+
.rc-meta .rc-seg{display:inline-flex;align-items:center;gap:7px;}
|
|
2118
|
+
.rc-dot{font:700 16px/1 var(--mono);color:var(--ink);}
|
|
2119
|
+
.rc-status-word{font:600 12px var(--sans);display:inline-flex;align-items:center;gap:7px;}
|
|
2120
|
+
/* the 7px status accent dot before the word; currentColor = the family ink */
|
|
2121
|
+
.rc-meta .rc-status-word::before{content:'';width:7px;height:7px;border-radius:50%;
|
|
2122
|
+
background:currentColor;flex:0 0 auto;}
|
|
2123
|
+
.rc-status-word.st-peach{color:var(--peach-ink);}
|
|
2124
|
+
.rc-status-word.st-blue{color:var(--blue-ink);}
|
|
2125
|
+
.rc-status-word.st-violet{color:var(--violet-ink);}
|
|
2126
|
+
.rc-status-word.st-amber{color:var(--amber-ink);}
|
|
2127
|
+
.rc-status-word.st-green{color:var(--green-ink);}
|
|
2128
|
+
.rc-status-word.st-red{color:var(--red-ink);}
|
|
2129
|
+
.rc-meta .run-time,.rc-meta .run-cost{font-weight:700;color:var(--ink);}
|
|
2130
|
+
.rc-branch{display:flex;align-items:center;gap:6px;margin-top:6px;min-width:0;
|
|
2131
|
+
font-family:var(--mono);font-size:12px;font-weight:600;color:var(--ink-2);}
|
|
2132
|
+
.rc-branch[hidden]{display:none;} /* author display:flex beats the UA [hidden] rule */
|
|
2133
|
+
.rc-base{color:var(--ink-3);font-weight:500;white-space:nowrap;}
|
|
2134
|
+
.rc-base[hidden]{display:none;}
|
|
2135
|
+
.rc-branch-copy{display:inline-flex;align-items:center;gap:8px;min-width:12ch;
|
|
2136
|
+
padding:4px 10px;border:1px solid var(--line);border-radius:9px;background:var(--field);
|
|
2137
|
+
font:700 11.5px var(--mono);color:var(--ink);cursor:pointer;}
|
|
2138
|
+
.rc-branch-copy:hover{border-color:var(--ink-3);background:var(--panel);}
|
|
2139
|
+
.rc-branch-name{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
2140
|
+
.rc-branch-copy .ico-check{display:none;}
|
|
2141
|
+
.rc-branch-copy.copied .ico-copy{display:none;}
|
|
2142
|
+
.rc-branch-copy.copied .ico-check{display:inline;color:var(--green-ink);}
|
|
2143
|
+
/* "Copied" caption — the CSS-only mechanism .hd-copied / .hist-copied use, driven
|
|
2144
|
+
off copyBranchToClipboard's own 1200ms `.copied` window (app.js:3666-3672). */
|
|
2145
|
+
.rc-copied{display:none;font:500 11px var(--sans);color:var(--green-ink);}
|
|
2146
|
+
.rc-branch-copy.copied + .rc-copied{display:inline;}
|
|
2147
|
+
.rc-acts{display:flex;align-items:center;gap:8px;flex:0 0 auto;align-self:center;margin-left:auto;}
|
|
2148
|
+
.rc-qpill{display:inline-flex;align-items:center;padding:5px 11px;border-radius:999px;
|
|
2149
|
+
background:var(--amber-bg);color:var(--amber-ink);font:700 11.5px var(--sans);white-space:nowrap;}
|
|
2150
|
+
.rc-qpill[hidden]{display:none;}
|
|
2151
|
+
/* the four 30px icon buttons; .rc-open mirrors .hist-open exactly */
|
|
2152
|
+
.rc-acts .btn-pause,.rc-acts .btn-resume,.rc-acts .btn-stop,.rc-open{
|
|
2153
|
+
display:inline-flex;align-items:center;justify-content:center;gap:0;
|
|
2154
|
+
width:30px;height:30px;padding:0;border-radius:9px;background:var(--panel);cursor:pointer;}
|
|
2155
|
+
.rc-acts .btn-pause,.rc-acts .btn-resume{border:1px solid var(--amber);color:var(--amber-ink);}
|
|
2156
|
+
.rc-acts .btn-pause:hover,.rc-acts .btn-resume:hover{background:var(--amber-bg);}
|
|
2157
|
+
.rc-acts .btn-stop{border:1px solid var(--red);color:var(--red-ink);}
|
|
2158
|
+
.rc-acts .btn-stop:hover{background:var(--red-bg);}
|
|
2159
|
+
/* The base `.btn-pause[hidden],.btn-resume[hidden]` rule (254) ties on specificity
|
|
2160
|
+
with `.rc-acts .btn-pause` above and would LOSE on source order — a paused card
|
|
2161
|
+
would show both buttons. Re-state it at the cluster's specificity. */
|
|
2162
|
+
.rc-acts .btn-pause[hidden],.rc-acts .btn-resume[hidden]{display:none;}
|
|
2163
|
+
.rc-open{border:1px solid var(--line);color:var(--ink-2);}
|
|
2164
|
+
.rc-open:hover{background:var(--ink);color:#fff;border-color:var(--ink);}
|
|
2165
|
+
.rc-open:focus-visible,.rc-branch-copy:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2166
|
+
/* ---------- Running redesign: shared keyframes (C2 — declared ONCE, here) ----------
|
|
2167
|
+
@keyframes are name-resolved, not cascaded, so their position relative to the
|
|
2168
|
+
rules that use them is irrelevant; what matters is that there is exactly one of
|
|
2169
|
+
each. Tasks 5, 6, 7, 10 and 12 grep before adding and add nothing. */
|
|
2170
|
+
@keyframes wr-spin{to{transform:rotate(360deg);}}
|
|
2171
|
+
@keyframes wr-pulse{0%,100%{opacity:1;transform:scale(1);}50%{opacity:.45;transform:scale(.82);}}
|
|
2172
|
+
@keyframes wr-rise{0%{transform:translateY(10px);opacity:0;}100%{transform:translateY(0);opacity:1;}}
|
|
2173
|
+
@keyframes wr-blink{0%,49%{opacity:1;}50%,100%{opacity:0;}}
|
|
2174
|
+
/* Placed AFTER the rule it neutralizes — source order, not specificity, is what wins. */
|
|
2175
|
+
@media (prefers-reduced-motion: reduce){
|
|
2176
|
+
.rc-sic .sic-spin{animation:none;}
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
/* ---------- Running list: density toggle + compact card body ---------- */
|
|
2180
|
+
/* .topbar is `justify-content:space-between` with three children now; pushing the
|
|
2181
|
+
pill right keeps pill + toggle together as the right-hand group. */
|
|
2182
|
+
#running-status-pill{margin-left:auto;}
|
|
2183
|
+
.run-density{display:inline-flex;align-items:center;gap:2px;padding:3px;border-radius:999px;
|
|
2184
|
+
background:var(--field);flex:0 0 auto;align-self:center;}
|
|
2185
|
+
/* `.rc-dseg`, not `.rd-seg`: the density toggle is LIST chrome, and the Global
|
|
2186
|
+
Constraints reserve `.rd-*` for the run DETAIL — `.rd-seg` also sits one
|
|
2187
|
+
character from C1's `secClass:'rd-sec'`, which the tab engine writes into the
|
|
2188
|
+
detail screen. */
|
|
2189
|
+
.run-density .rc-dseg{display:inline-flex;align-items:center;justify-content:center;
|
|
2190
|
+
width:32px;height:28px;padding:0;border:0;border-radius:999px;background:transparent;
|
|
2191
|
+
color:var(--ink-2);cursor:pointer;transition:background .15s,color .15s;}
|
|
2192
|
+
.run-density .rc-dseg:hover{color:var(--ink);}
|
|
2193
|
+
.run-density .rc-dseg[aria-pressed="true"]{background:var(--ink);color:#fff;}
|
|
2194
|
+
.run-density .rc-dseg:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2195
|
+
/* One body per density. The other is display:none — which zeroes its scrollers, so
|
|
2196
|
+
setRunDensity stashes .log scrollTop + .run-flow-wrap scrollLeft across the flip. */
|
|
2197
|
+
.run-card[data-density="compact"] .rc-detailed{display:none;}
|
|
2198
|
+
.run-card[data-density="detailed"] .rc-compact{display:none;}
|
|
2199
|
+
.rc-compact{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin-top:14px;}
|
|
2200
|
+
.rc-step-chip{padding:4px 10px;border-radius:999px;font:700 11px var(--mono);
|
|
2201
|
+
letter-spacing:.04em;background:var(--field);color:var(--ink-2);white-space:nowrap;}
|
|
2202
|
+
.rc-step-chip.st-blue{background:var(--blue-bg);color:var(--blue-ink);}
|
|
2203
|
+
.rc-step-chip.st-amber{background:var(--amber-bg);color:var(--amber-ink);}
|
|
2204
|
+
.rc-step-chip.st-green{background:var(--green-bg);color:var(--green-ink);}
|
|
2205
|
+
.rc-step-chip.st-red{background:var(--red-bg);color:var(--red-ink);}
|
|
2206
|
+
.rc-step-name{min-width:0;font:600 14.5px var(--sans);color:var(--ink);
|
|
2207
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
2208
|
+
.rc-step-model{font:400 12px var(--mono);color:var(--ink-3);margin-left:auto;white-space:nowrap;}
|
|
2209
|
+
.rc-step-model[hidden]{display:none;}
|
|
2210
|
+
/* .run-top's old 18px bottom margin used to open this gap. */
|
|
2211
|
+
.rc-detailed{margin-top:18px;}
|
|
2212
|
+
|
|
2213
|
+
/* ---------- Running two-screen shell (twin of the History track, 1591-1603) ---------- */
|
|
2214
|
+
.view[data-view="running"]{flex:1 1 auto;min-height:0;padding:0;position:relative;}
|
|
2215
|
+
.run-shell{position:relative;height:100%;overflow:hidden;}
|
|
2216
|
+
/* NO top padding on the scroller itself — T7's sticky .rd-tabs must pin flush to
|
|
2217
|
+
the scrollport top, exactly as .hist-screen does for .hd-tabs. */
|
|
2218
|
+
.run-screen{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;padding:0 32px 40px;
|
|
2219
|
+
transition:transform .46s cubic-bezier(.65,.02,.28,1);}
|
|
2220
|
+
.run-screen-list .topbar{padding-top:26px;}
|
|
2221
|
+
.run-screen-list{transform:translateX(0);}
|
|
2222
|
+
.run-screen-detail{transform:translateX(100%);padding:0;background:var(--bg);}
|
|
2223
|
+
.run-shell.detail-open .run-screen-list{transform:translateX(-100%);}
|
|
2224
|
+
.run-shell.detail-open .run-screen-detail{transform:translateX(0);}
|
|
2225
|
+
.run-shell.no-anim .run-screen{transition:none;}
|
|
2226
|
+
/* Same reasoning as body.view-history .main (222) and .topnav (227): .main stops
|
|
2227
|
+
scrolling and becomes the bounded column so each screen owns its scrollport,
|
|
2228
|
+
and the compact top-nav (<1080px, a SIBLING of the views) re-applies the gutter
|
|
2229
|
+
.main just dropped. */
|
|
2230
|
+
body.view-running .main{display:flex;flex-direction:column;overflow:hidden;padding:0;}
|
|
2231
|
+
body.view-running .topnav{margin:12px 32px 0;flex:0 0 auto;}
|
|
2232
|
+
/* style.css has no base .mono rule (only ancestor-scoped ones) — scope one to the
|
|
2233
|
+
new subtree, exactly as :1608 does for .hd/.hist-card/#shipit-modal. */
|
|
2234
|
+
.rd .mono{font-family:var(--mono);}
|
|
2235
|
+
|
|
2236
|
+
/* ---------- Running detail: header card ---------- */
|
|
2237
|
+
/* Card, not a full-bleed band: .run-screen-detail keeps padding:0 so the sticky
|
|
2238
|
+
tabs can pin, and this margin box supplies the inset (mirrors .hd-header:1615). */
|
|
2239
|
+
.rd-header{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);
|
|
2240
|
+
box-shadow:var(--shadow);margin:20px 32px 0;padding:20px 24px 18px;}
|
|
2241
|
+
.rd-body{padding:0 32px 40px;}
|
|
2242
|
+
.rd-row1{display:flex;align-items:center;gap:14px;}
|
|
2243
|
+
.rd-title{margin:0;min-width:0;flex:1;font:700 22px/1.25 var(--sans);letter-spacing:-.02em;
|
|
2244
|
+
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
2245
|
+
.rd-status{flex:0 0 auto;}
|
|
2246
|
+
.rd-status[hidden]{display:none;}
|
|
2247
|
+
/* The design's slower, softer pulse; .pill-run .pdot (567) supplies the 7px dot
|
|
2248
|
+
and the family fill, this only re-times it. `.parked` = nothing is running. */
|
|
2249
|
+
.rd-status .pdot{animation:wr-pulse 1.6s ease-in-out infinite;}
|
|
2250
|
+
.rd-status.parked .pdot{animation:none;}
|
|
2251
|
+
.rd-meta{display:flex;align-items:center;flex-wrap:wrap;gap:8px;min-width:0;margin-top:12px;
|
|
2252
|
+
font:400 12.5px var(--mono);color:var(--ink-3);}
|
|
2253
|
+
.rd-meta .strong{font-weight:700;color:var(--ink);}
|
|
2254
|
+
.rd-dot{font-weight:700;color:var(--ink);}
|
|
2255
|
+
.rd-row3{display:flex;align-items:center;gap:8px;margin-top:6px;min-width:0;}
|
|
2256
|
+
.rd-base{color:var(--ink-3);font-size:12px;white-space:nowrap;}
|
|
2257
|
+
.rd-base[hidden]{display:none;}
|
|
2258
|
+
.rd-branch-copy{display:flex;align-items:center;gap:9px;min-width:16ch;padding:8px 12px;
|
|
2259
|
+
border:1px solid var(--line);border-radius:9px;background:var(--field);
|
|
2260
|
+
font:700 12px var(--mono);color:var(--ink);cursor:pointer;}
|
|
2261
|
+
.rd-branch-copy[hidden]{display:none;}
|
|
2262
|
+
.rd-branch-copy:hover{border-color:var(--ink-3);background:var(--panel);}
|
|
2263
|
+
.rd-branch-name{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
2264
|
+
.rd-branch-copy .ico-check{display:none;}
|
|
2265
|
+
.rd-branch-copy.copied .ico-copy{display:none;}
|
|
2266
|
+
.rd-branch-copy.copied .ico-check{display:inline;color:var(--green-ink);}
|
|
2267
|
+
.rd-copied{display:none;font:500 11.5px var(--sans);color:var(--green-ink);}
|
|
2268
|
+
.rd-branch-copy.copied + .rd-copied{display:inline;}
|
|
2269
|
+
.rd-spacer{flex:1 1 24px;}
|
|
2270
|
+
.rd-pause{display:flex;align-items:center;gap:8px;padding:9px 15px;border:1.5px solid var(--amber-bg);
|
|
2271
|
+
border-radius:999px;background:var(--panel);font:600 12.5px var(--sans);color:var(--amber-ink);cursor:pointer;}
|
|
2272
|
+
.rd-pause[hidden]{display:none;}
|
|
2273
|
+
.rd-pause:hover:not([disabled]){background:var(--amber-bg);border-color:var(--amber);}
|
|
2274
|
+
.rd-pause[disabled]{opacity:.55;cursor:not-allowed;}
|
|
2275
|
+
/* Only one of the two glyphs shows; data-action decides which. */
|
|
2276
|
+
.rd-pause[data-action="pause"] .ico-play,.rd-pause[data-action="resume"] .ico-pause{display:none;}
|
|
2277
|
+
.rd-stop{display:flex;align-items:center;gap:8px;padding:9px 15px;border:1.5px solid var(--red-bg);
|
|
2278
|
+
border-radius:999px;background:var(--panel);font:600 12.5px var(--sans);color:var(--red-ink);cursor:pointer;}
|
|
2279
|
+
.rd-stop[hidden]{display:none;}
|
|
2280
|
+
.rd-stop:hover:not([disabled]){background:var(--red-bg);border-color:var(--red);}
|
|
2281
|
+
.rd-error{margin-top:24px;color:var(--red-ink);font-size:12.5px;}
|
|
2282
|
+
.rd-error[hidden]{display:none;}
|
|
2283
|
+
/* .btn-ghost declares no focus ring and .rd-back is focused programmatically by
|
|
2284
|
+
openRunDetail — same reasoning as the .hd-back arm. */
|
|
2285
|
+
.rd-back{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;}
|
|
2286
|
+
.rd-back:focus-visible,.rd-pause:focus-visible,.rd-stop:focus-visible,
|
|
2287
|
+
.rd-branch-copy:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2288
|
+
|
|
2289
|
+
/* MUST sit after the rules above: @media contributes no specificity, so an
|
|
2290
|
+
earlier placement would lose the source-order tie (see the note at :1927-1932). */
|
|
2291
|
+
@media (prefers-reduced-motion: reduce){
|
|
2292
|
+
.run-screen{transition:none;}
|
|
2293
|
+
.rd-status .pdot,.rd-status.parked .pdot{animation:none;}
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
/* ---------- Running detail: pipeline graph ---------- */
|
|
2297
|
+
/* The dot-grid panel spec §5.3 asks for is already `.run-flow-wrap` —
|
|
2298
|
+
radial-gradient var(--line-2) 1.1px at 22px 22px, 18px radius, horizontal
|
|
2299
|
+
scroll. This only supplies the margin box; the wrap's own legacy
|
|
2300
|
+
`margin:0 0 18px` is zeroed so it does not double up with .rd-graph's. */
|
|
2301
|
+
.rd-graph{margin-top:18px;}
|
|
2302
|
+
.rd-graph .run-flow-wrap{margin:0;}
|
|
2303
|
+
|
|
2304
|
+
/* ---------- Running detail: banners ---------- */
|
|
2305
|
+
/* align-items:flex-start, NOT the default stretch: `.hist-discard` is an
|
|
2306
|
+
inline-flex button with no width and a stretching column would blow it up to
|
|
2307
|
+
the full body width. Only the two BANNERS want the full row. Same shape as
|
|
2308
|
+
.hd-banners. */
|
|
2309
|
+
.rd-banners{display:flex;flex-direction:column;align-items:flex-start;gap:12px;}
|
|
2310
|
+
/* Both reused banners carry legacy margins from their old hosts —
|
|
2311
|
+
`.retained-banner{margin:0 0 18px}` and `.cost-banner{margin-top:12px}` —
|
|
2312
|
+
which double up with this column's own gap. */
|
|
2313
|
+
.rd-banners .retained-banner,.rd-banners .cost-banner{align-self:stretch;margin:0;}
|
|
2314
|
+
/* NOT `:empty` — the container always holds its two template children, just
|
|
2315
|
+
hidden. Key the margin off "has a visible child", as .hd-banners does. */
|
|
2316
|
+
.rd-banners:has(> :not([hidden])){margin-top:18px;}
|
|
2317
|
+
|
|
2318
|
+
/* ---------- Running detail: question panel ---------- */
|
|
2319
|
+
/* Container only — the panel's own restyle (larger metrics, green-tinted picked
|
|
2320
|
+
options, the "N of M answered" footer, "Open run") is T11 for BOTH mounts. */
|
|
2321
|
+
.rd-questions{margin-top:18px;animation:wr-rise .3s cubic-bezier(.2,.7,.3,1) both;}
|
|
2322
|
+
/* Explicit twin: the UA [hidden] rule is (0,0,0) and loses to any author
|
|
2323
|
+
`display`, so without this the panel would render even while hidden. */
|
|
2324
|
+
.rd-questions[hidden]{display:none;}
|
|
2325
|
+
/* .qpanel ships `margin-top:18px` which would double up with the wrapper's.
|
|
2326
|
+
T11 rewrites the .qpanel block mid-file but does NOT restate this rule, so it
|
|
2327
|
+
stays the last word on margin-top for the detail mount. */
|
|
2328
|
+
.rd-questions .qpanel{margin-top:0;}
|
|
2329
|
+
|
|
2330
|
+
/* MUST sit after the rule it neutralizes — @media contributes no specificity. */
|
|
2331
|
+
@media (prefers-reduced-motion: reduce){
|
|
2332
|
+
.rd-questions{animation:none;}
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
/* ---------- Running detail: tab bodies ---------- */
|
|
2336
|
+
/* NB: no `.mono` rule here. `.rd .mono{font-family:var(--mono);}` already ships
|
|
2337
|
+
and `#run-detail-tpl`'s root IS `<div class="rd">`, so the subtree is covered;
|
|
2338
|
+
a second `#run-detail .mono` would be dead weight. (History's twin is the
|
|
2339
|
+
`.hd .mono,.hist-card .mono,#shipit-modal .mono` rule mid-file.) */
|
|
2340
|
+
|
|
2341
|
+
/* Section tabs (§5.5 + C12). WITHOUT these rules the pill row renders as three
|
|
2342
|
+
unstyled native buttons and nothing pins on scroll. Twin of
|
|
2343
|
+
`.hd-tabs`/`.hd-tab`/`.hd-tab-badge`/`.hd-sec`; `.run-screen-detail` keeps
|
|
2344
|
+
`padding:0` precisely so `top:0` pins flush to the scrollport (D12).
|
|
2345
|
+
NO horizontal margin, deliberately: both hosts live INSIDE `.rd-body`, which
|
|
2346
|
+
carries `padding:0 32px 40px` — the exact shape of `.hd-body` and `.hd-tabs`,
|
|
2347
|
+
which carries no margin for precisely this reason. Adding `margin:0 32px` here
|
|
2348
|
+
would double the inset to 64px AND stop the pinned bar's `background:var(--bg)`
|
|
2349
|
+
32px short on each side, so scrolled content would show through the gutters
|
|
2350
|
+
behind it. */
|
|
2351
|
+
.rd-tabs{position:sticky;top:0;z-index:5;display:flex;align-items:center;flex-wrap:wrap;gap:8px;
|
|
2352
|
+
padding:18px 0 14px;background:var(--bg);}
|
|
2353
|
+
.rd-tab{display:flex;align-items:center;gap:9px;padding:10px 17px;border:1.5px solid var(--line);
|
|
2354
|
+
border-radius:999px;background:var(--panel);font:600 13.5px var(--sans);color:var(--ink-2);cursor:pointer;}
|
|
2355
|
+
.rd-tab:hover{border-color:var(--ink-3);color:var(--ink);}
|
|
2356
|
+
.rd-tab.active{background:var(--ink);color:#fff;border-color:var(--ink);}
|
|
2357
|
+
.rd-tab:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2358
|
+
.rd-tab-badge{padding:2px 8px;border-radius:999px;background:var(--field);color:var(--ink-3);
|
|
2359
|
+
font:600 10.5px var(--mono);}
|
|
2360
|
+
.rd-tab.active .rd-tab-badge{background:var(--blue-bg);color:var(--blue-ink);}
|
|
2361
|
+
/* .rd-sections needs no rule of its own — the inset comes from .rd-body's
|
|
2362
|
+
padding, exactly as .hd-sections does. */
|
|
2363
|
+
.rd-sec{margin-top:4px;}
|
|
2364
|
+
/* Explicit twin, exactly as `.hd-sec[hidden]`: the UA [hidden] rule is (0,0,0)
|
|
2365
|
+
and loses to any author `display`, so the moment a `.rd-sec-*` body gets one,
|
|
2366
|
+
every inactive panel would render at once. */
|
|
2367
|
+
.rd-sec[hidden]{display:none;}
|
|
2368
|
+
.rd-sec:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2369
|
+
|
|
2370
|
+
/* Live log tab (§5.6): white pane, --line border, 16px radius, bounded height.
|
|
2371
|
+
The pane is the shared `.log` markup inside a `.run-log` block, so `.run-log .log`
|
|
2372
|
+
is (0,2,0) and so is this — source order is what makes it win, which is why the
|
|
2373
|
+
rule lives at the END of the file and must not be moved above it. */
|
|
2374
|
+
.rd-sec-logs .log{min-height:300px;max-height:520px;
|
|
2375
|
+
background:var(--panel);border:1px solid var(--line);border-radius:16px;}
|
|
2376
|
+
/* §9's fourth keyframe: the blinking green caret at the tail of a LIVE log.
|
|
2377
|
+
CSS-only (a ::after on the pane) so no JS has to keep an element last after
|
|
2378
|
+
every append; Task 9 stamps `.rd-terminal` on the screen when the run ends and
|
|
2379
|
+
the caret disappears — "the log stops growing" (D8). */
|
|
2380
|
+
.rd-sec-logs .log::after{content:'';display:inline-block;width:7px;height:13px;
|
|
2381
|
+
vertical-align:-2px;margin-left:2px;background:var(--green);
|
|
2382
|
+
animation:wr-blink 1.05s step-end infinite;}
|
|
2383
|
+
/* Descendant form on purpose: Task 9 stamps `.rd-terminal` on the SCREEN
|
|
2384
|
+
(`screen.classList.toggle('rd-terminal', terminal)`), which is an ancestor of
|
|
2385
|
+
`.rd-sec-logs` — do not "fix" this to `.rd-terminal.rd-sec-logs`. */
|
|
2386
|
+
.rd-terminal .rd-sec-logs .log::after{display:none;}
|
|
2387
|
+
/* The pane's OTHER empty state: a live run whose filter matches none of its
|
|
2388
|
+
lines. A caret blinking after "(no lines match the filter)" reads as a tail
|
|
2389
|
+
about to print. Keyed on `data-empty` and not on emptiness in general —
|
|
2390
|
+
rdRepaintLog stamps it only when r.logLines is non-empty, so a fresh live run
|
|
2391
|
+
with zero lines correctly keeps its caret. */
|
|
2392
|
+
.rd-sec-logs .log[data-empty]::after{display:none;}
|
|
2393
|
+
|
|
2394
|
+
/* Overview tab (§5.7). The stat cards, the task card and the chips deliberately
|
|
2395
|
+
reuse History's `.hd-ov-*` rules — hdStatCard emits those class names, so
|
|
2396
|
+
re-declaring them here would fork one card design into two. Only the
|
|
2397
|
+
current-state banner is new. */
|
|
2398
|
+
.rd-ov-state{display:flex;align-items:center;flex-wrap:wrap;gap:12px;padding:16px 20px;
|
|
2399
|
+
background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);}
|
|
2400
|
+
.rd-ov-chip{padding:5px 12px;border-radius:999px;font:600 11.5px var(--sans);
|
|
2401
|
+
background:var(--field);color:var(--ink-2);}
|
|
2402
|
+
.rd-ov-chip.st-blue{background:var(--blue-bg);color:var(--blue-ink);}
|
|
2403
|
+
.rd-ov-chip.st-amber{background:var(--amber-bg);color:var(--amber-ink);}
|
|
2404
|
+
.rd-ov-chip.st-green{background:var(--green-bg);color:var(--green-ink);}
|
|
2405
|
+
.rd-ov-chip.st-red{background:var(--red-bg);color:var(--red-ink);}
|
|
2406
|
+
.rd-ov-copy{min-width:0;font:400 13px var(--sans);color:var(--ink-2);}
|
|
2407
|
+
|
|
2408
|
+
/* Agents tab (§5.8). History's card shell, but the spec's four-column GRID row
|
|
2409
|
+
instead of its flex row — which is why these carry their own class names
|
|
2410
|
+
rather than extending `.hd-ag-*`. */
|
|
2411
|
+
.rd-ag-group{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;}
|
|
2412
|
+
.rd-ag-group + .rd-ag-group{margin-top:14px;}
|
|
2413
|
+
.rd-ag-head{display:flex;align-items:center;flex-wrap:wrap;gap:12px;padding:15px 20px;
|
|
2414
|
+
border-bottom:1px solid var(--line);}
|
|
2415
|
+
.rd-ag-head b{font-size:13.5px;font-weight:600;letter-spacing:-.01em;}
|
|
2416
|
+
.rd-ag-meta{color:var(--ink-3);font-size:11.5px;margin-left:auto;}
|
|
2417
|
+
.rd-ag-none{padding:12px 20px;}
|
|
2418
|
+
.rd-ag-row{display:grid;grid-template-columns:1fr 130px 96px 84px;align-items:center;gap:10px;
|
|
2419
|
+
padding:12px 20px;border-top:1px solid var(--line);}
|
|
2420
|
+
/* NOT `:first-of-type` — `.rd-ag-head` is the first div in the card, so no row
|
|
2421
|
+
would ever match it (the same trap the `.hd-ag-head + .hd-ag-row` rule
|
|
2422
|
+
documents). */
|
|
2423
|
+
.rd-ag-head + .rd-ag-row{border-top:none;}
|
|
2424
|
+
.rd-ag-name{display:flex;align-items:center;gap:9px;min-width:0;font:500 13px var(--sans);color:var(--ink);}
|
|
2425
|
+
.rd-ag-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
2426
|
+
.rd-ag-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto;background:var(--ink-3);}
|
|
2427
|
+
.rd-ag-dot.run{background:var(--blue);animation:wr-pulse 1.6s ease-in-out infinite;}
|
|
2428
|
+
.rd-ag-dot.done{background:var(--green);}
|
|
2429
|
+
.rd-ag-dot.stop{background:var(--red);}
|
|
2430
|
+
.rd-ag-state{font:500 12px var(--sans);}
|
|
2431
|
+
.rd-ag-state.run{color:var(--blue-ink);}
|
|
2432
|
+
.rd-ag-state.done{color:var(--green-ink);}
|
|
2433
|
+
.rd-ag-state.stop{color:var(--red-ink);}
|
|
2434
|
+
.rd-ag-dur,.rd-ag-cost{text-align:right;font-size:11.5px;color:var(--ink-2);}
|
|
2435
|
+
/* skillPillsHtml emits `.subs-skills` into the head AND every row; in a grid row
|
|
2436
|
+
it must claim a full line of its own, the grid twin of the flex rule above. */
|
|
2437
|
+
.rd-ag-row .subs-skills{grid-column:1/-1;margin-top:6px;}
|
|
2438
|
+
/* AFTER the rules it neutralizes — source order, not specificity, is what makes
|
|
2439
|
+
this win in this stylesheet. */
|
|
2440
|
+
@media (prefers-reduced-motion: reduce){
|
|
2441
|
+
.rd-ag-dot.run{animation:none;}
|
|
2442
|
+
.rd-sec-logs .log::after{animation:none;}
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
/* ---------- Running detail: terminal state (D8) ---------- */
|
|
2446
|
+
/* NOTE: `.rd-status.parked .pdot{animation:none;}` is NOT repeated here — the
|
|
2447
|
+
header CSS already ships it (its (0,3,0) beats `.pill-run .pdot`), and a second
|
|
2448
|
+
copy would only make the sweep noisier. This task adds the class. */
|
|
2449
|
+
|
|
2450
|
+
/* A finished run stops moving. `runStepperView` only nulls activeId when the
|
|
2451
|
+
status is exactly 'done', so a STOPPED or ERRORED run's frontier node can still
|
|
2452
|
+
be `now` and its wire would march forever. Neutralize the three motions the
|
|
2453
|
+
graph carries rather than fighting the adapter.
|
|
2454
|
+
VERIFIED selector shapes at HEAD: nodes carry BOTH `node` and `run-node`
|
|
2455
|
+
(`.run-flow .node.run-node`), the glow rule is `.run-flow .node.is-active`, the
|
|
2456
|
+
wire rule is `.run-flow .wires path.wire-live` and the fan rule is
|
|
2457
|
+
`.run-flow .node .fan .sq.on`. Each override below is one class deeper than the
|
|
2458
|
+
rule it beats, so it wins on specificity, not source order. */
|
|
2459
|
+
.rd-graph.settled .run-flow .wires path.wire-live{animation:none;}
|
|
2460
|
+
/* Belt-and-braces: `runStatusOf` already returns 'stopped'/'done' for every node
|
|
2461
|
+
once the run is halted, so a terminal graph carries no `.is-active` — these two
|
|
2462
|
+
are no-ops today and exist only so a future adapter change cannot resurrect the
|
|
2463
|
+
glow. `.is-paused` is included because a run halted while parked keeps
|
|
2464
|
+
`nodeStatus === 'pause'`. */
|
|
2465
|
+
.rd-graph.settled .run-flow .run-node.is-active{animation:none;}
|
|
2466
|
+
.rd-graph.settled .run-flow .run-node.is-paused{animation:none;}
|
|
2467
|
+
.rd-graph.settled .run-flow .run-node .fan .sq.on{animation:none;}
|
|
2468
|
+
|
|
2469
|
+
.rd-history-link{flex:0 0 auto;font:600 12.5px var(--sans);color:var(--blue-ink);text-decoration:none;}
|
|
2470
|
+
.rd-history-link:hover{text-decoration:underline;}
|
|
2471
|
+
.rd-history-link[hidden]{display:none;}
|
|
2472
|
+
.rd-history-link:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2473
|
+
|
|
2474
|
+
/* ---------- "Stop this pipeline?" confirm modal (design §6) ---------- */
|
|
2475
|
+
/* WIDTH GOES ON `#stop-modal .card`, NOT `.stop-card`. The markup is
|
|
2476
|
+
`<div class="card stop-card">` inside `.viewer-modal`, and
|
|
2477
|
+
`.viewer-modal .card{width:min(860px,100%);…}` (:786) is (0,2,0): a bare
|
|
2478
|
+
`.stop-card{width:…}` (0,1,0) loses no matter where it is appended. Exact
|
|
2479
|
+
precedent: `#shipit-modal .card` (:1864). */
|
|
2480
|
+
#stop-modal .card{width:min(560px,100%);}
|
|
2481
|
+
.stop-card{padding:24px;animation:wr-rise .28s cubic-bezier(.2,.7,.3,1) both;}
|
|
2482
|
+
.stop-title{margin:0 0 12px;font:700 17px/1.25 var(--sans);letter-spacing:-.015em;}
|
|
2483
|
+
.stop-body{margin:0;font:400 13.5px/1.6 var(--sans);color:var(--ink-2);}
|
|
2484
|
+
.stop-ident{margin-top:14px;padding:11px 13px;background:var(--field);border-radius:14px;
|
|
2485
|
+
font:400 12px/1.6 var(--mono);color:var(--ink-2);word-break:break-all;}
|
|
2486
|
+
/* author display rule beats the UA [hidden] rule — a branch-less run must not
|
|
2487
|
+
leave a blank mono line in the block */
|
|
2488
|
+
.stop-ident-branch[hidden]{display:none;}
|
|
2489
|
+
.stop-err{margin-top:12px;}
|
|
2490
|
+
/* MANDATORY twin: the node is `class="hint err" hidden` and `.hint` (:285) sets
|
|
2491
|
+
display:block, which always beats the UA `[hidden]{display:none}`. Same as
|
|
2492
|
+
`.shipit-err[hidden]` (:1896). */
|
|
2493
|
+
.stop-err[hidden]{display:none;}
|
|
2494
|
+
.stop-actions{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:22px;}
|
|
2495
|
+
.stop-cancel{padding:11px 20px;border:1.5px solid var(--line-2);border-radius:999px;
|
|
2496
|
+
background:var(--panel);font:600 13.5px var(--sans);color:var(--ink);cursor:pointer;}
|
|
2497
|
+
.stop-cancel:hover{background:var(--field);}
|
|
2498
|
+
.stop-confirm{padding:11px 20px;border:1.5px solid transparent;border-radius:999px;
|
|
2499
|
+
background:var(--red-bg);font:600 13.5px var(--sans);color:var(--red-ink);cursor:pointer;}
|
|
2500
|
+
/* The mockup's hover is #F7D2CD — a shade §9 does not name and no token carries.
|
|
2501
|
+
brightness() keeps the darker-on-hover intent inside the existing palette (and
|
|
2502
|
+
out of Task 12's "one occurrence per new literal" assertion). */
|
|
2503
|
+
.stop-confirm:hover{filter:brightness(.97);}
|
|
2504
|
+
.stop-confirm:disabled{opacity:.6;cursor:default;}
|
|
2505
|
+
.stop-cancel:focus-visible,.stop-confirm:focus-visible{outline:2px solid var(--ink);outline-offset:2px;}
|
|
2506
|
+
|
|
2507
|
+
/* ---------- reduced motion for the Running redesign ---------- */
|
|
2508
|
+
/* MUST be the LAST block in the file: @media contributes no specificity, so a
|
|
2509
|
+
(0,1,0) `animation:none` here would LOSE the source-order tie against any
|
|
2510
|
+
`animation:wr-*` rule appended after it — exactly the trap documented at
|
|
2511
|
+
:748-763 for the four legacy names and at :1927-1940 for the ship-it set. */
|
|
2512
|
+
@media (prefers-reduced-motion: reduce){
|
|
2513
|
+
/* #stop-modal is a top-level overlay, outside the shell — named explicitly. */
|
|
2514
|
+
#stop-modal .card{animation:none;}
|
|
2515
|
+
/* PSEUDO-ELEMENTS DO NOT INHERIT `animation`, so the `*` blanket below cannot
|
|
2516
|
+
reach the live-log caret — it has to be named. (Task 7's own reduced-motion
|
|
2517
|
+
block already carries this rule; the duplicate here is deliberate belt-and-
|
|
2518
|
+
braces, because this block is the one guaranteed to be last.) */
|
|
2519
|
+
.rd-sec-logs .log::after{animation:none;}
|
|
2520
|
+
/* One scoped blanket for every ELEMENT inside the two Running screens: the
|
|
2521
|
+
status avatar spinner, the pulsing status/agent accent dots and the question
|
|
2522
|
+
panel's rise. `!important` (like the `*{transition:none !important}` rule in
|
|
2523
|
+
the legacy block) because enumerating them would restate selectors owned by
|
|
2524
|
+
Tasks 3/6/7/8 and silently rot the day one of them is renamed. The run-graph's
|
|
2525
|
+
own reduced-motion block (:1253-1258) is unaffected — it substitutes
|
|
2526
|
+
box-shadows, and only its redundant `animation:none` is overridden. */
|
|
2527
|
+
.run-shell *{animation:none !important;}
|
|
2528
|
+
}
|