anentrypoint-design 0.0.201 → 0.0.203

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-shell.css CHANGED
@@ -154,6 +154,9 @@ pre .n { color: var(--green-2); }
154
154
  ============================================================ */
155
155
  .app {
156
156
  display: flex; flex-direction: column;
157
+ /* Offset parent for the sidebar drawer/scrim/toggle, which are absolute so
158
+ they overlay THIS shell (a thebird WM window) rather than the viewport. */
159
+ position: relative;
157
160
  min-height: 100vh;
158
161
  /* Definite height so the flex column resolves height:100% for descendants
159
162
  (e.g. a full-height chat) at every breakpoint, not just where a desktop
@@ -1299,6 +1302,19 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1299
1302
  .ds-upload-item.done .ds-upload-pct { color: var(--success); }
1300
1303
  .ds-upload-item.error .ds-upload-fill { background: var(--warn); }
1301
1304
  .ds-upload-item.error .ds-upload-pct { color: var(--warn); }
1305
+ /* Per-row upload recovery actions (replace / dismiss) — error rows are not dead ends. */
1306
+ .ds-upload-item { grid-template-columns: minmax(0, 1fr) 120px 44px auto; }
1307
+ .ds-upload-actions { display: inline-flex; gap: var(--space-1); justify-content: flex-end; }
1308
+ .ds-upload-act {
1309
+ padding: 2px 10px; min-height: 24px; cursor: pointer;
1310
+ background: var(--bg); border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1);
1311
+ color: var(--fg-2); font-family: var(--ff-body); font-size: var(--fs-micro);
1312
+ }
1313
+ .ds-upload-act:hover { background: var(--bg-3); color: var(--fg); }
1314
+ .ds-upload-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
1315
+ @media (hover: none), (pointer: coarse) {
1316
+ .ds-upload-act { min-height: 44px; min-width: 44px; }
1317
+ }
1302
1318
 
1303
1319
  /* Empty state */
1304
1320
  .ds-file-empty {
@@ -1356,6 +1372,14 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1356
1372
  font-family: inherit; font-size: var(--fs-sm);
1357
1373
  }
1358
1374
  .ds-modal-input:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
