@pat-lewczuk/cezar 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +249 -45
  2. package/dist/config.d.ts +15 -0
  3. package/dist/config.js +11 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/core/agent-runner.d.ts +44 -2
  6. package/dist/core/agent-runner.js +8 -2
  7. package/dist/core/agent-runner.js.map +1 -1
  8. package/dist/core/backend-detect.d.ts +6 -4
  9. package/dist/core/backend-detect.js +44 -4
  10. package/dist/core/backend-detect.js.map +1 -1
  11. package/dist/core/claude-cli-runner.d.ts +3 -25
  12. package/dist/core/claude-cli-runner.js +2 -19
  13. package/dist/core/claude-cli-runner.js.map +1 -1
  14. package/dist/core/codex-app-server-runner.d.ts +29 -0
  15. package/dist/core/codex-app-server-runner.js +452 -0
  16. package/dist/core/codex-app-server-runner.js.map +1 -0
  17. package/dist/core/ndjson.d.ts +6 -0
  18. package/dist/core/ndjson.js +23 -0
  19. package/dist/core/ndjson.js.map +1 -0
  20. package/dist/core/opencode-server-runner.d.ts +30 -0
  21. package/dist/core/opencode-server-runner.js +451 -0
  22. package/dist/core/opencode-server-runner.js.map +1 -0
  23. package/dist/core/runner-factory.d.ts +8 -0
  24. package/dist/core/runner-factory.js +22 -0
  25. package/dist/core/runner-factory.js.map +1 -0
  26. package/dist/git-worktree.d.ts +7 -0
  27. package/dist/git-worktree.js +14 -0
  28. package/dist/git-worktree.js.map +1 -1
  29. package/dist/planner.js +7 -3
  30. package/dist/planner.js.map +1 -1
  31. package/dist/runs/store.d.ts +7 -2
  32. package/dist/runs/store.js +3 -0
  33. package/dist/runs/store.js.map +1 -1
  34. package/dist/server/git.d.ts +5 -0
  35. package/dist/server/git.js +38 -0
  36. package/dist/server/git.js.map +1 -1
  37. package/dist/server/github.d.ts +2 -1
  38. package/dist/server/github.js +17 -10
  39. package/dist/server/github.js.map +1 -1
  40. package/dist/server/pr.js +7 -1
  41. package/dist/server/pr.js.map +1 -1
  42. package/dist/server/server.js +207 -20
  43. package/dist/server/server.js.map +1 -1
  44. package/dist/skills.d.ts +11 -9
  45. package/dist/skills.js +74 -13
  46. package/dist/skills.js.map +1 -1
  47. package/dist/workflows/load.js +5 -3
  48. package/dist/workflows/load.js.map +1 -1
  49. package/dist/workflows/run.d.ts +3 -0
  50. package/dist/workflows/run.js +43 -11
  51. package/dist/workflows/run.js.map +1 -1
  52. package/dist/workflows/types.d.ts +87 -8
  53. package/dist/workflows/types.js +54 -2
  54. package/dist/workflows/types.js.map +1 -1
  55. package/package.json +1 -1
  56. package/web/app.js +1180 -88
  57. package/web/index.html +16 -7
  58. package/web/open-mercato.svg +11 -0
  59. package/web/style.css +458 -56
package/web/style.css CHANGED
@@ -128,6 +128,18 @@ summary::-webkit-details-marker { display: none; }
128
128
  white-space: nowrap;
129
129
  }
130
130
  .btn-text:hover { background: var(--panel2); color: var(--text); }
131
+ .btn-text .bi, .btn-dark .bi {
132
+ width: 12px;
133
+ height: 12px;
134
+ margin-right: 6px;
135
+ vertical-align: -1.5px;
136
+ fill: none;
137
+ stroke: currentColor;
138
+ stroke-width: 1.8;
139
+ stroke-linecap: round;
140
+ stroke-linejoin: round;
141
+ }
142
+ .btn-text .bi-fill, .btn-dark .bi-fill { fill: currentColor; stroke: none; width: 11px; height: 11px; }
131
143
  .btn-text.danger { color: var(--red); }
132
144
  .btn-text:disabled { opacity: 0.45; cursor: default; }
133
145
 
@@ -217,8 +229,8 @@ summary::-webkit-details-marker { display: none; }
217
229
  /* ---- sidebar ---- */
218
230
 
219
231
  #sidebar {
220
- width: 288px;
221
- min-width: 288px;
232
+ width: 318px;
233
+ min-width: 318px;
222
234
  display: flex;
