@worca/ui 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/app/styles.css CHANGED
@@ -535,14 +535,13 @@ h1, h2, h3, h4, h5, h6 {
535
535
  gap: 6px;
536
536
  }
537
537
 
538
- .run-branch {
539
- display: flex;
540
- align-items: center;
541
- gap: 6px;
542
- font-size: 13px;
543
- }
544
-
545
- .run-template {
538
+ /* Project / Branch / Pipeline-Template / Worktree rows inside
539
+ `.run-info-section` all share the same label-value typography so the
540
+ block reads as a uniform stack. Mirror .run-group below it. */
541
+ .run-project,
542
+ .run-branch,
543
+ .run-template,
544
+ .run-worktree {
546
545
  display: flex;
547
546
  align-items: center;
548
547
  gap: 6px;
@@ -1150,6 +1149,34 @@ sl-input [slot="prefix"] {
1150
1149
  color: var(--status-cancelled);
1151
1150
  }
1152
1151
 
1152
+ .status-halted {
1153
+ color: var(--status-paused);
1154
+ }
1155
+
1156
+ .status-setup-failed {
1157
+ color: var(--status-failed);
1158
+ }
1159
+
1160
+ .status-unrecoverable {
1161
+ color: var(--status-failed);
1162
+ }
1163
+
1164
+ .status-planning {
1165
+ color: var(--status-running);
1166
+ }
1167
+
1168
+ .status-integration-testing {
1169
+ color: var(--status-running);
1170
+ }
1171
+
1172
+ .status-integration-failed {
1173
+ color: var(--status-failed);
1174
+ }
1175
+
1176
+ .status-blocked {
1177
+ color: var(--status-paused);
1178
+ }
1179
+
1153
1180
  /* --- 18b. Control Buttons --- */
1154
1181
  .action-btn--amber {
1155
1182
  border-color: var(--status-paused);
@@ -1171,6 +1198,19 @@ sl-input [slot="prefix"] {
1171
1198
  color: #ffffff;
1172
1199
  }
1173
1200
 
1201
+ .action-btn--teal {
1202
+ /* "Re-run" / "iterate again" actions — distinct from primary blue
1203
+ (resume) and status palette colors so it reads as a separate
1204
+ intent: launch a fresh attempt from this one. */
1205
+ border-color: #0891b2;
1206
+ color: #0891b2;
1207
+ }
1208
+
1209
+ .action-btn--teal:hover {
1210
+ background: #0891b2;
1211
+ color: #ffffff;
1212
+ }
1213
+
1174
1214
  .action-btn--red {
1175
1215
  border-color: var(--status-failed);
1176
1216
  color: var(--status-failed);
@@ -1302,11 +1342,146 @@ sl-input [slot="prefix"] {
1302
1342
 
1303
1343
  /* Status-colored left border accent on run cards */
1304
1344
  .run-card.status-running { border-left: 3px solid var(--status-running); }
1345
+ .run-card.status-resuming { border-left: 3px solid var(--status-running); }
1305
1346
  .run-card.status-paused { border-left: 3px solid var(--status-paused); }
1347
+ .run-card.status-interrupted { border-left: 3px solid var(--status-interrupted); }
1306
1348
  .run-card.status-completed { border-left: 3px solid var(--status-completed); }
1307
1349
  .run-card.status-failed { border-left: 3px solid var(--status-failed); }
1350
+ .run-card.status-error { border-left: 3px solid var(--status-error); }
1308
1351
  .run-card.status-pending { border-left: 3px solid var(--status-pending); }
1352
+ .run-card.status-skipped { border-left: 3px solid var(--status-pending); }
1309
1353
  .run-card.status-cancelled { border-left: 3px solid var(--status-cancelled); }
1354
+ .run-card.status-halted { border-left: 3px solid var(--status-paused); }
1355
+ .run-card.status-setup-failed { border-left: 3px solid var(--status-failed); }
1356
+ .run-card.status-unrecoverable { border-left: 3px solid var(--status-failed); }
1357
+ .run-card.status-planning { border-left: 3px solid var(--status-running); }
1358
+ .run-card.status-integration-testing { border-left: 3px solid var(--status-running); }
1359
+ .run-card.status-integration-failed { border-left: 3px solid var(--status-failed); }
1360
+ .run-card.status-blocked { border-left: 3px solid var(--status-paused); }
1361
+
1362
+ /* ── Fleet card (shared component for Dashboard + Fleet list) ───────────
1363
+ The fleet card reuses the `.run-card` base class and its shared
1364
+ structural sub-elements (`.run-card-top`, `.run-card-status`,
1365
+ `.run-card-title`, `.run-card-meta`, `.run-card-meta-item`,
1366
+ `.run-card-actions`) — exactly like `.worktree-card` does. The
1367
+ `.fleet-card` / `.fleet-card-*` rules below are only the bits that are
1368
+ genuinely fleet-specific:
1369
+ - a layered "stack of cards" silhouette (::before / ::after layers)
1370
+ - the "Projects:" name-badge row
1371
+ - the failed-count pill + exception pills
1372
+ The box, hover, and status-accent styling all come from `.run-card`. */
1373
+
1374
+ /* Stack-of-cards illusion: two thin layers above-right behind the main card,
1375
+ each progressively offset and dimmed. Pure decoration — pointer-events
1376
+ off so they never steal clicks. */
1377
+ .fleet-card-stack {
1378
+ position: relative;
1379
+ isolation: isolate;
1380
+ }
1381
+ .fleet-card-stack::before,
1382
+ .fleet-card-stack::after {
1383
+ content: '';
1384
+ position: absolute;
1385
+ inset: 0;
1386
+ border: 1px solid var(--border-subtle);
1387
+ border-radius: var(--radius-lg);
1388
+ background: var(--surface);
1389
+ pointer-events: none;
1390
+ z-index: -1;
1391
+ }
1392
+ .fleet-card-stack::before {
1393
+ transform: translate(4px, -4px);
1394
+ opacity: 0.55;
1395
+ }
1396
+ .fleet-card-stack::after {
1397
+ transform: translate(8px, -8px);
1398
+ opacity: 0.3;
1399
+ }
1400
+
1401
+ /* The status-coloured left edge comes from `.run-card.status-*` (the
1402
+ fleet card carries the `run-card` base class). The one fleet-specific
1403
+ override: a user-initiated halt reads as informational grey, matching
1404
+ its `neutral` status-badge variant — per the badge-color-language
1405
+ guide §CSS Variables. Circuit-breaker / targets-not-ready halts keep
1406
+ the inherited orange. */
1407
+ .fleet-card.status-halted[data-halt-reason="user"] {
1408
+ border-left-color: var(--status-pending);
1409
+ }
1410
+
1411
+ /* Project name badges — the value of the "Projects:" meta label. Neutral
1412
+ (no status color), each clamped to ~20ch with an ellipsis; the JS also
1413
+ pre-truncates so the title attr carries the full name. Up to 3 render
1414
+ inline, the rest collapse into `.fleet-card-project-more`. */
1415
+ .fleet-card-project-badge {
1416
+ display: inline-block;
1417
+ max-width: 20ch;
1418
+ overflow: hidden;
1419
+ text-overflow: ellipsis;
1420
+ white-space: nowrap;
1421
+ vertical-align: bottom;
1422
+ padding: 1px 8px;
1423
+ font-size: 11px;
1424
+ color: var(--fg);
1425
+ background: var(--bg-tertiary);
1426
+ border: 1px solid var(--border-subtle);
1427
+ border-radius: 999px;
1428
+ flex-shrink: 0;
1429
+ }
1430
+ .fleet-card-project-more {
1431
+ font-size: 11px;
1432
+ color: var(--muted);
1433
+ flex-shrink: 0;
1434
+ }
1435
+ /* Failed-project count — rides the "Projects:" row after the name badges
1436
+ as a solid red badge (e.g. "1 failed"). Only rendered when at least one
1437
+ project failed; callers guard with `failedCount > 0`. */
1438
+ .fleet-card-failed-count {
1439
+ display: inline-block;
1440
+ flex-shrink: 0;
1441
+ padding: 1px 8px;
1442
+ font-size: 11px;
1443
+ font-weight: 500;
1444
+ color: #ffffff;
1445
+ background: var(--status-error);
1446
+ border-radius: 999px;
1447
+ }
1448
+
1449
+ /* Exception counter pills — surface non-zero failure / halted / paused
1450
+ buckets when they don't already match the fleet's overall status badge.
1451
+ Variants follow the badge-color-language guide: `danger` for failures,
1452
+ `warning` for halts/pauses. Replaces the prior right-edge accent stripe
1453
+ (which was too subtle to be actionable). */
1454
+ .fleet-card-exception-pill {
1455
+ flex-shrink: 0;
1456
+ }
1457
+
1458
+ .fleet-card-mono {
1459
+ font-family: var(--font-mono, ui-monospace, monospace);
1460
+ font-size: 11px;
1461
+ color: var(--fg);
1462
+ }
1463
+
1464
+ .fleet-card-children-label {
1465
+ align-self: center;
1466
+ flex-shrink: 0;
1467
+ font-size: 12px;
1468
+ /* Color/weight inherited from `.meta-label` so this row matches the
1469
+ Plan/Base/Started/Duration label vocabulary on the rows below. */
1470
+ }
1471
+ .fleet-card-children-empty {
1472
+ font-size: 12px;
1473
+ color: var(--muted);
1474
+ font-style: italic;
1475
+ }
1476
+
1477
+ /* "Projects:" label + name-badge list row. */
1478
+ .fleet-card-progress {
1479
+ display: flex;
1480
+ align-items: center;
1481
+ flex-wrap: wrap;
1482
+ gap: 6px;
1483
+ padding-left: 26px;
1484
+ }
1310
1485
 
1311
1486
  /* --- 21. Dashboard --- */
1312
1487
  .dashboard {
@@ -2340,7 +2515,39 @@ sl-details.live-output-panel::part(content) {
2340
2515
  .new-run-advanced {
2341
2516
  display: flex;
2342
2517
  flex-direction: column;
2343
- gap: 16px;
2518
+ gap: 24px;
2519
+ }
2520
+
2521
+ /* Advanced Options is dense — give each field a touch more breathing room
2522
+ between label / control / hint than the default 4px so multi-line
2523
+ sub-controls (head-template preview, plan-mode radio + warning) don't
2524
+ feel stacked. Scoped to .new-run-advanced so the rest of Settings
2525
+ keeps its tighter rhythm. */
2526
+ .new-run-advanced .settings-field {
2527
+ gap: 8px;
2528
+ }
2529
+ .new-run-advanced .settings-field-hint {
2530
+ margin-top: 4px;
2531
+ line-height: 1.5;
2532
+ }
2533
+
2534
+ /* Visual subgroup inside Advanced Options — small caps title + subtle
2535
+ underline divider. Keeps the section card's outer border doing the
2536
+ heavy lifting; the subgroup title is just a quiet "BRANCHES" /
2537
+ "PLANNING" / "CONCURRENCY" label for scanability. */
2538
+ .advanced-subgroup {
2539
+ display: flex;
2540
+ flex-direction: column;
2541
+ gap: 14px;
2542
+ }
2543
+ .advanced-subgroup-title {
2544
+ font-size: 11px;
2545
+ font-weight: 600;
2546
+ color: var(--muted);
2547
+ text-transform: uppercase;
2548
+ letter-spacing: 0.06em;
2549
+ padding-bottom: 6px;
2550
+ border-bottom: 1px dashed var(--border-subtle);
2344
2551
  }
2345
2552
 
2346
2553
  .new-run-grid {
@@ -2484,39 +2691,106 @@ sl-option.template-grouped:focus::part(suffix) {
2484
2691
  background: var(--bg-tertiary);
2485
2692
  }
2486
2693
 
2487
- /* Sidebar new run button */
2694
+ /* Sidebar new run button (split button pattern: primary + chevron).
2695
+ The split button is the W-040 UX choice — primary "New Pipeline"
2696
+ handles the common case; the chevron drops down to a menu of
2697
+ multi-project alternatives (Fleet, plus Workspace when W-047 ships). */
2488
2698
  .sidebar-new-run {
2489
2699
  padding: 8px 8px 4px;
2490
2700
  }
2491
2701
 
2492
- .sidebar-new-run-btn {
2702
+ .sidebar-new-run-split {
2493
2703
  display: flex;
2494
- align-items: center;
2495
- justify-content: center;
2496
- gap: 8px;
2704
+ align-items: stretch;
2497
2705
  width: 100%;
2498
- padding: 8px 12px;
2706
+ min-height: 36px;
2499
2707
  border: 2px dashed var(--accent);
2500
2708
  border-radius: var(--radius);
2709
+ overflow: hidden;
2710
+ background: transparent;
2711
+ transition: background var(--transition-fast), border-color var(--transition-fast);
2712
+ }
2713
+
2714
+ .sidebar-new-run-btn-primary {
2715
+ flex: 1 1 auto;
2716
+ display: flex;
2717
+ align-items: center;
2718
+ justify-content: center;
2719
+ gap: 8px;
2720
+ min-width: 0;
2721
+ padding: 6px 12px;
2722
+ border: 0;
2723
+ border-right: 2px dashed var(--accent);
2501
2724
  background: transparent;
2502
2725
  color: var(--accent);
2503
2726
  font-size: 13px;
2504
2727
  font-weight: 600;
2505
2728
  font-family: inherit;
2506
2729
  cursor: pointer;
2730
+ transition: background var(--transition-fast), color var(--transition-fast),
2731
+ border-color var(--transition-fast);
2732
+ }
2733
+
2734
+ .sidebar-new-run-btn-primary:hover:not(:disabled) {
2735
+ background: var(--accent);
2736
+ color: #ffffff;
2737
+ }
2738
+
2739
+ /* Disabled state: muted (not ghosted) so it reads as "waiting on something"
2740
+ rather than a broken control. Pairs with the title tooltip explaining
2741
+ why it's inactive (e.g., "Select a project first…"). */
2742
+ .sidebar-new-run-btn-primary:disabled {
2743
+ cursor: not-allowed;
2744
+ color: var(--muted);
2745
+ border-right-color: var(--muted);
2746
+ }
2747
+
2748
+ /* sl-dropdown defaults to inline-block; force it to fill the cross-axis
2749
+ so the slotted chevron button can stretch to the full split height. */
2750
+ .sidebar-new-run-chevron-dropdown {
2751
+ display: flex;
2752
+ flex: 0 0 auto;
2753
+ align-self: stretch;
2754
+ }
2755
+
2756
+ .sidebar-new-run-btn-chevron {
2757
+ display: flex;
2758
+ align-items: center;
2759
+ justify-content: center;
2760
+ align-self: stretch;
2761
+ height: 100%;
2762
+ min-height: 32px;
2763
+ padding: 0 12px;
2764
+ border: 0;
2765
+ background: transparent;
2766
+ color: var(--accent);
2767
+ cursor: pointer;
2507
2768
  transition: background var(--transition-fast), color var(--transition-fast);
2508
2769
  }
2509
2770
 
2510
- .sidebar-new-run-btn:hover {
2771
+ .sidebar-new-run-btn-chevron:hover:not(:disabled) {
2511
2772
  background: var(--accent);
2512
2773
  color: #ffffff;
2513
2774
  }
2514
2775
 
2515
- .sidebar.collapsed .sidebar-new-run-btn span {
2776
+ .sidebar-new-run-btn-chevron:disabled {
2777
+ cursor: not-allowed;
2778
+ color: var(--muted);
2779
+ }
2780
+
2781
+ /* Menu items: icon + label, slight indent under their icon */
2782
+ .sidebar-new-run-chevron-dropdown sl-menu-item::part(base) {
2783
+ display: flex;
2784
+ align-items: center;
2785
+ gap: 8px;
2786
+ font-size: 13px;
2787
+ }
2788
+
2789
+ .sidebar.collapsed .sidebar-new-run-btn-primary span {
2516
2790
  display: none;
2517
2791
  }
2518
2792
 
2519
- .sidebar.collapsed .sidebar-new-run-btn {
2793
+ .sidebar.collapsed .sidebar-new-run-btn-primary {
2520
2794
  padding: 8px;
2521
2795
  }
2522
2796
 
@@ -2906,6 +3180,16 @@ sl-details.run-beads-panel::part(content) {
2906
3180
  border: 1px solid var(--border-subtle);
2907
3181
  }
2908
3182
 
3183
+ /* Default badge layout: when a badge contains an icon + text (e.g. the
3184
+ pipeline-page header status badge "<icon> Completed"), the children
3185
+ sit flush against each other. Give them a small gap. Single-child
3186
+ badges are unaffected because flex+gap only manifests between siblings. */
3187
+ sl-badge::part(base) {
3188
+ display: inline-flex;
3189
+ align-items: center;
3190
+ gap: 4px;
3191
+ }
3192
+
2909
3193
  .run-bead-row sl-badge::part(base) {
2910
3194
  font-size: 0.68rem;
2911
3195
  padding: 0 5px;
@@ -3960,6 +4244,9 @@ sl-details.learnings-panel::part(content) {
3960
4244
  .filter-chip-failed.active { background: var(--status-failed); border-color: var(--status-failed); }
3961
4245
  .filter-chip-paused.active { background: var(--status-paused); border-color: var(--status-paused); }
3962
4246
  .filter-chip-error.active { background: var(--status-failed); border-color: var(--status-failed); }
4247
+ .filter-chip-halted.active { background: var(--status-paused); border-color: var(--status-paused); }
4248
+ .filter-chip-integration-failed.active,
4249
+ .filter-chip-integration_failed.active { background: var(--status-failed); border-color: var(--status-failed); }
3963
4250
  .filter-chip .chip-count {
3964
4251
  font-size: 0.68rem;
3965
4252
  opacity: 0.7;
@@ -3970,6 +4257,7 @@ sl-details.learnings-panel::part(content) {
3970
4257
  display: flex;
3971
4258
  align-items: center;
3972
4259
  justify-content: flex-end;
4260
+ flex-wrap: wrap;
3973
4261
  gap: 8px;
3974
4262
  padding-left: 26px;
3975
4263
  }
@@ -4036,11 +4324,8 @@ sl-details.learnings-panel::part(content) {
4036
4324
  .project-status-paused { background: var(--status-paused, #eab308); }
4037
4325
 
4038
4326
  /* --- Dashboard Project Cards --- */
4039
- .project-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; margin-bottom: 24px; }
4040
- .project-card { background: var(--surface); border-radius: var(--radius); padding: 16px; cursor: pointer; transition: var(--transition-fast); border: 1px solid var(--border); }
4041
- .project-card:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); }
4042
- .project-card-name { font-weight: 600; margin-bottom: 4px; }
4043
- .project-card-stats { font-size: 0.85rem; color: var(--text-secondary); }
4327
+ /* .project-cards / .project-card-* removed see app/views/dashboard.js
4328
+ for the rationale (sidebar dropdown replaces them). */
4044
4329
 
4045
4330
  /* --- Settings Projects List --- */
4046
4331
  .projects-list-item { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--border); }
@@ -4077,6 +4362,10 @@ sl-details.learnings-panel::part(content) {
4077
4362
  .pipeline-failed { border-left-color: var(--status-failed); }
4078
4363
  .pipeline-paused { border-left-color: var(--status-paused); }
4079
4364
  .pipeline-cancelled { border-left-color: var(--status-cancelled); }
4365
+ .pipeline-planning { border-left-color: var(--status-running); }
4366
+ .pipeline-integration-testing { border-left-color: var(--status-running); }
4367
+ .pipeline-integration-failed { border-left-color: var(--status-failed); }
4368
+ .pipeline-blocked { border-left-color: var(--status-paused); }
4080
4369
  .pipeline-unknown { border-left-color: var(--muted); }
4081
4370
 
4082
4371
  .pipeline-card-header {
@@ -4639,6 +4928,23 @@ sl-tooltip.bead-tooltip::part(body) {
4639
4928
  flex: 1;
4640
4929
  min-width: 240px;
4641
4930
  }
4931
+
4932
+ /* Shared text-filter row — the line under the filter chips on the
4933
+ History and Fleets list pages. Mirrors `.worktrees-toolbar` so the
4934
+ three list pages present an identical filter affordance. The
4935
+ worktrees page keeps its own toolbar (it carries the extra
4936
+ "Cleanup all completed" button alongside the text input). */
4937
+ .list-filter-row {
4938
+ display: flex;
4939
+ align-items: center;
4940
+ gap: 12px;
4941
+ flex-wrap: wrap;
4942
+ margin-bottom: 12px;
4943
+ }
4944
+ .list-filter-row .list-text-filter {
4945
+ flex: 1;
4946
+ min-width: 240px;
4947
+ }
4642
4948
  .worktree-card-path {
4643
4949
  align-items: baseline;
4644
4950
  }
@@ -4854,3 +5160,989 @@ sl-tooltip.bead-tooltip::part(body) {
4854
5160
  line-height: 1.2;
4855
5161
  flex: 0 0 auto;
4856
5162
  }
5163
+
5164
+ /* ─── Fleet group (W-040 §13.2) ────────────────────────────────────────────── */
5165
+ .fleet-group {
5166
+ margin-bottom: 8px;
5167
+ border: 1px solid var(--border-subtle);
5168
+ border-radius: 8px;
5169
+ overflow: hidden;
5170
+ }
5171
+
5172
+ .fleet-header {
5173
+ display: flex;
5174
+ align-items: center;
5175
+ gap: 10px;
5176
+ padding: 10px 14px;
5177
+ background: var(--bg-secondary);
5178
+ cursor: pointer;
5179
+ user-select: none;
5180
+ }
5181
+
5182
+ .fleet-header:hover {
5183
+ background: var(--bg-tertiary);
5184
+ }
5185
+
5186
+ .fleet-toggle {
5187
+ flex-shrink: 0;
5188
+ color: var(--fg-muted);
5189
+ font-size: 14px;
5190
+ }
5191
+
5192
+ .fleet-title {
5193
+ flex: 0 1 auto;
5194
+ font-size: 13px;
5195
+ font-weight: 600;
5196
+ color: var(--fg);
5197
+ overflow: hidden;
5198
+ text-overflow: ellipsis;
5199
+ white-space: nowrap;
5200
+ }
5201
+
5202
+ .fleet-status-badge {
5203
+ flex-shrink: 0;
5204
+ }
5205
+
5206
+ .fleet-progress {
5207
+ flex-shrink: 0;
5208
+ font-size: 12px;
5209
+ color: var(--fg-muted);
5210
+ }
5211
+
5212
+ .fleet-progress-bar {
5213
+ flex: 1 1 80px;
5214
+ min-width: 60px;
5215
+ max-width: 160px;
5216
+ }
5217
+
5218
+ .fleet-cost {
5219
+ flex-shrink: 0;
5220
+ font-size: 12px;
5221
+ color: var(--fg-muted);
5222
+ }
5223
+
5224
+ .fleet-detail-btn {
5225
+ flex-shrink: 0;
5226
+ margin-left: auto;
5227
+ }
5228
+
5229
+ .fleet-children {
5230
+ padding: 8px;
5231
+ display: flex;
5232
+ flex-direction: column;
5233
+ gap: 8px;
5234
+ background: var(--bg-primary);
5235
+ }
5236
+
5237
+ /* ── Fleet launcher (page) ─────────────────────────────────────────────── */
5238
+
5239
+ .fleet-launcher-page,
5240
+ .fleet-detail-page {
5241
+ max-width: 760px;
5242
+ }
5243
+
5244
+ .fleet-launcher-projects-controls {
5245
+ display: flex;
5246
+ gap: 8px;
5247
+ align-items: center;
5248
+ margin-bottom: 4px;
5249
+ }
5250
+
5251
+ .fleet-launcher-projects-controls .input-project-filter {
5252
+ flex: 1 1 auto;
5253
+ }
5254
+
5255
+ /* Head-template preview rows — render below the input as a small inset
5256
+ panel so the per-project resolved branches feel attached to (not just
5257
+ stacked under) the template field. */
5258
+ .head-template-input {
5259
+ display: flex;
5260
+ flex-direction: column;
5261
+ gap: 8px;
5262
+ }
5263
+ .head-template-preview {
5264
+ display: flex;
5265
+ flex-direction: column;
5266
+ gap: 4px;
5267
+ padding: 8px 12px;
5268
+ background: var(--bg-primary);
5269
+ border: 1px solid var(--border-subtle);
5270
+ border-radius: var(--radius);
5271
+ font-size: 12px;
5272
+ }
5273
+ .head-template-preview-row {
5274
+ display: flex;
5275
+ align-items: center;
5276
+ gap: 8px;
5277
+ font-family: var(--font-mono, ui-monospace, monospace);
5278
+ }
5279
+ .head-template-preview-row .preview-arrow {
5280
+ color: var(--muted);
5281
+ }
5282
+ .head-template-preview-row .preview-branch {
5283
+ color: var(--text);
5284
+ }
5285
+ .head-template-preview-row.collision .preview-branch {
5286
+ color: var(--status-error);
5287
+ }
5288
+ .head-template-preview-row .collision-flag {
5289
+ margin-left: auto;
5290
+ font-size: 11px;
5291
+ color: var(--status-error);
5292
+ text-transform: uppercase;
5293
+ letter-spacing: 0.04em;
5294
+ }
5295
+
5296
+ /* Plan-mode radio container: stack the radios with breathing room and
5297
+ keep the divergence-warning alert visually attached to the chosen
5298
+ option without crowding it. */
5299
+ .plan-mode-radio {
5300
+ display: flex;
5301
+ flex-direction: column;
5302
+ gap: 10px;
5303
+ }
5304
+ .plan-mode-radio sl-radio-group::part(form-control) {
5305
+ display: flex;
5306
+ flex-direction: column;
5307
+ gap: 4px;
5308
+ }
5309
+
5310
+ /* Base-branch validation states */
5311
+ .base-branch-validating {
5312
+ display: flex;
5313
+ align-items: center;
5314
+ gap: 8px;
5315
+ font-size: 12px;
5316
+ color: var(--muted);
5317
+ padding: 4px 0;
5318
+ }
5319
+ .base-branch-error {
5320
+ font-size: 12px;
5321
+ color: var(--status-error);
5322
+ padding: 8px 12px;
5323
+ background: var(--bg-primary);
5324
+ border: 1px solid var(--status-error);
5325
+ border-radius: var(--radius);
5326
+ }
5327
+ .base-branch-missing-list {
5328
+ margin: 4px 0 0;
5329
+ padding-left: 20px;
5330
+ }
5331
+
5332
+ /* ── Fleet detail (page) ────────────────────────────────────────────────── */
5333
+
5334
+ /* The page top mirrors `runDetailView`'s overview: a clickable projects
5335
+ strip (analogue of the stage-timeline pills) sits above a single
5336
+ `.run-info-section` panel that holds the status badge + id chip + flat
5337
+ meta rows. No hero card — the per-project run-cards below carry the
5338
+ "card" affordance now. */
5339
+ .fleet-detail-overview {
5340
+ display: flex;
5341
+ flex-direction: column;
5342
+ gap: 8px;
5343
+ }
5344
+
5345
+ .fleet-projects-strip {
5346
+ display: flex;
5347
+ gap: 6px;
5348
+ width: 100%;
5349
+ }
5350
+ .fleet-projects-strip-segment {
5351
+ flex: 1 1 0;
5352
+ min-width: 0;
5353
+ display: inline-flex;
5354
+ align-items: center;
5355
+ justify-content: center;
5356
+ gap: 6px;
5357
+ padding: 8px 10px;
5358
+ border: 1px solid var(--border-subtle);
5359
+ border-left-width: 3px;
5360
+ border-radius: var(--radius-md);
5361
+ background: var(--bg-secondary);
5362
+ color: var(--fg);
5363
+ font-size: 12px;
5364
+ font-weight: 500;
5365
+ cursor: pointer;
5366
+ transition: background 120ms ease, transform 120ms ease;
5367
+ overflow: hidden;
5368
+ }
5369
+ .fleet-projects-strip-segment:hover {
5370
+ background: var(--bg-hover);
5371
+ }
5372
+ .fleet-projects-strip-segment:disabled {
5373
+ cursor: default;
5374
+ opacity: 0.75;
5375
+ }
5376
+ .fleet-projects-strip-segment.status-running { border-left-color: var(--status-running); }
5377
+ .fleet-projects-strip-segment.status-resuming { border-left-color: var(--status-running); }
5378
+ .fleet-projects-strip-segment.status-paused { border-left-color: var(--status-paused); }
5379
+ .fleet-projects-strip-segment.status-interrupted { border-left-color: var(--status-interrupted); }
5380
+ .fleet-projects-strip-segment.status-completed { border-left-color: var(--status-completed); }
5381
+ .fleet-projects-strip-segment.status-failed,
5382
+ .fleet-projects-strip-segment.status-setup-failed,
5383
+ .fleet-projects-strip-segment.status-unrecoverable { border-left-color: var(--status-failed); }
5384
+ .fleet-projects-strip-segment.status-error { border-left-color: var(--status-error); }
5385
+ .fleet-projects-strip-segment.status-halted { border-left-color: var(--status-paused); }
5386
+ .fleet-projects-strip-segment.status-pending,
5387
+ .fleet-projects-strip-segment.status-skipped,
5388
+ .fleet-projects-strip-segment.status-cancelled { border-left-color: var(--status-pending); }
5389
+ .fleet-projects-strip-icon {
5390
+ display: inline-flex;
5391
+ align-items: center;
5392
+ flex-shrink: 0;
5393
+ }
5394
+ .fleet-projects-strip-label {
5395
+ overflow: hidden;
5396
+ text-overflow: ellipsis;
5397
+ white-space: nowrap;
5398
+ min-width: 0;
5399
+ }
5400
+
5401
+ .fleet-info-section {
5402
+ /* Inherits .run-info-section padding/background — adds a couple of fleet
5403
+ -specific layout rules for the status row. */
5404
+ }
5405
+ .fleet-overview-status-row {
5406
+ display: flex;
5407
+ align-items: center;
5408
+ gap: 10px;
5409
+ flex-wrap: wrap;
5410
+ /* Match `.fleet-meta-line` so the "Fleet ID:" label renders in the
5411
+ same vocabulary as the Projects / Base / Started / Cost labels. */
5412
+ font-size: 13px;
5413
+ color: var(--fg);
5414
+ }
5415
+ .fleet-meta-line {
5416
+ display: flex;
5417
+ flex-wrap: wrap;
5418
+ gap: 4px 20px;
5419
+ font-size: 13px;
5420
+ color: var(--fg);
5421
+ }
5422
+ .fleet-meta-item {
5423
+ display: inline-flex;
5424
+ align-items: center;
5425
+ gap: 6px;
5426
+ }
5427
+ /* Projects row in the hero — label + name badges, same vocabulary as the
5428
+ fleet card's "Projects:" row. Tighter gap than the default meta line so
5429
+ the badges read as a contiguous list. */
5430
+ .fleet-meta-line-projects {
5431
+ align-items: center;
5432
+ gap: 6px;
5433
+ }
5434
+ .fleet-cost-strip {
5435
+ /* Reuses .pipeline-cost-strip — no overrides needed but keep the class
5436
+ so future tweaks can target fleet-specific copy. */
5437
+ }
5438
+
5439
+ /* Anchor wrapper around each project run-card so the projects strip can
5440
+ scroll to a specific card on click. */
5441
+ .fleet-project-anchor {
5442
+ scroll-margin-top: 80px;
5443
+ }
5444
+
5445
+ .fleet-detail-status-row {
5446
+ display: flex;
5447
+ align-items: center;
5448
+ gap: 12px;
5449
+ padding: 12px 16px;
5450
+ border: 1px solid var(--border-subtle);
5451
+ border-radius: var(--radius-lg);
5452
+ background: var(--bg-secondary);
5453
+ }
5454
+
5455
+ .fleet-detail-status-row .fleet-status-badge::part(base) {
5456
+ font-size: 12px;
5457
+ padding: 4px 10px;
5458
+ }
5459
+
5460
+ .fleet-id-chip {
5461
+ font-family: var(--sl-font-mono);
5462
+ font-size: 12px;
5463
+ color: var(--muted);
5464
+ padding: 2px 8px;
5465
+ background: var(--bg-tertiary);
5466
+ border-radius: 4px;
5467
+ border: 1px solid var(--border-subtle);
5468
+ }
5469
+
5470
+ .fleet-detail-body {
5471
+ margin-top: 4px;
5472
+ }
5473
+
5474
+ .fleet-manifest-grid {
5475
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
5476
+ }
5477
+
5478
+ .fleet-meta-mono {
5479
+ font-family: var(--sl-font-mono);
5480
+ font-size: 12.5px;
5481
+ color: var(--fg);
5482
+ background: var(--bg-tertiary);
5483
+ padding: 2px 6px;
5484
+ border-radius: 4px;
5485
+ display: inline-block;
5486
+ word-break: break-all;
5487
+ }
5488
+
5489
+ .fleet-meta-value {
5490
+ font-size: 13px;
5491
+ color: var(--fg);
5492
+ font-weight: 500;
5493
+ }
5494
+
5495
+ .fleet-wr-title {
5496
+ font-size: 16px;
5497
+ font-weight: 600;
5498
+ color: var(--fg);
5499
+ }
5500
+
5501
+ .fleet-wr-description {
5502
+ margin: 0;
5503
+ font-size: 13px;
5504
+ line-height: 1.55;
5505
+ color: var(--fg);
5506
+ white-space: pre-wrap;
5507
+ }
5508
+
5509
+ .fleet-guide-files {
5510
+ display: flex;
5511
+ flex-wrap: wrap;
5512
+ gap: 6px;
5513
+ margin-bottom: 4px;
5514
+ }
5515
+
5516
+ .fleet-guide-tag::part(base) {
5517
+ font-family: var(--sl-font-mono);
5518
+ }
5519
+
5520
+ .fleet-guide-actions {
5521
+ border-top: none;
5522
+ padding-top: 4px;
5523
+ }
5524
+
5525
+ .fleet-children-header {
5526
+ display: flex;
5527
+ align-items: baseline;
5528
+ justify-content: space-between;
5529
+ gap: 12px;
5530
+ }
5531
+
5532
+ .fleet-children-list {
5533
+ margin-top: 4px;
5534
+ }
5535
+
5536
+ .fleet-child-card {
5537
+ border-left-width: 3px;
5538
+ }
5539
+
5540
+ .fleet-child-card .run-card-meta code.fleet-meta-mono {
5541
+ background: transparent;
5542
+ padding: 0;
5543
+ font-size: 12px;
5544
+ }
5545
+
5546
+ .fleet-aggregate-cost-section .fleet-total-cost {
5547
+ font-size: 22px;
5548
+ font-weight: 600;
5549
+ color: var(--fg);
5550
+ font-variant-numeric: tabular-nums;
5551
+ }
5552
+
5553
+ .fleet-circuit-breaker-alert,
5554
+ .fleet-user-halt-alert {
5555
+ display: block;
5556
+ }
5557
+
5558
+ .fleet-circuit-breaker-alert .cb-trip-reason,
5559
+ .fleet-circuit-breaker-alert .cb-unstarted-count {
5560
+ display: block;
5561
+ margin-top: 4px;
5562
+ font-size: 12.5px;
5563
+ color: var(--fg);
5564
+ opacity: 0.85;
5565
+ }
5566
+
5567
+ .fleet-actions {
5568
+ display: flex;
5569
+ flex-wrap: wrap;
5570
+ gap: 10px;
5571
+ align-items: center;
5572
+ }
5573
+
5574
+ /* Run-detail "Fleet:" / "Workspace:" group line above the Branch row.
5575
+ Mirrors .run-branch exactly: same font-size, gap, and value weight.
5576
+ The only visual difference is the accent-colored anchor + underline-
5577
+ on-hover affordance signalling it's clickable. */
5578
+ .run-group {
5579
+ display: flex;
5580
+ align-items: center;
5581
+ gap: 6px;
5582
+ font-size: 13px;
5583
+ }
5584
+
5585
+ .run-group-link {
5586
+ /* Inherits font-family + font-size from .run-group → matches the plain
5587
+ <span class="meta-value"> on the Branch line, just colored and
5588
+ underlined-on-hover to read as a link. */
5589
+ color: var(--accent);
5590
+ font-weight: 600;
5591
+ text-decoration: none;
5592
+ word-break: break-all;
5593
+ }
5594
+
5595
+ .run-group-link:hover {
5596
+ text-decoration: underline;
5597
+ }
5598
+
5599
+ /* Run-card "Fleet:" / "Workspace:" meta-item — sized by parent
5600
+ .run-card-meta (12px). Same coloring as .run-group-link but no
5601
+ monospace. */
5602
+ .run-card-group-link {
5603
+ color: var(--accent);
5604
+ font-weight: 600;
5605
+ text-decoration: none;
5606
+ word-break: break-all;
5607
+ }
5608
+
5609
+ .run-card-group-link:hover {
5610
+ text-decoration: underline;
5611
+ }
5612
+
5613
+ /* Sidebar fleet-header clickable feedback */
5614
+ .fleet-header-clickable {
5615
+ transition: background-color var(--transition-fast);
5616
+ }
5617
+
5618
+ .fleet-header-clickable:hover {
5619
+ background-color: color-mix(in srgb, var(--accent) 6%, transparent);
5620
+ }
5621
+
5622
+ /* Fleet list view (route: /#/fleet-runs) — one `fleet-card` per fleet.
5623
+ No wrapping border / shared background; each card carries its own
5624
+ chrome plus the layered stack-of-cards shadow. Gap matches the
5625
+ gap between pipeline cards in run-list for visual consistency. */
5626
+ .fleet-list {
5627
+ display: flex;
5628
+ flex-direction: column;
5629
+ gap: 16px;
5630
+ }
5631
+
5632
+ .fleet-list-row {
5633
+ display: flex;
5634
+ align-items: center;
5635
+ gap: 12px;
5636
+ padding: 12px 16px;
5637
+ border-bottom: 1px solid var(--border-subtle);
5638
+ cursor: pointer;
5639
+ transition: background-color var(--transition-fast);
5640
+ }
5641
+
5642
+ .fleet-list-row:last-child {
5643
+ border-bottom: none;
5644
+ }
5645
+
5646
+ .fleet-list-row:hover {
5647
+ background-color: color-mix(in srgb, var(--accent) 6%, transparent);
5648
+ }
5649
+
5650
+ .fleet-list-row-title {
5651
+ font-size: 14px;
5652
+ font-weight: 600;
5653
+ color: var(--fg);
5654
+ flex: 1 1 auto;
5655
+ min-width: 0;
5656
+ overflow: hidden;
5657
+ text-overflow: ellipsis;
5658
+ white-space: nowrap;
5659
+ }
5660
+
5661
+ .fleet-list-row-badge {
5662
+ flex-shrink: 0;
5663
+ }
5664
+
5665
+ .fleet-list-row-meta {
5666
+ font-size: 12px;
5667
+ color: var(--muted);
5668
+ flex-shrink: 0;
5669
+ }
5670
+
5671
+ .fleet-list-row-id {
5672
+ font-family: var(--sl-font-mono);
5673
+ font-size: 11.5px;
5674
+ color: var(--muted);
5675
+ background: var(--bg-tertiary);
5676
+ padding: 2px 8px;
5677
+ border-radius: 4px;
5678
+ flex-shrink: 0;
5679
+ }
5680
+
5681
+ .fleet-list-loading,
5682
+ .fleet-list-empty {
5683
+ padding: 24px;
5684
+ text-align: center;
5685
+ color: var(--muted);
5686
+ display: flex;
5687
+ flex-direction: column;
5688
+ align-items: center;
5689
+ gap: 12px;
5690
+ }
5691
+
5692
+ .fleet-detail-empty {
5693
+ padding: 64px 24px;
5694
+ text-align: center;
5695
+ color: var(--muted);
5696
+ display: flex;
5697
+ flex-direction: column;
5698
+ align-items: center;
5699
+ gap: 12px;
5700
+ max-width: 540px;
5701
+ margin: 0 auto;
5702
+ }
5703
+
5704
+ .fleet-detail-empty sl-icon {
5705
+ font-size: 48px;
5706
+ color: var(--muted);
5707
+ opacity: 0.6;
5708
+ }
5709
+
5710
+ .fleet-detail-empty h2 {
5711
+ margin: 8px 0 0 0;
5712
+ font-size: 18px;
5713
+ color: var(--fg);
5714
+ }
5715
+
5716
+ .fleet-detail-empty p {
5717
+ margin: 0;
5718
+ line-height: 1.5;
5719
+ }
5720
+
5721
+ .fleet-detail-empty code {
5722
+ font-size: 12px;
5723
+ background: var(--bg-2, var(--border));
5724
+ padding: 1px 6px;
5725
+ border-radius: 4px;
5726
+ }
5727
+
5728
+ .fleet-detail-empty-hint {
5729
+ font-size: 13px;
5730
+ opacity: 0.85;
5731
+ }
5732
+
5733
+ .fleet-detail-empty-hint a {
5734
+ color: var(--accent, var(--fg));
5735
+ }
5736
+
5737
+ /* --- Workspace: tier styling --- */
5738
+
5739
+ .workspace-card-tiers {
5740
+ display: flex;
5741
+ flex-direction: column;
5742
+ gap: 6px;
5743
+ margin-top: 8px;
5744
+ }
5745
+
5746
+ .workspace-tier-row {
5747
+ display: flex;
5748
+ align-items: center;
5749
+ gap: 8px;
5750
+ }
5751
+
5752
+ .tier-label {
5753
+ font-size: 11px;
5754
+ font-weight: 600;
5755
+ color: var(--muted);
5756
+ text-transform: uppercase;
5757
+ letter-spacing: 0.05em;
5758
+ min-width: 60px;
5759
+ flex-shrink: 0;
5760
+ }
5761
+
5762
+ .tier-status {
5763
+ display: inline-flex;
5764
+ align-items: center;
5765
+ flex-shrink: 0;
5766
+ }
5767
+
5768
+ .tier-children {
5769
+ display: flex;
5770
+ flex-wrap: wrap;
5771
+ gap: 4px;
5772
+ }
5773
+
5774
+ .tier-child {
5775
+ font-size: 12px;
5776
+ padding: 2px 8px;
5777
+ border-radius: 4px;
5778
+ background: var(--bg-tertiary);
5779
+ border: 1px solid var(--border);
5780
+ }
5781
+
5782
+ /* --- Workspace: DAG graph --- */
5783
+
5784
+ .dag-preview {
5785
+ overflow-x: auto;
5786
+ border: 1px solid var(--border);
5787
+ border-radius: var(--radius);
5788
+ background: var(--bg-secondary);
5789
+ padding: 16px;
5790
+ }
5791
+
5792
+ .dag-preview svg {
5793
+ display: block;
5794
+ }
5795
+
5796
+ .workspace-dag-panel {
5797
+ display: flex;
5798
+ flex-direction: column;
5799
+ gap: 8px;
5800
+ }
5801
+
5802
+
5803
+
5804
+ .workspace-dag-svg {
5805
+ overflow-x: auto;
5806
+ }
5807
+
5808
+ /* --- Workspace run card --- */
5809
+
5810
+ /* --- Plan stage artifact strip (run-detail) --- */
5811
+
5812
+ .plan-artifact-strip {
5813
+ display: flex;
5814
+ align-items: center;
5815
+ flex-wrap: wrap;
5816
+ gap: 8px;
5817
+ margin: 10px 0 4px;
5818
+ }
5819
+ .plan-artifact-strip .plan-file-chip {
5820
+ font-family: var(--font-mono);
5821
+ font-size: 12px;
5822
+ color: var(--fg-muted);
5823
+ background: var(--bg-secondary);
5824
+ padding: 2px 6px;
5825
+ border-radius: 4px;
5826
+ max-width: 360px;
5827
+ overflow: hidden;
5828
+ text-overflow: ellipsis;
5829
+ white-space: nowrap;
5830
+ }
5831
+ .plan-loading,
5832
+ .plan-error {
5833
+ display: flex;
5834
+ align-items: center;
5835
+ gap: 8px;
5836
+ padding: 20px;
5837
+ color: var(--fg-muted);
5838
+ }
5839
+
5840
+ /* --- sl-dialog: wider markdown-body dialogs (plan, guide) --- */
5841
+
5842
+ sl-dialog.markdown-dialog::part(panel) {
5843
+ /* Default sl-dialog is ~31rem wide — too narrow for prose with code
5844
+ blocks. Cap at 90vw so it stays comfortable on small viewports. */
5845
+ width: min(960px, 90vw);
5846
+ max-width: min(960px, 90vw);
5847
+ }
5848
+ sl-dialog.markdown-dialog::part(body) {
5849
+ /* Give the body breathing room and let it scroll vertically instead
5850
+ of the whole dialog growing without bound. */
5851
+ max-height: 70vh;
5852
+ overflow: auto;
5853
+ }
5854
+
5855
+ /* --- Markdown body styling (used by guide-content + workspace-plan-content) --- */
5856
+
5857
+ .markdown-body {
5858
+ font-family: var(--sl-font-sans, system-ui, sans-serif);
5859
+ font-size: 14px;
5860
+ line-height: 1.55;
5861
+ color: var(--fg);
5862
+ }
5863
+ .markdown-body h1,
5864
+ .markdown-body h2,
5865
+ .markdown-body h3,
5866
+ .markdown-body h4 {
5867
+ margin: 1.2em 0 0.5em;
5868
+ line-height: 1.25;
5869
+ font-weight: 600;
5870
+ }
5871
+ .markdown-body h1 { font-size: 1.5em; }
5872
+ .markdown-body h2 { font-size: 1.25em; border-bottom: 1px solid var(--border-subtle); padding-bottom: 4px; }
5873
+ .markdown-body h3 { font-size: 1.1em; }
5874
+ .markdown-body p { margin: 0.6em 0; }
5875
+ .markdown-body ul,
5876
+ .markdown-body ol { margin: 0.6em 0; padding-left: 1.5em; }
5877
+ .markdown-body li { margin: 0.25em 0; }
5878
+ .markdown-body code {
5879
+ font-family: var(--font-mono);
5880
+ font-size: 0.9em;
5881
+ background: var(--bg-secondary);
5882
+ padding: 1px 5px;
5883
+ border-radius: 3px;
5884
+ }
5885
+ .markdown-body pre {
5886
+ background: var(--bg-secondary);
5887
+ border: 1px solid var(--border-subtle);
5888
+ border-radius: 6px;
5889
+ padding: 10px 12px;
5890
+ overflow-x: auto;
5891
+ font-size: 12.5px;
5892
+ }
5893
+ .markdown-body pre code {
5894
+ background: transparent;
5895
+ padding: 0;
5896
+ border-radius: 0;
5897
+ }
5898
+ .markdown-body blockquote {
5899
+ border-left: 3px solid var(--border);
5900
+ padding: 4px 12px;
5901
+ margin: 0.6em 0;
5902
+ color: var(--fg-muted);
5903
+ }
5904
+ .markdown-body a { color: var(--accent); }
5905
+ .markdown-body table {
5906
+ border-collapse: collapse;
5907
+ margin: 0.8em 0;
5908
+ }
5909
+ .markdown-body th,
5910
+ .markdown-body td {
5911
+ border: 1px solid var(--border-subtle);
5912
+ padding: 4px 8px;
5913
+ text-align: left;
5914
+ }
5915
+
5916
+ .workspace-run-card .workspace-card-root,
5917
+ .workspace-run-card .workspace-card-name {
5918
+ font-family: var(--font-mono);
5919
+ font-size: 12px;
5920
+ color: var(--fg-muted);
5921
+ }
5922
+
5923
+ /* --- Workspace forms: external-repo picker --- */
5924
+
5925
+ .repo-checklist-actions {
5926
+ display: flex;
5927
+ align-items: center;
5928
+ gap: 12px;
5929
+ margin-top: 12px;
5930
+ flex-wrap: wrap;
5931
+ }
5932
+ .ws-external-tag {
5933
+ margin-left: 8px;
5934
+ }
5935
+
5936
+ /* --- Workspace forms: Dependency Graph label --- */
5937
+
5938
+ .dag-preview-block {
5939
+ margin-top: 16px;
5940
+ }
5941
+ .dag-preview-label {
5942
+ display: block;
5943
+ margin-bottom: 8px;
5944
+ }
5945
+
5946
+ /* --- Workspace edit: scan-for-additions status + Available tag --- */
5947
+
5948
+ .ws-edit-scan-status {
5949
+ display: flex;
5950
+ align-items: center;
5951
+ gap: 8px;
5952
+ font-size: 13px;
5953
+ color: var(--fg-muted);
5954
+ margin-bottom: 12px;
5955
+ }
5956
+ .ws-edit-scan-error {
5957
+ margin-bottom: 12px;
5958
+ }
5959
+ .ws-edit-new-tag {
5960
+ margin-left: 8px;
5961
+ }
5962
+
5963
+ /* --- Workspace create: Parent Directory row --- */
5964
+
5965
+ .parent-dir-row {
5966
+ display: flex;
5967
+ gap: 8px;
5968
+ align-items: stretch;
5969
+ }
5970
+ .parent-dir-row .input-parent-dir {
5971
+ flex: 1;
5972
+ }
5973
+ .parent-dir-suggestions {
5974
+ margin-top: 8px;
5975
+ border: 1px solid var(--border);
5976
+ border-radius: 6px;
5977
+ background: var(--bg);
5978
+ overflow: hidden;
5979
+ }
5980
+ .parent-dir-suggestions-label {
5981
+ padding: 6px 12px;
5982
+ font-size: 11px;
5983
+ text-transform: uppercase;
5984
+ letter-spacing: 0.04em;
5985
+ color: var(--fg-muted);
5986
+ background: var(--bg-secondary);
5987
+ border-bottom: 1px solid var(--border-subtle);
5988
+ }
5989
+ .parent-dir-suggestion-item {
5990
+ display: flex;
5991
+ align-items: center;
5992
+ gap: 8px;
5993
+ width: 100%;
5994
+ padding: 8px 12px;
5995
+ background: transparent;
5996
+ border: none;
5997
+ border-bottom: 1px solid var(--border-subtle);
5998
+ cursor: pointer;
5999
+ font-family: var(--font-mono);
6000
+ font-size: 13px;
6001
+ color: var(--fg);
6002
+ text-align: left;
6003
+ }
6004
+ .parent-dir-suggestion-item:last-child {
6005
+ border-bottom: none;
6006
+ }
6007
+ .parent-dir-suggestion-item:hover {
6008
+ background: var(--bg-hover);
6009
+ }
6010
+ .parent-dir-suggestion-item svg {
6011
+ flex-shrink: 0;
6012
+ color: var(--fg-muted);
6013
+ }
6014
+
6015
+ /* --- Configuration → Workspaces list --- */
6016
+
6017
+ .workspaces-config-empty {
6018
+ display: flex;
6019
+ flex-direction: column;
6020
+ align-items: center;
6021
+ justify-content: center;
6022
+ text-align: center;
6023
+ padding: 64px 24px;
6024
+ gap: 12px;
6025
+ color: var(--fg-muted);
6026
+ }
6027
+ .workspaces-config-empty .empty-icon {
6028
+ color: var(--fg-muted);
6029
+ opacity: 0.5;
6030
+ margin-bottom: 8px;
6031
+ }
6032
+ .workspaces-config-empty h3 {
6033
+ margin: 0;
6034
+ color: var(--fg);
6035
+ }
6036
+ .workspaces-config-empty p {
6037
+ max-width: 480px;
6038
+ margin: 0 0 12px;
6039
+ line-height: 1.5;
6040
+ }
6041
+
6042
+ .workspaces-config-table {
6043
+ padding: 16px;
6044
+ overflow-x: auto;
6045
+ }
6046
+ .workspaces-config-table table {
6047
+ width: 100%;
6048
+ border-collapse: collapse;
6049
+ font-size: 14px;
6050
+ }
6051
+ .workspaces-config-table thead th {
6052
+ text-align: left;
6053
+ font-weight: 600;
6054
+ padding: 8px 12px;
6055
+ border-bottom: 1px solid var(--border);
6056
+ color: var(--fg-muted);
6057
+ text-transform: uppercase;
6058
+ font-size: 11px;
6059
+ letter-spacing: 0.04em;
6060
+ }
6061
+ .workspaces-config-table tbody td {
6062
+ padding: 12px;
6063
+ border-bottom: 1px solid var(--border);
6064
+ vertical-align: middle;
6065
+ }
6066
+ .workspaces-config-table tbody tr:hover {
6067
+ background: var(--bg-hover);
6068
+ }
6069
+ .workspaces-config-table .ws-name strong {
6070
+ font-weight: 600;
6071
+ }
6072
+ .workspaces-config-table .ws-path code,
6073
+ .workspaces-config-table .ws-umbrella {
6074
+ font-family: var(--font-mono);
6075
+ font-size: 12px;
6076
+ color: var(--fg-muted);
6077
+ }
6078
+ .workspaces-config-table .ws-tiers {
6079
+ color: var(--fg-muted);
6080
+ font-size: 12px;
6081
+ margin-left: 4px;
6082
+ }
6083
+ .workspaces-config-table .ws-dash {
6084
+ color: var(--fg-muted);
6085
+ opacity: 0.5;
6086
+ }
6087
+ .workspaces-config-table .actions-col {
6088
+ text-align: right;
6089
+ }
6090
+ .workspaces-config-table .ws-actions {
6091
+ display: flex;
6092
+ gap: 4px;
6093
+ justify-content: flex-end;
6094
+ }
6095
+ .ws-action-btn {
6096
+ background: transparent;
6097
+ border: 1px solid var(--border);
6098
+ border-radius: 4px;
6099
+ padding: 4px 6px;
6100
+ cursor: pointer;
6101
+ color: var(--fg);
6102
+ display: inline-flex;
6103
+ align-items: center;
6104
+ justify-content: center;
6105
+ }
6106
+ .ws-action-btn:hover {
6107
+ background: var(--bg-hover);
6108
+ }
6109
+ .ws-action-btn--danger:hover {
6110
+ background: rgba(220, 38, 38, 0.1);
6111
+ color: rgb(220, 38, 38);
6112
+ border-color: rgba(220, 38, 38, 0.4);
6113
+ }
6114
+
6115
+ .dag-graph-node rect {
6116
+ rx: 6;
6117
+ fill: var(--bg);
6118
+ stroke: var(--border);
6119
+ stroke-width: 1.5;
6120
+ }
6121
+
6122
+ .dag-graph-node text {
6123
+ font-size: 12px;
6124
+ font-family: var(--sl-font-sans);
6125
+ fill: var(--fg);
6126
+ }
6127
+
6128
+ .dag-graph-edge {
6129
+ fill: none;
6130
+ stroke: var(--border);
6131
+ stroke-width: 2;
6132
+ }
6133
+
6134
+ .dag-graph-node--status-pending rect { stroke: var(--status-pending); }
6135
+ .dag-graph-node--status-running rect { stroke: var(--status-running); }
6136
+ .dag-graph-node--status-completed rect { stroke: var(--status-completed); }
6137
+ .dag-graph-node--status-failed rect { stroke: var(--status-failed); }
6138
+ .dag-graph-node--status-paused rect { stroke: var(--status-paused); }
6139
+ .dag-graph-node--status-blocked rect { stroke: var(--status-blocked); }
6140
+ .dag-graph-node--status-planning rect { stroke: var(--status-running); }
6141
+ .dag-graph-node--status-integration-testing rect { stroke: var(--status-running); }
6142
+ .dag-graph-node--status-integration-failed rect { stroke: var(--status-failed); }
6143
+
6144
+ /* --- Workspace: conflict icon --- */
6145
+
6146
+ .conflict-icon {
6147
+ color: var(--status-blocked);
6148
+ }