1375
+ /* In-body modal error (role=alert): mutation failures (409/403) surface INSIDE
1376
+ the dialog, not behind the fixed overlay. */
1377
+ .ds-modal-error {
1378
+ margin: var(--space-2) 0 0; padding: 8px 10px;
1379
+ border: var(--bw-hair) solid var(--flame); border-radius: var(--r-2);
1380
+ background: color-mix(in oklab, var(--flame) 12%, var(--bg));
1381
+ color: var(--flame); font-size: var(--fs-xs);
1382
+ }
1359
1383
  .btn-primary.danger {
1360
1384
  background: var(--warn);
1361
1385
  border-color: var(--warn);
@@ -1485,10 +1509,12 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1485
1509
  .ds-file-row:hover .ds-file-check,
1486
1510
  .ds-file-row:focus-within .ds-file-check,
1487
1511
  .ds-file-check.on { opacity: 1; }
1488
- /* Touch / coarse-pointer devices have no hover — keep checkboxes visible so
1489
- multi-select is reachable without a pointer. */
1512
+ /* Touch / coarse-pointer devices have no hover — keep checkboxes AND the
1513
+ per-row action buttons (rename/delete/download) visible so the file manager
1514
+ is fully reachable without a pointer (e.g. an iPad in landscape). */
1490
1515
  @media (hover: none), (pointer: coarse) {
1491
1516
  .ds-file-check { opacity: 1; }
1517
+ .ds-file-actions { opacity: 1; }
1492
1518
  }
1493
1519
  .ds-file-check.on { background: var(--accent); border-color: var(--accent); }
1494
1520
  .ds-file-row.selected {
@@ -2639,14 +2665,20 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
2639
2665
  ============================================================ */
2640
2666
 
2641
2667
  /* Tablet + Mobile: side rail becomes off-canvas drawer (≤900px) */
2642
- @media (max-width: 900px) {
2668
+ /* Sidebar drawer collapse keys on the SHELL width (@container on .app, which is
2669
+ container-type:inline-size) — NOT the viewport. Full-page (freddie) the shell
2670
+ == viewport so this is identical to the old @media(max-width:900px); embedded
2671
+ in a thebird WM window the drawer + hamburger appear when the WINDOW is narrow
2672
+ even on a wide desktop. Drawer/scrim/toggle are absolute (anchored to .app), so
2673
+ they overlay the window, not the page. */
2674
+ @container (max-width: 900px) {
2643
2675
  .app-body,
2644
2676
  .app-body.no-side { grid-template-columns: 1fr !important; }
2645
2677
  .app-side-shell {
2646
- position: fixed;
2678
+ position: absolute;
2647
2679
  left: 0; top: var(--app-topbar-h);
2648
- height: calc(100vh - var(--app-topbar-h) - var(--app-status-h));
2649
- width: 280px; max-width: 80vw;
2680
+ height: calc(100% - var(--app-topbar-h) - var(--app-status-h));
2681
+ width: 280px; max-width: 80%;
2650
2682
  transform: translateX(-100%);
2651
2683
  transition: transform var(--dur-base, 240ms) var(--ease, ease);
2652
2684
  z-index: 50;
@@ -2680,21 +2712,24 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
2680
2712
  .app-main { padding-left: var(--space-3); padding-right: var(--space-3); }
2681
2713
  }
2682
2714
 
2683
- /* Drawer scrim — lives inside .app-body, shown when drawer open ≤900px */
2715
+ /* Drawer scrim — absolute so it covers THIS shell, shown when drawer open and
2716
+ the shell is narrow (@container on .app). */
2684
2717
  .app-side-scrim {
2685
2718
  display: none;
2686
- position: fixed; inset: 0;
2719
+ position: absolute; inset: 0;
2687
2720
  background: color-mix(in oklab, var(--bg) 60%, transparent);
2688
2721
  z-index: 49;
2689
2722
  }
2690
- @media (max-width: 900px) {
2723
+ @container (max-width: 900px) {
2691
2724
  .app-body.side-open .app-side-scrim { display: block; }
2692
2725
  }
2693
2726
 
2694
- /* Mobile nav toggle (hamburger) — hidden on desktop, shown ≤900px */
2727
+ /* Nav toggle (hamburger) — hidden when the shell is wide, shown when the shell
2728
+ itself is narrow (@container on .app). Absolute so it sits in THIS shell's
2729
+ topbar, not pinned to the viewport corner. */
2695
2730
  .app-side-toggle {
2696
2731
  display: none;
2697
- position: fixed; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
2732
+ position: absolute; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
2698
2733
  z-index: 51;
2699
2734
  /* 44x44 minimum hit area (WCAG 2.5.5 / Apple HIG) - 36px is below the
2700
2735
  reliable-tap threshold on touch. */
@@ -2707,7 +2742,7 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
2707
2742
  cursor: pointer;
2708
2743
  }
2709
2744
  .app-side-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
2710
- @media (max-width: 900px) {
2745
+ @container (max-width: 900px) {
2711
2746
  .app-side-toggle { display: inline-flex; }
2712
2747
  .app-topbar .brand { margin-left: 44px; }
2713
2748
  }
package/chat.css CHANGED
@@ -541,3 +541,94 @@ button.chat-composer-context:focus-visible { outline: 2px solid var(--accent); o
541
541
  @media (pointer: coarse), (max-width: 640px) {
542
542
  .ds-session-meta-copy { min-height: 44px; min-width: 44px; }
543
543
  }
544
+
545
+ /* ============================================================================
546
+ Logic/predictability sweep (2026-06-10): composer ergonomics, turn notices,
547
+ windowed thread, dashboard stopping/external states, cwd validation.
548
+ ============================================================================ */
549
+
550
+ /* Enter-to-send hint: visible while the composer is focused or carries a
551
+ draft; hidden under 420px to save rows. */
552
+ .chat-composer-hint {
553
+ display: none; padding: 2px var(--space-3) 0;
554
+ font-size: var(--fs-micro); color: var(--fg-3);
555
+ }
556
+ .chat-composer:focus-within .chat-composer-hint,
557
+ .chat-composer.has-draft .chat-composer-hint { display: block; }
558
+ @media (max-width: 420px) {
559
+ .chat-composer .chat-composer-hint { display: none; }
560
+ }
561
+
562
+ /* Transient composer note (paste/drop not supported), aria-live polite. */
563
+ .chat-composer-note {
564
+ padding: 4px var(--space-3); font-size: var(--fs-tiny); color: var(--fg-2);
565
+ }
566
+
567
+ /* Drag-over ring: token accent, never a hex. */
568
+ .chat-composer.dragover { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--r-2); }
569
+
570
+ /* Per-bit composer context: only the bit that owns a control is a button. */
571
+ .chat-composer-context-bit {
572
+ display: inline; padding: 0; margin: 0;
573
+ background: none; border: none; cursor: pointer;
574
+ font: inherit; color: inherit; text-decoration: underline dotted;
575
+ }
576
+ .chat-composer-context-bit:hover { color: var(--fg-2); }
577
+ .chat-composer-context-bit:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
578
+ @media (pointer: coarse) {
579
+ .chat-composer-context-bit { min-height: 44px; }
580
+ }
581
+
582
+ /* Out-of-band turn notices: neutral tone (NOT error red) — a stopped or
583
+ incomplete turn must not read as a finished answer. */
584
+ .chat-msg-notice {
585
+ margin-top: var(--space-1); padding: 6px 10px;
586
+ border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
587
+ background: var(--bg-2); color: var(--fg-2); font-size: var(--fs-tiny);
588
+ }
589
+ .chat-msg-notice.is-incomplete { border-style: dashed; }
590
+
591
+ /* Tail-window streaming head ('streaming · N KB so far'). */
592
+ .chat-stream-head {
593
+ padding: 2px 0 6px; font-family: var(--ff-mono);
594
+ font-size: var(--fs-micro); color: var(--fg-3);
595
+ }
596
+
597
+ /* Windowed thread: 'show N earlier turns' control at the top. */
598
+ .agentchat-earlier {
599
+ display: flex; align-items: center; justify-content: center;
600
+ gap: var(--space-3); padding: var(--space-2) var(--space-3);
601
+ }
602
+ .agentchat-earlier-count { font-size: var(--fs-tiny); color: var(--fg-3); }
603
+ .agentchat-earlier-btn {
604
+ padding: 4px 12px; min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
605
+ border-radius: var(--r-1); background: var(--bg-2); color: var(--fg-2); cursor: pointer;
606
+ font-family: var(--ff-body); font-size: var(--fs-tiny);
607
+ }
608
+ .agentchat-earlier-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
609
+ @media (pointer: coarse) {
610
+ .agentchat-earlier-btn { min-height: 44px; }
611
+ }
612
+
613
+ /* Inline cwd validation line (checking / error) under the cwd input. */
614
+ .agentchat-cwd-hint { font-size: var(--fs-tiny); color: var(--fg-3); }
615
+ .agentchat-cwd-hint.is-error { color: var(--flame); }
616
+
617
+ /* Dashboard: shared session title heading (same string as the rails). */
618
+ .ds-dash-title {
619
+ font-size: var(--fs-body); font-weight: 600; color: var(--fg);
620
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
621
+ }
622
+
623
+ /* Stopping state: in-flight cancel reads distinctly from running/error. */
624
+ .ds-dash-status.is-stopping { color: var(--amber, #d9a93a); }
625
+
626
+ /* External (observed, not owned) session card: no stop control exists. */
627
+ .ds-dash-external {
628
+ padding: 1px 6px; border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-pill);
629
+ font-size: var(--fs-micro); color: var(--fg-3); text-transform: uppercase; letter-spacing: .03em;
630
+ }
631
+ .ds-dash-card.is-external { border-style: dashed; }
632
+
633
+ /* One connection vocabulary: offline (is-lost kept as legacy alias). */
634
+ .ds-dash-stream.is-offline { color: var(--flame); }
package/dist/247420.css CHANGED
@@ -555,6 +555,9 @@
555
555
  ============================================================ */
556
556
  .ds-247420 .app {
557
557
  display: flex; flex-direction: column;
558
+ /* Offset parent for the sidebar drawer/scrim/toggle, which are absolute so
559
+ they overlay THIS shell (a thebird WM window) rather than the viewport. */
560
+ position: relative;
558
561
  min-height: 100vh;
559
562
  /* Definite height so the flex column resolves height:100% for descendants
560
563
  (e.g. a full-height chat) at every breakpoint, not just where a desktop
@@ -1700,6 +1703,19 @@
1700
1703
  .ds-247420 .ds-upload-item.done .ds-upload-pct { color: var(--success); }
1701
1704
  .ds-247420 .ds-upload-item.error .ds-upload-fill { background: var(--warn); }
1702
1705
  .ds-247420 .ds-upload-item.error .ds-upload-pct { color: var(--warn); }
1706
+ /* Per-row upload recovery actions (replace / dismiss) — error rows are not dead ends. */
1707
+ .ds-247420 .ds-upload-item { grid-template-columns: minmax(0, 1fr) 120px 44px auto; }
1708
+ .ds-247420 .ds-upload-actions { display: inline-flex; gap: var(--space-1); justify-content: flex-end; }
1709
+ .ds-247420 .ds-upload-act {
1710
+ padding: 2px 10px; min-height: 24px; cursor: pointer;
1711
+ background: var(--bg); border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1);
1712
+ color: var(--fg-2); font-family: var(--ff-body); font-size: var(--fs-micro);
1713
+ }
1714
+ .ds-247420 .ds-upload-act:hover { background: var(--bg-3); color: var(--fg); }
1715
+ .ds-247420 .ds-upload-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
1716
+ @media (hover: none), (pointer: coarse) {
1717
+ .ds-247420 .ds-upload-act { min-height: 44px; min-width: 44px; }
1718
+ }
1703
1719
 
1704
1720
  /* Empty state */
1705
1721
  .ds-247420 .ds-file-empty {
@@ -1757,6 +1773,14 @@
1757
1773
  font-family: inherit; font-size: var(--fs-sm);
1758
1774
  }
1759
1775
  .ds-247420 .ds-modal-input:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
1776
+ /* In-body modal error (role=alert): mutation failures (409/403) surface INSIDE
1777
+ the dialog, not behind the fixed overlay. */
1778
+ .ds-247420 .ds-modal-error {
1779
+ margin: var(--space-2) 0 0; padding: 8px 10px;
1780
+ border: var(--bw-hair) solid var(--flame); border-radius: var(--r-2);
1781
+ background: color-mix(in oklab, var(--flame) 12%, var(--bg));
1782
+ color: var(--flame); font-size: var(--fs-xs);
1783
+ }
1760
1784
  .ds-247420 .btn-primary.danger {
1761
1785
  background: var(--warn);
1762
1786
  border-color: var(--warn);
@@ -1886,10 +1910,12 @@
1886
1910
  .ds-247420 .ds-file-row:hover .ds-file-check,
1887
1911
  .ds-247420 .ds-file-row:focus-within .ds-file-check,
1888
1912
  .ds-247420 .ds-file-check.on { opacity: 1; }
1889
- /* Touch / coarse-pointer devices have no hover — keep checkboxes visible so
1890
- multi-select is reachable without a pointer. */
1913
+ /* Touch / coarse-pointer devices have no hover — keep checkboxes AND the
1914
+ per-row action buttons (rename/delete/download) visible so the file manager
1915
+ is fully reachable without a pointer (e.g. an iPad in landscape). */
1891
1916
  @media (hover: none), (pointer: coarse) {
1892
1917
  .ds-247420 .ds-file-check { opacity: 1; }
1918
+ .ds-247420 .ds-file-actions { opacity: 1; }
1893
1919
  }
1894
1920
  .ds-247420 .ds-file-check.on { background: var(--accent); border-color: var(--accent); }
1895
1921
  .ds-247420 .ds-file-row.selected {
@@ -3031,14 +3057,20 @@
3031
3057
  ============================================================ */
3032
3058
 
3033
3059
  /* Tablet + Mobile: side rail becomes off-canvas drawer (≤900px) */
3034
- @media (max-width: 900px) {
3060
+ /* Sidebar drawer collapse keys on the SHELL width (@container on .app, which is
3061
+ container-type:inline-size) — NOT the viewport. Full-page (freddie) the shell
3062
+ == viewport so this is identical to the old @media(max-width:900px); embedded
3063
+ in a thebird WM window the drawer + hamburger appear when the WINDOW is narrow
3064
+ even on a wide desktop. Drawer/scrim/toggle are absolute (anchored to .app), so
3065
+ they overlay the window, not the page. */
3066
+ @container (max-width: 900px) {
3035
3067
  .ds-247420 .app-body,
3036
3068
  .ds-247420 .app-body.no-side { grid-template-columns: 1fr !important; }
3037
3069
  .ds-247420 .app-side-shell {
3038
- position: fixed;
3070
+ position: absolute;
3039
3071
  left: 0; top: var(--app-topbar-h);
3040
- height: calc(100vh - var(--app-topbar-h) - var(--app-status-h));
3041
- width: 280px; max-width: 80vw;
3072
+ height: calc(100% - var(--app-topbar-h) - var(--app-status-h));
3073
+ width: 280px; max-width: 80%;
3042
3074
  transform: translateX(-100%);
3043
3075
  transition: transform var(--dur-base, 240ms) var(--ease, ease);
3044
3076
  z-index: 50;
@@ -3072,21 +3104,24 @@
3072
3104
  .ds-247420 .app-main { padding-left: var(--space-3); padding-right: var(--space-3); }
3073
3105
  }
3074
3106
 
3075
- /* Drawer scrim — lives inside .app-body, shown when drawer open ≤900px */
3107
+ /* Drawer scrim — absolute so it covers THIS shell, shown when drawer open and
3108
+ the shell is narrow (@container on .app). */
3076
3109
  .ds-247420 .app-side-scrim {
3077
3110
  display: none;
3078
- position: fixed; inset: 0;
3111
+ position: absolute; inset: 0;
3079
3112
  background: color-mix(in oklab, var(--bg) 60%, transparent);
3080
3113
  z-index: 49;
3081
3114
  }
3082
- @media (max-width: 900px) {
3115
+ @container (max-width: 900px) {
3083
3116
  .ds-247420 .app-body.side-open .app-side-scrim { display: block; }
3084
3117
  }
3085
3118
 
3086
- /* Mobile nav toggle (hamburger) — hidden on desktop, shown ≤900px */
3119
+ /* Nav toggle (hamburger) — hidden when the shell is wide, shown when the shell
3120
+ itself is narrow (@container on .app). Absolute so it sits in THIS shell's
3121
+ topbar, not pinned to the viewport corner. */
3087
3122
  .ds-247420 .app-side-toggle {
3088
3123
  display: none;
3089
- position: fixed; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
3124
+ position: absolute; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
3090
3125
  z-index: 51;
3091
3126
  /* 44x44 minimum hit area (WCAG 2.5.5 / Apple HIG) - 36px is below the
3092
3127
  reliable-tap threshold on touch. */
@@ -3099,7 +3134,7 @@
3099
3134
  cursor: pointer;
3100
3135
  }
3101
3136
  .ds-247420 .app-side-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
3102
- @media (max-width: 900px) {
3137
+ @container (max-width: 900px) {
3103
3138
  .ds-247420 .app-side-toggle { display: inline-flex; }
3104
3139
  .ds-247420 .app-topbar .brand { margin-left: 44px; }
3105
3140
  }
@@ -5415,6 +5450,97 @@
5415
5450
  .ds-247420 .ds-session-meta-copy { min-height: 44px; min-width: 44px; }
5416
5451
  }
5417
5452
 
5453
+ /* ============================================================================
5454
+ Logic/predictability sweep (2026-06-10): composer ergonomics, turn notices,
5455
+ windowed thread, dashboard stopping/external states, cwd validation.
5456
+ ============================================================================ */
5457
+
5458
+ /* Enter-to-send hint: visible while the composer is focused or carries a
5459
+ draft; hidden under 420px to save rows. */
5460
+ .ds-247420 .chat-composer-hint {
5461
+ display: none; padding: 2px var(--space-3) 0;
5462
+ font-size: var(--fs-micro); color: var(--fg-3);
5463
+ }
5464
+ .ds-247420 .chat-composer:focus-within .chat-composer-hint,
5465
+ .ds-247420 .chat-composer.has-draft .chat-composer-hint { display: block; }
5466
+ @media (max-width: 420px) {
5467
+ .ds-247420 .chat-composer .chat-composer-hint { display: none; }
5468
+ }
5469
+
5470
+ /* Transient composer note (paste/drop not supported), aria-live polite. */
5471
+ .ds-247420 .chat-composer-note {
5472
+ padding: 4px var(--space-3); font-size: var(--fs-tiny); color: var(--fg-2);
5473
+ }
5474
+
5475
+ /* Drag-over ring: token accent, never a hex. */
5476
+ .ds-247420 .chat-composer.dragover { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--r-2); }
5477
+
5478
+ /* Per-bit composer context: only the bit that owns a control is a button. */
5479
+ .ds-247420 .chat-composer-context-bit {
5480
+ display: inline; padding: 0; margin: 0;
5481
+ background: none; border: none; cursor: pointer;
5482
+ font: inherit; color: inherit; text-decoration: underline dotted;
5483
+ }
5484
+ .ds-247420 .chat-composer-context-bit:hover { color: var(--fg-2); }
5485
+ .ds-247420 .chat-composer-context-bit:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
5486
+ @media (pointer: coarse) {
5487
+ .ds-247420 .chat-composer-context-bit { min-height: 44px; }
5488
+ }
5489
+
5490
+ /* Out-of-band turn notices: neutral tone (NOT error red) — a stopped or
5491
+ incomplete turn must not read as a finished answer. */
5492
+ .ds-247420 .chat-msg-notice {
5493
+ margin-top: var(--space-1); padding: 6px 10px;
5494
+ border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
5495
+ background: var(--bg-2); color: var(--fg-2); font-size: var(--fs-tiny);
5496
+ }
5497
+ .ds-247420 .chat-msg-notice.is-incomplete { border-style: dashed; }
5498
+
5499
+ /* Tail-window streaming head ('streaming · N KB so far'). */
5500
+ .ds-247420 .chat-stream-head {
5501
+ padding: 2px 0 6px; font-family: var(--ff-mono);
5502
+ font-size: var(--fs-micro); color: var(--fg-3);
5503
+ }
5504
+
5505
+ /* Windowed thread: 'show N earlier turns' control at the top. */
5506
+ .ds-247420 .agentchat-earlier {
5507
+ display: flex; align-items: center; justify-content: center;
5508
+ gap: var(--space-3); padding: var(--space-2) var(--space-3);
5509
+ }
5510
+ .ds-247420 .agentchat-earlier-count { font-size: var(--fs-tiny); color: var(--fg-3); }
5511
+ .ds-247420 .agentchat-earlier-btn {
5512
+ padding: 4px 12px; min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
5513
+ border-radius: var(--r-1); background: var(--bg-2); color: var(--fg-2); cursor: pointer;
5514
+ font-family: var(--ff-body); font-size: var(--fs-tiny);
5515
+ }
5516
+ .ds-247420 .agentchat-earlier-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
5517
+ @media (pointer: coarse) {
5518
+ .ds-247420 .agentchat-earlier-btn { min-height: 44px; }
5519
+ }
5520
+
5521
+ /* Inline cwd validation line (checking / error) under the cwd input. */
5522
+ .ds-247420 .agentchat-cwd-hint { font-size: var(--fs-tiny); color: var(--fg-3); }
5523
+ .ds-247420 .agentchat-cwd-hint.is-error { color: var(--flame); }
5524
+
5525
+ /* Dashboard: shared session title heading (same string as the rails). */
5526
+ .ds-247420 .ds-dash-title {
5527
+ font-size: var(--fs-body); font-weight: 600; color: var(--fg);
5528
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
5529
+ }
5530
+
5531
+ /* Stopping state: in-flight cancel reads distinctly from running/error. */
5532
+ .ds-247420 .ds-dash-status.is-stopping { color: var(--amber, #d9a93a); }
5533
+
5534
+ /* External (observed, not owned) session card: no stop control exists. */
5535
+ .ds-247420 .ds-dash-external {
5536
+ padding: 1px 6px; border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-pill);
5537
+ font-size: var(--fs-micro); color: var(--fg-3); text-transform: uppercase; letter-spacing: .03em;
5538
+ }
5539
+ .ds-247420 .ds-dash-card.is-external { border-style: dashed; }
5540
+
5541
+ /* One connection vocabulary: offline (is-lost kept as legacy alias). */
5542
+ .ds-247420 .ds-dash-stream.is-offline { color: var(--flame); }
5543
+
5418
5544
  /* editor-primitives.css */
5419
5545
  /* editor-primitives.css — chrome for in-engine editors, inspectors, IDEs,
5420
5546
  debug HUDs. All rules under .ds-247420 scope (build prefixes). Tokens