223
235
  flex-direction: column;
224
236
  min-height: 0;
@@ -279,11 +291,11 @@ summary::-webkit-details-marker { display: none; }
279
291
  #task-thumbs img { height: 38px; border-radius: 7px; border: 1px solid var(--line2); display: block; }
280
292
  #task-thumbs .thumb:hover img { border-color: var(--red); opacity: 0.7; }
281
293
  #new-task .row { display: flex; gap: 7px; align-items: center; }
294
+ #new-task .row.actions { flex-wrap: wrap; row-gap: 6px; }
282
295
 
283
296
  /* pill dropdowns — "≡ fix-and-verify ⌄" / "⊞ auto ⌄" */
284
297
  .pill-select { position: relative; min-width: 0; }
285
- #src-pill { flex: 0 1 auto; min-width: 0; }
286
- #model-pill { flex: 0 1 auto; min-width: 0; }
298
+ #src-pill, #model-pill, #runner-pill { flex: 0 1 auto; min-width: 0; }
287
299
  .pill-btn {
288
300
  display: inline-flex;
289
301
  align-items: center;
@@ -382,6 +394,16 @@ summary::-webkit-details-marker { display: none; }
382
394
  .pill-menu .menu-item:hover { background: color-mix(in oklab, var(--text) 7%, transparent); }
383
395
  .pill-menu .mi-title { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--text); }
384
396
  .pill-menu .mi-title .chk { width: 12px; flex: none; color: var(--accent); font-size: 11px; }
397
+ .pill-menu .mi-title .mi-ic {
398
+ width: 11px;
399
+ height: 11px;
400
+ flex: none;
401
+ fill: none;
402
+ stroke: var(--accent);
403
+ stroke-width: 1.8;
404
+ stroke-linejoin: round;
405
+ opacity: 0.9;
406
+ }
385
407
  .pill-menu .mi-desc {
386
408
  margin: 2px 0 0 19px;
387
409
  font-size: 11px;
@@ -443,44 +465,86 @@ summary::-webkit-details-marker { display: none; }
443
465
  #run-btn:hover { opacity: 0.88; }
444
466
  #run-btn:disabled { opacity: 0.45; cursor: default; }
445
467
 
446
- /* plan panel (spec 008) */
468
+ /* plan overlay (spec 008; moved from the sidebar to the main window) */
469
+ #plan-overlay {
470
+ position: fixed;
471
+ inset: 0;
472
+ z-index: 60;
473
+ background: color-mix(in oklab, var(--bg) 55%, transparent);
474
+ backdrop-filter: blur(3px);
475
+ display: flex;
476
+ align-items: flex-start;
477
+ justify-content: center;
478
+ padding: 9vh 24px 24px;
479
+ }
480
+ #plan-overlay[hidden] { display: none; }
447
481
  #plan-panel {
448
- margin-top: 10px;
449
- border: 1px solid var(--line);
450
- border-radius: 12px;
482
+ width: min(640px, 94vw);
483
+ max-height: 78vh;
484
+ overflow-y: auto;
485
+ border: 1px solid var(--line2);
486
+ border-radius: 16px;
451
487
  background: var(--card);
452
- box-shadow: var(--shadow-sm);
453
- padding: 10px 11px;
488
+ box-shadow: 0 24px 80px rgba(0, 0, 0, 0.35);
489
+ padding: 18px 20px;
454
490
  display: flex;
455
491
  flex-direction: column;
456
- gap: 8px;
492
+ gap: 10px;
493
+ }
494
+ .plan-head { display: flex; align-items: flex-start; gap: 10px; }
495
+ .plan-head > div:first-child { flex: 1; }
496
+ .plan-task {
497
+ font-family: var(--serif);
498
+ font-size: 17px;
499
+ font-weight: 500;
500
+ letter-spacing: -0.01em;
501
+ line-height: 1.35;
502
+ }
503
+ .plan-close {
504
+ width: 26px;
505
+ height: 26px;
506
+ flex: none;
507
+ display: inline-flex;
508
+ align-items: center;
509
+ justify-content: center;
510
+ border: none;
511
+ border-radius: 99px;
512
+ background: transparent;
513
+ color: var(--text3);
514
+ cursor: pointer;
515
+ font-size: 16px;
457
516
  }
458
- #plan-panel[hidden] { display: none; }
459
- .plan-note { font-size: 11.5px; color: var(--amber); }
460
- .plan-rationale { font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
461
- .plan-steps { display: flex; flex-direction: column; gap: 5px; }
517
+ .plan-close:hover { color: var(--text); background: var(--panel2); }
518
+ .plan-note { font-size: 12px; color: var(--amber); }
519
+ .plan-rationale { font-size: 12.5px; color: var(--text2); line-height: 1.55; max-width: 64ch; }
520
+ .plan-steps { display: flex; flex-direction: column; gap: 7px; }
462
521
  .plan-step {
463
522
  display: flex;
464
- align-items: center;
465
- gap: 6px;
523
+ align-items: flex-start;
524
+ gap: 10px;
466
525
  border: 1px solid var(--line);
467
- border-radius: 9px;
468
- padding: 5px 8px;
526
+ border-radius: 11px;
527
+ padding: 10px 12px;
469
528
  background: var(--bg);
470
- font-size: 12px;
529
+ font-size: 13px;
530
+ cursor: grab;
471
531
  }
472
532
  .plan-step.drag-over { border-color: var(--accent); }
473
- .plan-step .grip { cursor: grab; color: var(--text3); user-select: none; }
474
- .plan-step .num { color: var(--text3); font-family: var(--mono); font-size: 10.5px; }
475
- .plan-step .name { font-weight: 600; white-space: nowrap; }
533
+ .plan-step .grip { cursor: grab; color: var(--text3); user-select: none; margin-top: 1px; }
534
+ .plan-step .num { color: var(--text3); font-family: var(--mono); font-size: 10.5px; margin-top: 3px; }
535
+ .plan-step-main { flex: 1; min-width: 0; }
536
+ .plan-step .row1 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
537
+ .plan-step .name { font-weight: 600; }
476
538
  .plan-step .hint {
477
- flex: 1;
478
- min-width: 0;
479
- overflow: hidden;
480
- text-overflow: ellipsis;
481
- white-space: nowrap;
539
+ margin-top: 3px;
482
540
  font-family: var(--mono);
483
- font-size: 10.5px;
541
+ font-size: 11px;
542
+ line-height: 1.55;
543
+ color: var(--text3);
544
+ display: -webkit-box;
545
+ -webkit-line-clamp: 3;
546
+ -webkit-box-orient: vertical;
547
+ overflow: hidden;
484
548
  }
485
549
  .plan-badge {
486
550
  font-size: 9px;
@@ -500,11 +564,13 @@ summary::-webkit-details-marker { display: none; }
500
564
  color: var(--text3);
501
565
  cursor: pointer;
502
566
  padding: 0 2px;
503
- font-size: 12px;
567
+ font-size: 13px;
568
+ margin-top: 1px;
504
569
  }
505
570
  .plan-step .plan-remove:hover { color: var(--red); }
506
- .plan-actions { display: flex; gap: 6px; }
507
- .plan-actions .btn-dark, .plan-actions .btn-ghost { flex: 1; justify-content: center; height: 28px; font-size: 12px; }
571
+ .plan-actions { display: flex; gap: 8px; margin-top: 2px; }
572
+ .plan-actions .btn-dark, .plan-actions .btn-ghost { flex: 1; justify-content: center; height: 30px; font-size: 12.5px; }
573
+ #plan-btn.busy svg { animation: cz-pulse 1.2s ease-in-out infinite; }
508
574
 
509
575
  /* nav */
510
576
  #tabs { display: flex; flex-direction: column; gap: 1px; padding: 0 8px 10px; }
@@ -611,10 +677,10 @@ summary::-webkit-details-marker { display: none; }
611
677
  border-top: 1px solid var(--line);
612
678
  padding: 11px 16px;
613
679
  display: flex;
614
- align-items: center;
615
- gap: 12px;
680
+ align-items: flex-end;
681
+ gap: 8px;
616
682
  }
617
- #env-chips { display: flex; gap: 12px; min-width: 0; }
683
+ #env-chips { display: flex; flex-wrap: wrap; gap: 6px 9px; min-width: 0; flex: 1 1 auto; }
618
684
  .env-chip {
619
685
  display: flex;
620
686
  align-items: center;
@@ -628,6 +694,8 @@ summary::-webkit-details-marker { display: none; }
628
694
  .env-chip.bad .led { background: var(--red); }
629
695
  #theme-toggle {
630
696
  margin-left: auto;
697
+ align-self: flex-end;
698
+ flex: none;
631
699
  border: none;
632
700
  background: transparent;
633
701
  color: var(--text3);
@@ -733,6 +801,44 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
733
801
  margin-bottom: 9px;
734
802
  }
735
803
 
804
+ /* rendered markdown (handoff notes) */
805
+ .md { font-size: 13px; line-height: 1.65; color: var(--text); max-width: 72ch; }
806
+ .md h1, .md h2, .md h3, .md h4 { font-family: var(--serif); font-weight: 600; letter-spacing: -0.01em; margin: 18px 0 6px; }
807
+ .md h1 { font-size: 17px; }
808
+ .md h2 { font-size: 15px; }
809
+ .md h3, .md h4 { font-size: 13.5px; }
810
+ .md h1:first-child, .md h2:first-child { margin-top: 0; }
811
+ .md p { margin: 6px 0; }
812
+ .md ul, .md ol { margin: 6px 0; padding-left: 22px; }
813
+ .md li { margin: 3px 0; }
814
+ .md code {
815
+ font-family: var(--mono);
816
+ font-size: 11.5px;
817
+ background: var(--panel2);
818
+ border-radius: 5px;
819
+ padding: 1px 6px;
820
+ word-break: break-all;
821
+ }
822
+ .md pre {
823
+ margin: 8px 0;
824
+ padding: 11px 14px;
825
+ background: var(--card);
826
+ border: 1px solid var(--line);
827
+ border-radius: 10px;
828
+ overflow-x: auto;
829
+ }
830
+ .md pre code { background: transparent; padding: 0; word-break: normal; font-size: 11.5px; line-height: 1.6; }
831
+ .md hr { border: none; border-top: 1px solid var(--line); margin: 14px 0; }
832
+ .md strong { font-weight: 600; }
833
+ .md blockquote {
834
+ margin: 8px 0;
835
+ padding: 3px 14px;
836
+ border-left: 3px solid var(--line2);
837
+ color: var(--text2);
838
+ }
839
+ .md li.task { list-style: none; margin-left: -18px; }
840
+ .md li.task .cb { margin-right: 7px; color: var(--text2); }
841
+
736
842
  #review-panel { background: var(--accent-soft); border-bottom: 1px solid var(--accent-line); }
737
843
  #review-panel .panel-label { color: var(--accent); }
738
844
  #review-notes {
@@ -771,47 +877,66 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
771
877
  line-height: 1.7;
772
878
  margin: 9px 0;
773
879
  max-width: 66ch;
774
- white-space: pre-wrap;
775
880
  word-break: break-word;
776
881
  }
882
+ .ev.text.md p:first-child { margin-top: 0; }
883
+ .ev.text.md p:last-child { margin-bottom: 0; }
777
884
 
778
- .ev.tool, .ev.result > summary {
885
+ .ev.tool, .ev.result summary {
779
886
  display: inline-flex;
780
887
  align-items: center;
781
- gap: 8px;
782
- margin: 3px 8px 3px 0;
783
- padding: 5px 11px 5px 9px;
888
+ gap: 7px;
889
+ margin: 2px 8px 2px 0;
890
+ padding: 3px 9px 3px 8px;
784
891
  border: 1px solid var(--line);
785
- border-radius: 9px;
892
+ border-radius: 8px;
786
893
  background: var(--card);
787
- font-size: 12px;
894
+ font-size: 11.5px;
788
895
  color: var(--text2);
789
896
  max-width: 100%;
790
897
  }
791
- .ev.tool .ok { color: var(--green); font-size: 11px; }
898
+ .ev.tool .ok { color: var(--green); font-size: 10px; }
792
899
  .ev.tool .arg, .ev.tool code {
793
900
  font-family: var(--mono);
794
- font-size: 11px;
901
+ font-size: 10.5px;
795
902
  color: var(--text);
796
903
  background: var(--panel2);
797
904
  border-radius: 5px;
798
- padding: 1px 7px;
905
+ padding: 1px 6px;
799
906
  overflow: hidden;
800
907
  text-overflow: ellipsis;
801
908
  white-space: nowrap;
802
909
  max-width: 46ch;
803
910
  }
911
+ /* collapsed tool streaks (Claude-Code style) */
912
+ .ev.tool-streak { min-width: 0; margin: 4px 0; }
913
+ .streak-box { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
914
+ .streak-box[hidden] { display: none; }
915
+ .streak-toggle {
916
+ display: inline-flex;
917
+ align-items: center;
918
+ border: none;
919
+ background: transparent;
920
+ color: var(--text3);
921
+ font-family: var(--mono);
922
+ font-size: 10.5px;
923
+ cursor: pointer;
924
+ padding: 3px 2px;
925
+ margin: 1px 0;
926
+ }
927
+ .streak-toggle:hover { color: var(--text2); }
928
+
804
929
  .ev.result { margin: 4px 0; }
805
- .ev.result > summary { cursor: pointer; }
806
- .ev.result > summary:hover { border-color: var(--line2); }
807
- .ev.result > summary .lead-in { color: var(--text3); font-size: 11px; }
808
- .ev.result > summary .head {
930
+ .ev.result summary { cursor: pointer; }
931
+ .ev.result summary:hover { border-color: var(--line2); }
932
+ .ev.result summary .lead-in { color: var(--text3); font-size: 10px; }
933
+ .ev.result summary .head {
809
934
  overflow: hidden;
810
935
  text-overflow: ellipsis;
811
936
  white-space: nowrap;
812
937
  max-width: 60ch;
813
938
  }
814
- .ev.result > summary .show { font-family: var(--mono); font-size: 10px; color: var(--text3); }
939
+ .ev.result summary .show { font-family: var(--mono); font-size: 10px; color: var(--text3); }
815
940
  .ev.result pre, .ev.tool-detail pre {
816
941
  margin: 7px 0 4px;
817
942
  padding: 12px 15px;
@@ -824,7 +949,7 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
824
949
  font-family: var(--mono);
825
950
  font-size: 11.5px;
826
951
  }
827
- .ev.result.error > summary { color: var(--red); }
952
+ .ev.result.error summary { color: var(--red); }
828
953
 
829
954
  .ev.check {
830
955
  margin: 10px 0;
@@ -1039,7 +1164,9 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
1039
1164
 
1040
1165
  /* ---- split views (GitHub / Skills) ---- */
1041
1166
 
1042
- .split { flex: 1; min-height: 0; display: grid; grid-template-columns: 352px minmax(0, 1fr); }
1167
+ /* The list column grows with the viewport 352px was cramped on wide
1168
+ screens (feedback 2026-07-11). */
1169
+ .split { flex: 1; min-height: 0; display: grid; grid-template-columns: clamp(340px, 27vw, 560px) minmax(0, 1fr); }
1043
1170
  .split-list { border-right: 1px solid var(--line); display: flex; flex-direction: column; min-height: 0; }
1044
1171
  .split-list .split-head { padding: 24px 18px 0; }
1045
1172
  .split-list .head-row { display: flex; align-items: baseline; gap: 10px; }
@@ -1077,7 +1204,7 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
1077
1204
  .split-list .sub-tabs button.active { background: var(--panel2); color: var(--text); }
1078
1205
  .split-rows { flex: 1; overflow-y: auto; padding: 0 10px 14px; }
1079
1206
  .split-detail { overflow-y: auto; min-width: 0; }
1080
- .split-detail .inner { max-width: 700px; padding: 30px 38px 44px; }
1207
+ .split-detail .inner { max-width: 840px; padding: 30px 38px 44px; }
1081
1208
  .split-detail h1 {
1082
1209
  margin: 0;
1083
1210
  font-family: var(--serif);
@@ -1143,8 +1270,7 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
1143
1270
  border-bottom: 1px solid var(--line);
1144
1271
  font-size: 14px;
1145
1272
  line-height: 1.7;
1146
- max-width: 64ch;
1147
- white-space: pre-wrap;
1273
+ max-width: 68ch;
1148
1274
  word-break: break-word;
1149
1275
  }
1150
1276
  .gh-hand { margin-top: 24px; }
@@ -1192,6 +1318,8 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
1192
1318
  background: var(--panel2);
1193
1319
  }
1194
1320
  .skill-tag.team { color: var(--accent); background: color-mix(in oklab, var(--accent) 12%, transparent); }
1321
+ .skill-tag.agents { color: var(--green); background: color-mix(in oklab, var(--green) 11%, transparent); }
1322
+ .skill-tag.global { color: var(--amber); background: color-mix(in oklab, var(--amber) 12%, transparent); }
1195
1323
  .skill-detail .title-row { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
1196
1324
  .skill-detail .path-line { font-family: var(--mono); font-size: 11px; color: var(--text3); margin-top: 9px; word-break: break-all; }
1197
1325
  .skill-detail .desc { color: var(--text2); font-size: 14px; line-height: 1.65; margin-top: 12px; max-width: 60ch; }
@@ -1237,6 +1365,49 @@ main { flex: 1; min-width: 0; display: flex; min-height: 0; background: var(--bg
1237
1365
  .commit-row .hash { font-family: var(--mono); font-size: 11px; color: var(--text3); flex: none; }
1238
1366
  .commit-row .subj { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1239
1367
  .commit-row .when { font-family: var(--mono); font-size: 10.5px; color: var(--text3); flex: none; }
1368
+ .base-branch-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
1369
+ #base-branch {
1370
+ height: 30px;
1371
+ padding: 0 10px;
1372
+ border: 1px solid var(--line2);
1373
+ border-radius: 9px;
1374
+ background: var(--panel2);
1375
+ color: var(--text);
1376
+ font-family: var(--mono);
1377
+ font-size: 12px;
1378
+ outline: none;
1379
+ cursor: pointer;
1380
+ max-width: 320px;
1381
+ }
1382
+
1383
+ .commit-row.clickable { cursor: pointer; border-radius: 8px; padding: 5px 8px; margin: 0 -8px; align-items: center; }
1384
+ .commit-row.clickable:hover { background: var(--panel2); }
1385
+ .commit-row .chev {
1386
+ width: 10px;
1387
+ height: 10px;
1388
+ flex: none;
1389
+ fill: none;
1390
+ stroke: var(--text3);
1391
+ stroke-width: 2.2;
1392
+ stroke-linecap: round;
1393
+ transition: transform 0.12s ease;
1394
+ }
1395
+ .commit-row.open .chev { transform: rotate(90deg); }
1396
+ .commit-diff { margin: 2px 0 8px 22px; }
1397
+ .commit-gh { display: inline-block; font-size: 11.5px; margin: 4px 0 2px; }
1398
+ .commit-head {
1399
+ margin: 4px 0 8px;
1400
+ padding: 10px 13px;
1401
+ background: var(--card);
1402
+ border: 1px solid var(--line);
1403
+ border-radius: 10px;
1404
+ font-family: var(--mono);
1405
+ font-size: 11px;
1406
+ line-height: 1.6;
1407
+ color: var(--text2);
1408
+ overflow-x: auto;
1409
+ white-space: pre-wrap;
1410
+ }
1240
1411
  .repo-diff {
1241
1412
  border: 1px solid var(--line);
1242
1413
  border-radius: 12px;
@@ -1357,9 +1528,240 @@ a.bm:hover { border-color: var(--accent-line); color: var(--accent); text-decora
1357
1528
  .bm-copy:hover { border-color: var(--text3); color: var(--text); }
1358
1529
  .bm-hint { font-size: 11.5px; color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1359
1530
 
1531
+ /* ---- workflow builder (spec 012) ---- */
1532
+
1533
+ .wb-grid { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) 300px; }
1534
+ .wb-main { overflow-y: auto; min-width: 0; }
1535
+ .wb-inner { max-width: 620px; margin: 0 auto; padding: 30px 40px 60px; }
1536
+
1537
+ .wb-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
1538
+ .wb-head h1 {
1539
+ margin: 0;
1540
+ font-family: var(--serif);
1541
+ font-size: 25px;
1542
+ font-weight: 500;
1543
+ letter-spacing: -0.015em;
1544
+ flex: 1;
1545
+ min-width: 180px;
1546
+ }
1547
+ .wb-head .btn-dark { height: 29px; }
1548
+
1549
+ .wb-meta { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
1550
+ .wb-name-pill {
1551
+ display: inline-flex;
1552
+ align-items: center;
1553
+ gap: 7px;
1554
+ height: 30px;
1555
+ padding: 0 13px;
1556
+ border: 1px solid var(--line);
1557
+ border-radius: 99px;
1558
+ background: var(--panel2);
1559
+ }
1560
+ .wb-name-pill svg { width: 11px; height: 11px; fill: none; stroke: var(--text3); stroke-width: 2; stroke-linecap: round; flex: none; }
1561
+ .wb-name-pill input {
1562
+ border: none;
1563
+ background: transparent;
1564
+ color: var(--text);
1565
+ font-family: var(--mono);
1566
+ font-size: 12px;
1567
+ font-weight: 600;
1568
+ outline: none;
1569
+ padding: 0;
1570
+ width: 170px;
1571
+ }
1572
+ #wb-count { font-size: 11px; }
1573
+
1574
+ .wb-load { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 12px; }
1575
+ .wb-load .wb-k { font-size: 12px; color: var(--text3); }
1576
+ .wb-load .chip-toggle { height: 25px; font-size: 11.5px; }
1577
+
1578
+ .wb-import {
1579
+ margin-top: 14px;
1580
+ border: 1px solid var(--accent-line);
1581
+ border-radius: 13px;
1582
+ background: var(--card);
1583
+ padding: 13px 14px;
1584
+ box-shadow: var(--shadow-sm);
1585
+ }
1586
+ .wb-import-label {
1587
+ font-size: 10.5px;
1588
+ font-weight: 600;
1589
+ letter-spacing: 0.09em;
1590
+ text-transform: uppercase;
1591
+ color: var(--accent);
1592
+ margin-bottom: 8px;
1593
+ }
1594
+ .wb-import textarea {
1595
+ width: 100%;
1596
+ border: 1px solid var(--line);
1597
+ border-radius: 9px;
1598
+ background: var(--bg);
1599
+ color: var(--text);
1600
+ font-family: var(--mono);
1601
+ font-size: 11.5px;
1602
+ line-height: 1.6;
1603
+ resize: vertical;
1604
+ outline: none;
1605
+ padding: 9px 11px;
1606
+ }
1607
+ .wb-import-actions { display: flex; gap: 8px; margin-top: 9px; }
1608
+ .wb-import-actions .btn-dark, .wb-import-actions .btn-ghost { height: 28px; font-size: 12px; }
1609
+
1610
+ #wb-steps { margin-top: 16px; }
1611
+
1612
+ /* insertion gaps: a hairline at rest, dashed slots while dragging, an accent
1613
+ "drop to insert" slot under the pointer */
1614
+ .wb-gap { position: relative; display: flex; align-items: center; justify-content: center; height: 16px; transition: height 0.12s ease; }
1615
+ .wb-gap-inner {
1616
+ width: 1.5px;
1617
+ height: 100%;
1618
+ background: var(--line2);
1619
+ pointer-events: none;
1620
+ overflow: hidden;
1621
+ font-size: 0;
1622
+ color: transparent;
1623
+ }
1624
+ .wb-dragging .wb-gap { height: 28px; }
1625
+ .wb-dragging .wb-gap-inner {
1626
+ width: 100%;
1627
+ height: 16px;
1628
+ border: 1.5px dashed var(--line2);
1629
+ border-radius: 9px;
1630
+ background: transparent;
1631
+ }
1632
+ .wb-dragging .wb-gap.over { height: 46px; }
1633
+ .wb-dragging .wb-gap.over .wb-gap-inner {
1634
+ height: 36px;
1635
+ border-color: var(--accent);
1636
+ border-radius: 11px;
1637
+ background: color-mix(in oklab, var(--accent) 7%, transparent);
1638
+ display: flex;
1639
+ align-items: center;
1640
+ justify-content: center;
1641
+ font-size: 11px;
1642
+ font-weight: 600;
1643
+ color: var(--accent);
1644
+ }
1645
+ /* empty canvas: one big always-visible drop slot */
1646
+ .wb-gap.tall, .wb-dragging .wb-gap.tall { height: 72px; }
1647
+ .wb-gap.tall .wb-gap-inner, .wb-dragging .wb-gap.tall .wb-gap-inner {
1648
+ width: 100%;
1649
+ height: 100%;
1650
+ border: 1.5px dashed var(--line2);
1651
+ border-radius: 13px;
1652
+ background: transparent;
1653
+ display: flex;
1654
+ align-items: center;
1655
+ justify-content: center;
1656
+ font-size: 12px;
1657
+ color: var(--text3);
1658
+ }
1659
+ .wb-gap.tall.over .wb-gap-inner, .wb-dragging .wb-gap.tall.over .wb-gap-inner {
1660
+ border-color: var(--accent);
1661
+ color: var(--accent);
1662
+ background: color-mix(in oklab, var(--accent) 7%, transparent);
1663
+ }
1664
+
1665
+ .wb-step {
1666
+ display: flex;
1667
+ gap: 12px;
1668
+ align-items: center;
1669
+ padding: 12px 15px;
1670
+ border: 1px solid var(--line2);
1671
+ border-radius: 13px;
1672
+ box-shadow: var(--shadow-sm);
1673
+ cursor: grab;
1674
+ background: var(--card);
1675
+ }
1676
+ .wb-step.drag-src { opacity: 0.35; }
1677
+ .wb-step .grip { flex: none; fill: var(--text3); }
1678
+ .wb-step .num { font-size: 10px; color: var(--text3); flex: none; width: 18px; }
1679
+ .wb-ic { width: 14px; height: 14px; fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-linejoin: round; flex: none; }
1680
+ .wb-step-main { flex: 1; min-width: 0; }
1681
+ .wb-step-name { font-size: 12.5px; font-weight: 600; color: var(--text); }
1682
+ .wb-step-desc {
1683
+ font-size: 11px;
1684
+ color: var(--text3);
1685
+ margin-top: 2px;
1686
+ line-height: 1.45;
1687
+ overflow: hidden;
1688
+ text-overflow: ellipsis;
1689
+ white-space: nowrap;
1690
+ }
1691
+ .wb-badge {
1692
+ flex: none;
1693
+ font-size: 9.5px;
1694
+ font-weight: 600;
1695
+ letter-spacing: 0.06em;
1696
+ text-transform: uppercase;
1697
+ padding: 2px 8px;
1698
+ border-radius: 99px;
1699
+ color: var(--text2);
1700
+ background: var(--panel2);
1701
+ }
1702
+ .wb-badge.unknown { color: var(--amber); background: color-mix(in oklab, var(--amber) 13%, transparent); }
1703
+ .wb-badge.check { color: var(--green); background: color-mix(in oklab, var(--green) 12%, transparent); }
1704
+ .wb-remove {
1705
+ width: 24px;
1706
+ height: 24px;
1707
+ flex: none;
1708
+ display: inline-flex;
1709
+ align-items: center;
1710
+ justify-content: center;
1711
+ border: none;
1712
+ border-radius: 99px;
1713
+ background: transparent;
1714
+ color: var(--text3);
1715
+ cursor: pointer;
1716
+ font-size: 14px;
1717
+ }
1718
+ .wb-remove:hover { color: var(--red); background: color-mix(in oklab, var(--red) 10%, transparent); }
1719
+ .wb-flow-note { display: flex; align-items: center; gap: 9px; justify-content: center; margin-top: 2px; font-size: 11.5px; color: var(--text3); }
1720
+ .wb-flow-note svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
1721
+
1722
+ .wb-aside { border-left: 1px solid var(--line); background: var(--panel); overflow-y: auto; padding: 24px 16px; }
1723
+ .wb-hint { font-size: 11px; color: var(--text3); margin-bottom: 9px; line-height: 1.5; }
1724
+ #wb-palette { display: flex; flex-direction: column; gap: 6px; }
1725
+ .wb-skill {
1726
+ display: flex;
1727
+ align-items: center;
1728
+ gap: 8px;
1729
+ padding: 8px 12px;
1730
+ border: 1px solid var(--line);
1731
+ border-radius: 99px;
1732
+ background: var(--card);
1733
+ cursor: grab;
1734
+ }
1735
+ .wb-skill:hover { border-color: var(--accent-line); }
1736
+ .wb-skill .wb-ic { width: 12px; height: 12px; }
1737
+ .wb-skill .name { font-size: 11.5px; font-weight: 600; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1738
+ .wb-skill-right { margin-left: auto; display: flex; align-items: center; gap: 7px; flex: none; }
1739
+ .wb-skill .in-flow { width: 11px; height: 11px; fill: none; stroke: var(--green); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
1740
+ .wb-skill .dots { width: 10px; height: 10px; fill: var(--text3); }
1741
+
1742
+ .wb-yaml-head { display: flex; align-items: center; gap: 8px; margin: 20px 0 9px; }
1743
+ .wb-yaml-head .spacer { flex: 1; }
1744
+ .wb-yaml {
1745
+ margin: 0;
1746
+ padding: 12px 14px;
1747
+ background: var(--bg);
1748
+ border: 1px solid var(--line);
1749
+ border-radius: 11px;
1750
+ font-family: var(--mono);
1751
+ font-size: 10.5px;
1752
+ line-height: 1.7;
1753
+ color: var(--text2);
1754
+ overflow-x: auto;
1755
+ white-space: pre-wrap;
1756
+ }
1757
+ .wb-note { display: flex; align-items: flex-start; gap: 7px; margin-top: 10px; font-size: 11px; color: var(--text3); line-height: 1.5; }
1758
+ .wb-note svg { flex: none; margin-top: 1px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
1759
+
1360
1760
  /* narrow screens: sidebar shrinks, splits stack */
1361
1761
  @media (max-width: 900px) {
1362
- #sidebar { width: 240px; min-width: 240px; }
1762
+ #sidebar { width: 258px; min-width: 258px; }
1363
1763
  .split { grid-template-columns: 1fr; grid-template-rows: minmax(0, 45%) minmax(0, 1fr); }
1364
1764
  .split-list { border-right: none; border-bottom: 1px solid var(--line); }
1765
+ .wb-grid { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) minmax(0, 45%); }
1766
+ .wb-aside { border-left: none; border-top: 1px solid var(--line); }
1365
1767
  }