anentrypoint-design 0.0.208 → 0.0.209

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/dist/247420.css CHANGED
@@ -37,9 +37,21 @@
37
37
 
38
38
  /* Signals */
39
39
  --sun: #F5C344;
40
- --flame: #FF5A1F;
40
+ /* Error/status tones are theme-tuned: the root values are the LIGHT (paper)
41
+ pair (flame 4.74:1, amber 4.5+:1 on paper); the dark blocks below restore
42
+ the originals (#FF5A1F / #D9A93A) which were tuned on ink and fail on
43
+ paper (2.9:1 / 2.0:1). */
44
+ --flame: #C53E00;
45
+ --amber: #8A6512;
41
46
  --sky: #3A6EFF;
42
47
  --warn: #E0241A;
48
+ /* Syntax-token aliases: light values pass 4.5:1 on paper; the dark blocks
49
+ restore the bright dark-tuned originals. Components reference ONLY these. */
50
+ --code-string: var(--green);
51
+ --code-keyword: #2453C9;
52
+ --code-fn: #B84300;
53
+ --code-str-alt: var(--mascot-deep);
54
+ --code-num: #946300;
43
55
  --danger: oklch(0.55 0.18 25);
44
56
  --success: var(--green-2);
45
57
  --live: var(--green);
@@ -248,6 +260,13 @@
248
260
  --accent-fg: var(--ink);
249
261
  --accent-bright: var(--green-2);
250
262
  --danger: oklch(0.68 0.19 25);
263
+ --flame: #FF5A1F;
264
+ --amber: #D9A93A;
265
+ --code-string: var(--green-2);
266
+ --code-keyword: var(--sky);
267
+ --code-fn: var(--flame);
268
+ --code-str-alt: var(--mascot);
269
+ --code-num: var(--sun);
251
270
  }
252
271
 
253
272
  /* NOTE: the [data-theme="auto"] block below intentionally duplicates the
@@ -274,6 +293,13 @@
274
293
  --accent: var(--accent-bright, var(--green-2));
275
294
  --accent-fg: var(--ink);
276
295
  --accent-bright: var(--green-2);
296
+ --flame: #FF5A1F;
297
+ --amber: #D9A93A;
298
+ --code-string: var(--green-2);
299
+ --code-keyword: var(--sky);
300
+ --code-fn: var(--flame);
301
+ --code-str-alt: var(--mascot);
302
+ --code-num: var(--sun);
277
303
  }
278
304
  }
279
305
 
@@ -312,6 +338,11 @@
312
338
  --cat-sun: inherit;
313
339
  --cat-flame: inherit;
314
340
  --cat-sky: inherit;
341
+ --code-string: inherit;
342
+ --code-keyword: inherit;
343
+ --code-fn: inherit;
344
+ --code-str-alt: inherit;
345
+ --code-num: inherit;
315
346
  }
316
347
 
317
348
  /* ============================================================
@@ -328,6 +359,8 @@
328
359
  --bg: var(--paper); --bg-2: var(--paper-2); --bg-3: var(--paper-3);
329
360
  --fg: var(--ink); --fg-2: var(--ink-2); --fg-3: var(--ink-3);
330
361
  --accent: var(--green); --accent-fg: var(--paper);
362
+ /* A paper island under a dark ancestor must not inherit the dark signal pair. */
363
+ --flame: #C53E00; --amber: #8A6512;
331
364
  }
332
365
 
333
366
  /* thebird — warm-paper brand preset. A first-class swappable theme: it lives
@@ -544,8 +577,8 @@
544
577
  margin: 0;
545
578
  border-radius: var(--r-3);
546
579
  }
547
- .ds-247420 pre .k { color: var(--mascot); }
548
- .ds-247420 pre .s { color: var(--sun); }
580
+ .ds-247420 pre .k { color: var(--code-str-alt, var(--mascot)); }
581
+ .ds-247420 pre .s { color: var(--code-string, var(--green)); }
549
582
  .ds-247420 pre .c { color: var(--fg-3); }
550
583
  .ds-247420 pre .n { color: var(--green-2); }
551
584
 
@@ -787,13 +820,21 @@
787
820
  width: 100%;
788
821
  min-height: var(--app-status-h);
789
822
  padding: 10px var(--pad-x);
790
- font-family: var(--ff-mono); font-size: var(--fs-xs);
823
+ /* Status chrome is prose, not code - mono is reserved for code/paths. */
824
+ font-family: var(--ff-body); font-size: var(--fs-xs);
791
825
  color: var(--fg-3);
792
826
  border-top: 1px solid var(--rule);
793
827
  }
794
- .ds-247420 .app-status .item { color: inherit; }
828
+ .ds-247420 .app-status .item { color: inherit; white-space: nowrap; }
795
829
  .ds-247420 .app-status .item:first-of-type { color: var(--accent); }
796
830
  .ds-247420 .app-status .spread { flex: 1; }
831
+ /* The status bar NEVER wraps: at narrow widths the trailing items (hints,
832
+ agent target) drop in priority order instead of breaking mid-word onto a
833
+ second line. */
834
+ .ds-247420 .app-status { flex-wrap: nowrap; overflow: hidden; }
835
+ @media (max-width: 1100px) {
836
+ .ds-247420 .app-status .item:last-of-type:not(:only-of-type) { display: none; }
837
+ }
797
838
 
798
839
  /* ============================================================
799
840
  Primitives
@@ -840,7 +881,8 @@
840
881
  .ds-247420 .ds-icon-btn-ghost:hover { background: var(--bg-2); }
841
882
  .ds-247420 .ds-icon-btn-primary { background: var(--accent); color: var(--accent-fg); }
842
883
  .ds-247420 .ds-icon-btn-primary:hover { background: var(--fg); color: var(--bg); }
843
- .ds-247420 .ds-icon-btn-danger { background: var(--flame); color: var(--paper); }
884
+ /* warn = destructive ACTION tone; flame stays exclusively error STATUS. */
885
+ .ds-247420 .ds-icon-btn-danger { background: var(--warn); color: var(--paper); }
844
886
  .ds-247420 .ds-icon-btn-danger:hover { filter: brightness(1.1); }
845
887
  .ds-247420 .ds-icon-btn:active { transform: translateY(1px); }
846
888
  .ds-247420 .ds-icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@@ -914,11 +956,15 @@
914
956
  .ds-247420 .panel.panel-wide { background: transparent; }
915
957
  .ds-247420 .panel-head {
916
958
  display: flex; align-items: baseline; justify-content: space-between;
917
- padding: var(--space-4) var(--space-5) var(--space-3);
959
+ /* Shares the .panel-body 16px side padding so the caps label and the body
960
+ rows sit on ONE left axis (the old 24/32 padding was authored for the
961
+ pre-padding .panel-wide era and indented the label 16px past its content). */
962
+ padding: var(--space-2) var(--space-3);
918
963
  font-size: var(--fs-xs); font-weight: 600;
919
964
  color: var(--fg-3);
920
965
  letter-spacing: var(--tr-caps); text-transform: uppercase;
921
966
  }
967
+ .ds-247420 .panel.panel-wide .panel-head { padding-left: 0; padding-right: 0; }
922
968
  .ds-247420 .panel-head > :last-child {
923
969
  font-weight: 500; color: var(--fg-3);
924
970
  font-family: var(--ff-mono); letter-spacing: 0;
@@ -986,6 +1032,12 @@
986
1032
  .ds-247420 .row .code { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
987
1033
  .ds-247420 .row .title { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-lg); line-height: var(--lh-snug, 1.3); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
988
1034
  .ds-247420 .row .title .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
1035
+ /* App typescale: list rows are quiet working chrome (the 18px/600 default is a
1036
+ marketing-surface voice). One size for ALL app list rows - matches
1037
+ .ds-file-row/.ds-session-title at fs-sm/500; values mirror the kit's own
1038
+ mobile block below. Marketing pages without data-typescale keep the default. */
1039
+ .ds-247420[data-typescale="app"] .row { padding: 12px 16px; }
1040
+ .ds-247420[data-typescale="app"] .row .title { font-size: var(--fs-sm); font-weight: 500; }
989
1041
  .ds-247420 .row .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
990
1042
  .ds-247420 .row .meta { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; align-self: center; }
991
1043
  /* WorksList meta pairs a label with a disclosure chevron, inline-aligned. */
@@ -1431,8 +1483,8 @@
1431
1483
  padding: 12px 18px; font-size: var(--fs-sm);
1432
1484
  }
1433
1485
 
1434
- /* Panel */
1435
- .ds-247420 .panel-head { padding: var(--space-4) var(--space-4); }
1486
+ /* Panel - keep the head on the body's left axis at laptop widths too. */
1487
+ .ds-247420 .panel-head { padding: var(--space-2) var(--space-3); }
1436
1488
  .ds-247420 .panel-body { padding: var(--space-2) var(--space-3); }
1437
1489
 
1438
1490
  /* Hero — fluid base font-size; only width unconstrained on tablet. */
@@ -1504,13 +1556,15 @@
1504
1556
 
1505
1557
  /* Listing wrapper holds the optional filter + sort header above the grid. */
1506
1558
  .ds-247420 .ds-file-listing { display: flex; flex-direction: column; gap: var(--space-2); min-height: 0; }
1507
- .ds-247420 .ds-file-filter { padding: 0 0 var(--space-1); }
1559
+ /* The quick filter is a compact control, not a full-width form row - a giant
1560
+ input above the grid reads as a search page and costs fold height. */
1561
+ .ds-247420 .ds-file-filter { padding: 0 0 var(--space-1); display: flex; justify-content: flex-end; }
1508
1562
  .ds-247420 .ds-file-filter-input {
1509
- width: 100%; padding: 8px 12px; font-size: var(--fs-sm);
1563
+ width: min(280px, 100%); padding: 6px 12px; font-size: var(--fs-sm);
1510
1564
  background: var(--bg); color: var(--fg);
1511
- border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
1565
+ border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1);
1512
1566
  }
1513
- .ds-247420 .ds-file-filter-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
1567
+ .ds-247420 .ds-file-filter-input:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent); }
1514
1568
  .ds-247420 .ds-file-sort { display: flex; gap: var(--space-2); padding: 0 var(--space-2) var(--space-1); }
1515
1569
  .ds-247420 .ds-file-sort-btn {
1516
1570
  font-size: var(--fs-tiny); font-family: var(--ff-mono); color: var(--fg-3);
@@ -1522,6 +1576,16 @@
1522
1576
 
1523
1577
  /* Skeleton shimmer rows shown while a directory loads. */
1524
1578
  .ds-247420 .ds-file-row-skeleton { cursor: default; pointer-events: none; }
1579
+ /* In-place refresh: dim the populated grid instead of swapping it for shimmer
1580
+ rows (the rows stay; the round-trip reads as a settle, not a reload). */
1581
+ .ds-247420 .ds-file-grid.is-refreshing { opacity: .6; }
1582
+ @media (prefers-reduced-motion: no-preference) {
1583
+ .ds-247420 .ds-file-grid { transition: opacity .15s var(--ease); }
1584
+ }
1585
+ /* EventList loading skeleton (shares the .ds-skel shimmer base above). */
1586
+ .ds-247420 .ds-event-row-skeleton { display: flex; align-items: center; gap: var(--space-3); padding: 12px 16px; pointer-events: none; }
1587
+ .ds-247420 .ds-skel-rank { height: 12px; width: 2.5ch; }
1588
+ .ds-247420 .ds-event-state { padding: var(--space-2) 16px; }
1525
1589
  .ds-247420 .ds-skel { display: inline-block; border-radius: var(--r-1); background: var(--bg-2); position: relative; overflow: hidden; }
1526
1590
  .ds-247420 .ds-skel::after {
1527
1591
  content: ''; position: absolute; inset: 0;
@@ -1570,7 +1634,7 @@
1570
1634
  .ds-247420 .ds-file-row[data-file-type="code"] { border-left-width: 3px; border-left-color: var(--green-2); }
1571
1635
  .ds-247420 .ds-file-row[data-file-type="text"] { border-left-width: 3px; border-left-color: var(--ink-3); }
1572
1636
  .ds-247420 .ds-file-row[data-file-type="archive"] { border-left-width: 3px; border-left-color: var(--flame); }
1573
- .ds-247420 .ds-file-row[data-file-type="document"] { border-left-width: 3px; border-left-color: var(--sun); }
1637
+ .ds-247420 .ds-file-row[data-file-type="document"] { border-left-width: 3px; border-left-color: var(--amber, var(--sun)); }
1574
1638
  .ds-247420 .ds-file-row[data-file-type="symlink"] { border-left-width: 3px; border-left-color: var(--purple); }
1575
1639
  .ds-247420 .ds-file-row[data-file-type="other"] { border-left-width: 3px; border-left-color: var(--fg-3); }
1576
1640
 
@@ -1601,7 +1665,7 @@
1601
1665
  .ds-247420 .ds-file-row[data-file-type="audio"] .ds-file-icon { color: var(--sky); }
1602
1666
  .ds-247420 .ds-file-row[data-file-type="code"] .ds-file-icon { color: var(--green-2); }
1603
1667
  .ds-247420 .ds-file-row[data-file-type="archive"] .ds-file-icon { color: var(--flame); }
1604
- .ds-247420 .ds-file-row[data-file-type="document"] .ds-file-icon { color: var(--sun); }
1668
+ .ds-247420 .ds-file-row[data-file-type="document"] .ds-file-icon { color: var(--amber, var(--sun)); }
1605
1669
 
1606
1670
  /* Row actions — hidden until hover/focus, revealed without layout shift. */
1607
1671
  .ds-247420 .ds-file-actions {
@@ -1651,6 +1715,19 @@
1651
1715
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
1652
1716
  }
1653
1717
  .ds-247420 .ds-bulkbar-count { font-size: var(--fs-tiny); color: var(--fg-2); }
1718
+ /* BulkBar is a toolbar (it even declares role=toolbar): compact rect buttons,
1719
+ quiet destructive outline - the app arm-confirms destructive bulk actions
1720
+ via ConfirmDialog, so the strip never needs a loud CTA. */
1721
+ .ds-247420 .ds-bulkbar .btn, .ds-247420 .ds-bulkbar .btn-primary {
1722
+ padding: 5px 12px; min-height: 32px; border-radius: var(--r-1); font-weight: 500;
1723
+ }
1724
+ .ds-247420 .ds-bulkbar .btn { background: transparent; border: var(--bw-hair) solid var(--rule); color: var(--fg-2); }
1725
+ .ds-247420 .ds-bulkbar .btn:hover { background: var(--bg-2); color: var(--fg); }
1726
+ .ds-247420 .ds-bulkbar .btn-primary.danger { background: transparent; color: var(--warn); border: var(--bw-hair) solid var(--warn); }
1727
+ .ds-247420 .ds-bulkbar .btn-primary.danger:hover { background: color-mix(in oklab, var(--warn) 12%, transparent); color: var(--warn); }
1728
+ @media (pointer: coarse) {
1729
+ .ds-247420 .ds-bulkbar .btn, .ds-247420 .ds-bulkbar .btn-primary { min-height: 44px; }
1730
+ }
1654
1731
 
1655
1732
  /* Density picker — list / compact / thumbnails. */
1656
1733
  .ds-247420 .ds-density {
@@ -1737,6 +1814,11 @@
1737
1814
  .ds-247420 .app-main > div > .ds-file-stage,
1738
1815
  .ds-247420 .app-main .ds-file-stage { padding-top: 0; }
1739
1816
 
1817
+ /* Full-width files stack: the stage's space-3 vertical beat without its
1818
+ 920px cap/auto-margins, so the roots / toolbar / bulkbar / uploads / grid
1819
+ bands keep one consistent rhythm instead of touching edge-to-edge. */
1820
+ .ds-247420 .ds-files-stack { display: flex; flex-direction: column; gap: var(--space-3); min-height: 0; }
1821
+
1740
1822
  /* Breadcrumb path */
1741
1823
  .ds-247420 .ds-crumb-path {
1742
1824
  display: flex; align-items: center; flex-wrap: wrap; gap: 2px;
@@ -1757,10 +1839,38 @@
1757
1839
  display: flex; align-items: center; justify-content: space-between;
1758
1840
  gap: var(--space-2); flex-wrap: wrap;
1759
1841
  }
1842
+ /* Dense page header: one row, small heading, single-line muted lede. The
1843
+ working surfaces (files, live, history, settings) lead with content, not a
1844
+ display H1 + paragraph that costs the first 150px of every fold. */
1845
+ .ds-247420 .ds-page-header-dense { margin: 0 0 var(--space-3); }
1846
+ .ds-247420 .ds-page-header-dense-row { display: flex; align-items: baseline; gap: var(--space-3); min-width: 0; }
1847
+ .ds-247420 .ds-page-header-dense-row h1 {
1848
+ margin: 0; font-size: var(--fs-lg); line-height: 1.3; font-weight: 600;
1849
+ letter-spacing: normal; flex: 0 0 auto;
1850
+ }
1851
+ .ds-247420 .ds-page-header-dense-lede {
1852
+ flex: 1 1 auto; min-width: 0;
1853
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
1854
+ font-size: var(--fs-sm); color: var(--fg-3);
1855
+ }
1856
+ .ds-247420 .ds-page-header-dense .ds-page-header-right { flex: 0 0 auto; margin-left: auto; }
1760
1857
  .ds-247420 .ds-file-toolbar-left,
1761
1858
  .ds-247420 .ds-file-toolbar-right {
1762
1859
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
1763
1860
  }
1861
+ /* Toolbar-scoped buttons: quiet, compact, rectangular - a toolbar is chrome,
1862
+ not a CTA row; the stadium pill stays for real page-level actions. */
1863
+ .ds-247420 .ds-file-toolbar .btn, .ds-247420 .ds-file-toolbar .btn-ghost {
1864
+ padding: 5px 12px; min-height: 32px;
1865
+ border-radius: var(--r-1);
1866
+ font-weight: 500;
1867
+ background: transparent;
1868
+ border: var(--bw-hair) solid var(--rule); color: var(--fg-2);
1869
+ }
1870
+ .ds-247420 .ds-file-toolbar .btn:hover, .ds-247420 .ds-file-toolbar .btn-ghost:hover { background: var(--bg-2); color: var(--fg); }
1871
+ @media (pointer: coarse) {
1872
+ .ds-247420 .ds-file-toolbar .btn, .ds-247420 .ds-file-toolbar .btn-ghost { min-height: 44px; }
1873
+ }
1764
1874
  .ds-247420 .ds-meta-mono {
1765
1875
  font-family: var(--ff-mono); font-size: var(--fs-xs);
1766
1876
  color: var(--fg-3); letter-spacing: var(--tr-caps);
@@ -1801,6 +1911,20 @@
1801
1911
  0%, 100% { border-color: var(--accent); }
1802
1912
  50% { border-color: color-mix(in oklab, var(--accent) 45%, transparent); }
1803
1913
  }
1914
+ /* Wrapper form (has children): no permanent chrome - the content renders as if
1915
+ the zone were not there, and the dashed affordance overlays it ONLY while a
1916
+ drag is in flight. */
1917
+ .ds-247420 .ds-dropzone--wrap { position: relative; border: none; border-radius: 0; background: transparent; }
1918
+ .ds-247420 .ds-dropzone--wrap > .ds-dropzone-inner { display: none; }
1919
+ .ds-247420 .ds-dropzone--wrap.dragover > .ds-dropzone-inner {
1920
+ display: flex; position: absolute; inset: 0; z-index: 5;
1921
+ margin: 0; padding: var(--space-3);
1922
+ align-items: center; justify-content: center;
1923
+ background: color-mix(in srgb, var(--bg) 84%, transparent);
1924
+ outline: var(--bw-rule) dashed var(--accent); outline-offset: -6px;
1925
+ border-radius: var(--r-3);
1926
+ }
1927
+ .ds-247420 .ds-dropzone--wrap.dragover { animation: none; }
1804
1928
 
1805
1929
  /* Upload progress */
1806
1930
  .ds-247420 .ds-upload-progress { display: flex; flex-direction: column; gap: 6px; }
@@ -1994,7 +2118,7 @@
1994
2118
  border-radius: var(--r-pill); color: var(--fg);
1995
2119
  font-family: inherit; font-size: var(--fs-xs);
1996
2120
  }
1997
- .ds-247420 .ds-filter-input:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
2121
+ .ds-247420 .ds-filter-input:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent); }
1998
2122
 
1999
2123
  /* Loading skeleton — placeholder rows while a directory loads. */
2000
2124
  .ds-247420 .ds-file-grid-loading { display: flex; flex-direction: column; gap: 4px; }
@@ -2021,44 +2145,19 @@
2021
2145
  .ds-247420 .ds-file-row[draggable="true"] { cursor: grab; }
2022
2146
  .ds-247420 .ds-file-row[draggable="true"]:active { cursor: grabbing; }
2023
2147
 
2024
- /* Multi-select per-row checkbox overlay + selected state + bulk bar. */
2148
+ /* (A stale duplicate multi-select block used to live here: an absolute-overlay
2149
+ .ds-file-check hidden until hover, plus .ds-file-check.on / .ds-file-row.selected
2150
+ / .ds-bulk-bar rules NO component ever emits. Being later in source at equal
2151
+ specificity it clobbered the real in-flow checkbox at ~1243 - the shipped
2152
+ multi-select rendered invisible-until-hover with clipped brackets. The live
2153
+ rules are the earlier block; only the still-load-bearing bits remain below.) */
2025
2154
  .ds-247420 .ds-file-row { position: relative; }
2026
- .ds-247420 .ds-file-check {
2027
- position: absolute; left: 4px; top: 50%; transform: translateY(-50%);
2028
- width: 18px; height: 18px; padding: 0; z-index: 1;
2029
- display: inline-flex; align-items: center; justify-content: center;
2030
- border: var(--bw-hair) solid var(--rule); border-radius: 5px;
2031
- background: var(--bg); color: var(--accent-fg);
2032
- font-size: var(--fs-micro); line-height: 1; cursor: pointer;
2033
- opacity: 0; transition: opacity var(--dur-base) var(--ease), background var(--dur-snap) var(--ease);
2034
- }
2035
- .ds-247420 .ds-file-row:hover .ds-file-check,
2036
- .ds-247420 .ds-file-row:focus-within .ds-file-check,
2037
- .ds-247420 .ds-file-check.on { opacity: 1; }
2038
- /* Touch / coarse-pointer devices have no hover — keep checkboxes AND the
2039
- per-row action buttons (rename/delete/download) visible so the file manager
2040
- is fully reachable without a pointer (e.g. an iPad in landscape). */
2155
+ /* Touch / coarse-pointer devices have no hover — keep the per-row action
2156
+ buttons (rename/delete/download) visible so the file manager is fully
2157
+ reachable without a pointer (e.g. an iPad in landscape). */
2041
2158
  @media (hover: none), (pointer: coarse) {
2042
- .ds-247420 .ds-file-check { opacity: 1; }
2043
2159
  .ds-247420 .ds-file-actions { opacity: 1; }
2044
2160
  }
2045
- .ds-247420 .ds-file-check.on { background: var(--accent); border-color: var(--accent); }
2046
- .ds-247420 .ds-file-row.selected {
2047
- background: var(--accent-tint);
2048
- border-color: var(--accent);
2049
- }
2050
- .ds-247420 .ds-file-row.selected:hover { background: color-mix(in oklab, var(--accent) 22%, var(--bg)); }
2051
-
2052
- .ds-247420 .ds-bulk-bar {
2053
- display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2);
2054
- padding: 10px 14px; border-radius: var(--r-2);
2055
- background: var(--accent-tint);
2056
- border: var(--bw-hair) solid var(--accent);
2057
- position: sticky; top: var(--space-2); z-index: 2;
2058
- }
2059
- .ds-247420 .ds-bulk-count {
2060
- font-weight: 600; font-size: var(--fs-sm); margin-right: auto;
2061
- }
2062
2161
 
2063
2162
  /* Keyboard-shortcuts hint — compact two-column legend. */
2064
2163
  .ds-247420 .ds-shortcuts-hint {
@@ -2101,6 +2200,13 @@
2101
2200
  font-family: var(--ff-mono); font-size: var(--fs-xs);
2102
2201
  display: inline-flex; align-items: center; gap: 6px;
2103
2202
  }
2203
+ /* CSS-drawn half-disc mark on the compact theme toggle: keeps the control
2204
+ legible when its text label is hidden (icon-only rail strip). */
2205
+ .ds-247420 .ds-theme-disc {
2206
+ flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%;
2207
+ border: var(--bw-hair) solid var(--fg-3);
2208
+ background: linear-gradient(90deg, var(--fg-3) 0 50%, transparent 50% 100%);
2209
+ }
2104
2210
 
2105
2211
  /* ============================================================
2106
2212
  Chat kit polish — styles every class emitted by Chat /
@@ -2281,10 +2387,10 @@
2281
2387
  .ds-247420 .chat-bubble.chat-code .token.atrule,
2282
2388
  .ds-247420 .chat-bubble.chat-code .token.selector { color: var(--accent); }
2283
2389
  .ds-247420 .chat-bubble.chat-code .token.string,
2284
- .ds-247420 .chat-bubble.chat-code .token.attr-value { color: var(--mascot); }
2390
+ .ds-247420 .chat-bubble.chat-code .token.attr-value { color: var(--code-str-alt, var(--mascot)); }
2285
2391
  .ds-247420 .chat-bubble.chat-code .token.comment { color: var(--fg-3); font-style: italic; }
2286
2392
  .ds-247420 .chat-bubble.chat-code .token.number,
2287
- .ds-247420 .chat-bubble.chat-code .token.boolean { color: var(--sun); }
2393
+ .ds-247420 .chat-bubble.chat-code .token.boolean { color: var(--code-num, var(--sun)); }
2288
2394
  .ds-247420 .chat-bubble.chat-code .token.punctuation { color: var(--fg-2); }
2289
2395
  .ds-247420 .chat-bubble.chat-code .token.property,
2290
2396
  .ds-247420 .chat-bubble.chat-code .token.attr-name { color: var(--sky); }
@@ -2453,7 +2559,9 @@
2453
2559
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--space-2);
2454
2560
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
2455
2561
  background: var(--bg);
2456
- border: var(--bw-hair) solid var(--rule);
2562
+ /* The composer sits bg-on-bg: the 14% --rule hairline is ~1.3:1 on paper,
2563
+ leaving the primary input near-invisible at rest - use the strong rule. */
2564
+ border: var(--bw-hair) solid var(--rule-strong);
2457
2565
  border-radius: var(--r-2);
2458
2566
  flex-shrink: 0;
2459
2567
  transition: border-color var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease);
@@ -2467,7 +2575,9 @@
2467
2575
  background: none; color: var(--fg);
2468
2576
  border: none; border-radius: 0;
2469
2577
  font-family: inherit; font-size: var(--fs-sm);
2470
- line-height: 1.45; resize: none;
2578
+ /* 1.5 is the value that actually renders (a later polish block used to
2579
+ re-declare it; the sizing block now states the truth). */
2580
+ line-height: 1.5; resize: none;
2471
2581
  min-height: 28px; max-height: 200px;
2472
2582
  box-sizing: border-box; overflow-y: auto;
2473
2583
  scrollbar-width: thin;
@@ -2534,13 +2644,19 @@
2534
2644
  /* ── select primitive ─────────────────────────────────────────────────── */
2535
2645
  .ds-247420 .ds-select {
2536
2646
  width: 100%;
2537
- padding: 10px 14px;
2647
+ min-width: 0;
2648
+ padding: 10px 30px 10px 14px; /* right gap clears the chevron */
2538
2649
  background: var(--bg-2);
2539
2650
  border: 0;
2540
2651
  border-radius: var(--r-2);
2541
2652
  font-family: inherit;
2542
2653
  font-size: var(--fs-sm);
2543
2654
  color: var(--fg);
2655
+ /* Clip long option text gracefully - a select that cuts 'Claude Sonnet
2656
+ (latest' mid-parenthesis reads as broken; ellipsis reads as truncated. */
2657
+ text-overflow: ellipsis;
2658
+ white-space: nowrap;
2659
+ overflow: hidden;
2544
2660
  appearance: none;
2545
2661
  background-image: linear-gradient(45deg, transparent 50%, var(--fg-3) 50%),
2546
2662
  linear-gradient(135deg, var(--fg-3) 50%, transparent 50%);
@@ -2549,15 +2665,12 @@
2549
2665
  background-repeat: no-repeat;
2550
2666
  cursor: pointer;
2551
2667
  }
2552
- .ds-247420 .ds-select:focus { box-shadow: inset 0 0 0 2px var(--accent); }
2668
+ .ds-247420 .ds-select:focus-visible { box-shadow: inset 0 0 0 2px var(--accent); }
2553
2669
  .ds-247420 .ds-select:hover { background-color: var(--bg-3); }
2554
2670
 
2555
- /* ── chat composer autogrow polish ────────────────────────────────────── */
2671
+ /* ── chat composer autogrow polish (sizing lives in the primary block) ── */
2556
2672
  .ds-247420 .chat-composer textarea {
2557
- resize: none;
2558
- overflow-y: auto;
2559
2673
  transition: height var(--dur-snap) var(--ease);
2560
- line-height: 1.5;
2561
2674
  }
2562
2675
  .ds-247420 .chat-composer textarea:disabled {
2563
2676
  opacity: 0.5;
@@ -3451,36 +3564,109 @@
3451
3564
  .ds-247420 .ws-pane-toggle:hover { background: var(--bg-3); color: var(--fg); }
3452
3565
  .ds-247420 .ws-pane-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
3453
3566
 
3454
- /* Responsive: below 900px collapse to a single content column; rail+sessions+pane
3455
- become overlay drawers the host can toggle, or simply hide on mobile. We keep it
3456
- honest: stack rail (icon row) over content, hide sessions+pane unless toggled. */
3567
+ /* Drawer toggles and the scrim are hidden by default and revealed by the staged
3568
+ media blocks BELOW - these base rules must precede those blocks in source
3569
+ order: at equal specificity the later rule wins regardless of media, so a
3570
+ trailing display:none silently kills every drawer affordance (shipped bug:
3571
+ the mobile drawers were dead because these lines used to sit last). */
3572
+ .ds-247420 .ws-drawer-toggle { display: none; align-items: center; justify-content: center; width: 40px; height: 40px; border: none; background: none; color: var(--fg-2); cursor: pointer; border-radius: var(--r-1); }
3573
+ .ds-247420 .ws-scrim { display: none; }
3574
+
3575
+ /* Responsive: the columns yield to the CONTENT in stages - the main column is
3576
+ the product, so the right pane gives way first, the sessions list second,
3577
+ and only below 900px does the rail itself drop to a fixed icon strip. Yielded
3578
+ columns stay reachable as overlay drawers (.ws-pane-open / .ws-sessions-open,
3579
+ toggled from the crumb bar) over a shared fade scrim. Before this staging the
3580
+ 4-track grid survived down to 901px and crushed the chat thread to ~245px
3581
+ while the 320px context pane kept its full width. */
3582
+
3583
+ /* Stage 1 (<=1480px): drop the pane TRACK; the context pane becomes a right
3584
+ overlay drawer. */
3585
+ @media (max-width: 1480px) {
3586
+ .ds-247420 .ws-shell,
3587
+ .ds-247420 .ws-shell.ws-no-pane,
3588
+ .ds-247420 .ws-shell.ws-pane-collapsed,
3589
+ .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed:not(.ws-no-sessions) {
3590
+ grid-template-columns: var(--ws-rail-w) var(--ws-sessions-w) minmax(0, 1fr);
3591
+ grid-template-areas: "rail sessions content";
3592
+ }
3593
+ .ds-247420 .ws-shell.ws-no-sessions,
3594
+ .ds-247420 .ws-shell.ws-no-pane.ws-no-sessions,
3595
+ .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed.ws-no-sessions {
3596
+ grid-template-columns: var(--ws-rail-w) minmax(0, 1fr);
3597
+ grid-template-areas: "rail content";
3598
+ }
3599
+ /* Drawer width is a literal: --ws-pane-w is 0px while pane-collapsed, and a
3600
+ desktop-collapsed pane must still open as a full drawer. */
3601
+ .ds-247420 .ws-pane {
3602
+ position: fixed; inset: 0 0 0 auto;
3603
+ width: min(340px, 85vw);
3604
+ z-index: 42; transform: translateX(110%);
3605
+ transition: transform var(--dur-base) var(--ease);
3606
+ }
3607
+ .ds-247420 .ws-shell.ws-pane-open .ws-pane { transform: translateX(0); width: min(340px, 85vw); }
3608
+ .ds-247420 .ws-shell.ws-pane-open.ws-pane-collapsed .ws-pane { border-left: var(--bw-hair) solid var(--bg-3); }
3609
+ .ds-247420 .ws-shell.ws-pane-open.ws-pane-collapsed .ws-pane > :not(.ws-pane-toggle) { display: revert; }
3610
+ /* The desktop collapse chevron is meaningless in drawer mode. */
3611
+ .ds-247420 .ws-pane-toggle { display: none; }
3612
+ .ds-247420 .ws-pane-drawer-toggle { display: inline-flex; }
3613
+ /* Scrim is always present from this stage down so it FADES with the drawer
3614
+ instead of hard-appearing; pointer-events gate keeps it inert while closed. */
3615
+ .ds-247420 .ws-scrim { display: block; opacity: 0; pointer-events: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); transition: opacity var(--dur-base) var(--ease); }
3616
+ .ds-247420 .ws-shell.ws-sessions-open .ws-scrim, .ds-247420 .ws-shell.ws-pane-open .ws-scrim { opacity: 1; pointer-events: auto; }
3617
+ }
3618
+
3619
+ /* Stage 2 (<=1100px): drop the sessions TRACK; the conversation list becomes a
3620
+ left overlay drawer. */
3621
+ @media (max-width: 1100px) {
3622
+ .ds-247420 .ws-shell,
3623
+ .ds-247420 .ws-shell.ws-no-pane,
3624
+ .ds-247420 .ws-shell.ws-pane-collapsed,
3625
+ .ds-247420 .ws-shell.ws-no-sessions,
3626
+ .ds-247420 .ws-shell.ws-no-pane.ws-no-sessions,
3627
+ .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed:not(.ws-no-sessions),
3628
+ .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed.ws-no-sessions {
3629
+ grid-template-columns: var(--ws-rail-w) minmax(0, 1fr);
3630
+ grid-template-areas: "rail content";
3631
+ }
3632
+ .ds-247420 .ws-sessions {
3633
+ position: fixed; inset: 0 auto 0 0;
3634
+ width: min(var(--ws-sessions-w), 80vw);
3635
+ z-index: 42; transform: translateX(-110%);
3636
+ transition: transform var(--dur-base) var(--ease);
3637
+ border-right: var(--bw-hair) solid var(--bg-3);
3638
+ }
3639
+ .ds-247420 .ws-shell.ws-sessions-open .ws-sessions { transform: translateX(0); }
3640
+ .ds-247420 .ws-sessions-drawer-toggle { display: inline-flex; }
3641
+ }
3642
+
3643
+ /* Stage 3 (<=900px): single content column; the rail drops to a fixed icon-only
3644
+ strip. Labels hide UNCONDITIONALLY here - a 60px rail showing clipped label
3645
+ text ('age', 'Ne') is the worst of both worlds. */
3457
3646
  @media (max-width: 900px) {
3458
3647
  .ds-247420 .ws-shell,
3459
3648
  .ds-247420 .ws-shell.ws-no-sessions,
3460
3649
  .ds-247420 .ws-shell.ws-no-pane,
3461
- .ds-247420 .ws-shell.ws-no-pane.ws-no-sessions {
3462
- grid-template-columns: 1fr;
3650
+ .ds-247420 .ws-shell.ws-pane-collapsed,
3651
+ .ds-247420 .ws-shell.ws-no-pane.ws-no-sessions,
3652
+ .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed:not(.ws-no-sessions),
3653
+ .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed.ws-no-sessions {
3654
+ grid-template-columns: minmax(0, 1fr);
3463
3655
  grid-template-areas: "content";
3464
3656
  }
3465
3657
  .ds-247420 .ws-rail { position: fixed; inset: 0 auto 0 0; width: var(--ws-rail-w-collapsed); z-index: 40; }
3466
- .ds-247420 .ws-sessions { position: fixed; inset: 0 auto 0 var(--ws-rail-w-collapsed); width: min(var(--ws-sessions-w), 80vw); z-index: 42; transform: translateX(-110%); transition: transform var(--dur-base) var(--ease); }
3467
- .ds-247420 .ws-shell.ws-sessions-open .ws-sessions { transform: translateX(0); }
3468
- /* On mobile the pane is a drawer driven by .ws-pane-open (an explicit open
3469
- intent), NOT by :not(.ws-pane-collapsed) - the desktop collapse default is
3470
- "open" which would otherwise pop the pane over the thread on every load. */
3471
- .ds-247420 .ws-pane { position: fixed; inset: 0 0 0 auto; width: min(var(--ws-pane-w), 85vw); z-index: 42; transform: translateX(110%); transition: transform var(--dur-base) var(--ease); }
3472
- .ds-247420 .ws-shell.ws-pane-open .ws-pane { transform: translateX(0); }
3658
+ .ds-247420 .ws-rail .ws-rail-brand,
3659
+ .ds-247420 .ws-rail .ws-rail-action-label,
3660
+ .ds-247420 .ws-rail .ws-rail-item-label,
3661
+ .ds-247420 .ws-rail .ws-rail-item-count,
3662
+ .ds-247420 .ws-rail .ds-theme-toggle-label { display: none; }
3663
+ .ds-247420 .ws-rail .ws-rail-item, .ds-247420 .ws-rail .ws-rail-action { justify-content: center; gap: 0; }
3664
+ .ds-247420 .ws-rail .ws-rail-head { justify-content: center; }
3665
+ /* Expand/collapse is meaningless on the icon strip. */
3666
+ .ds-247420 .ws-rail-toggle { display: none; }
3667
+ .ds-247420 .ws-rail-foot { display: flex; justify-content: center; }
3668
+ .ds-247420 .ws-sessions { inset: 0 auto 0 var(--ws-rail-w-collapsed); }
3473
3669
  .ds-247420 .ws-content { grid-area: content; padding-left: var(--ws-rail-w-collapsed); }
3474
- .ds-247420 .ws-rail-collapsed .ws-rail-item-label, .ds-247420 .ws-rail-collapsed .ws-rail-brand { display: none; }
3475
- /* Tap-scrim behind an open drawer; dismiss on click. Hidden unless a drawer
3476
- is open so it never blocks the content area on desktop. */
3477
- /* Scrim is always present on mobile so it can FADE with the drawer instead of
3478
- hard-appearing via a display toggle; pointer-events gate keeps it inert
3479
- while closed. Reduced-motion users get the global transition kill -> instant. */
3480
- .ds-247420 .ws-scrim { display: block; opacity: 0; pointer-events: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); transition: opacity var(--dur-base) var(--ease); }
3481
- .ds-247420 .ws-shell.ws-sessions-open .ws-scrim, .ds-247420 .ws-shell.ws-pane-open .ws-scrim { opacity: 1; pointer-events: auto; }
3482
- /* The mobile drawer-toggle affordances live in the crumb bar. */
3483
- .ds-247420 .ws-drawer-toggle { display: inline-flex; }
3484
3670
  /* The Crumb's narrow collapse elsewhere keys on the .app @container, which
3485
3671
  does not exist inside WorkspaceShell - mirror it here so the crumb bar
3486
3672
  cannot overflow a narrow viewport (trail hides, leaf ellipsizes, the
@@ -3491,11 +3677,8 @@
3491
3677
  .ds-247420 .ws-crumb .app-crumb .leaf { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
3492
3678
  .ds-247420 .ws-crumb .app-crumb .crumb-right { margin-left: 0; flex-wrap: wrap; min-width: 0; display: inline-flex; }
3493
3679
  }
3494
- /* Drawer toggles are mobile-only chrome; hidden on the desktop grid. */
3495
- .ds-247420 .ws-drawer-toggle { display: none; align-items: center; justify-content: center; width: 40px; height: 40px; border: none; background: none; color: var(--fg-2); cursor: pointer; border-radius: var(--r-1); }
3496
3680
  .ds-247420 .ws-drawer-toggle:hover { background: var(--bg-2); color: var(--fg); }
3497
3681
  .ds-247420 .ws-drawer-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
3498
- .ds-247420 .ws-scrim { display: none; }
3499
3682
 
3500
3683
  /* ============================================================
3501
3684
  Row title highlight, expanded-row actions, filter pills.
@@ -5090,6 +5273,13 @@
5090
5273
  .ds-247420 .agentchat-controls .select,
5091
5274
  .ds-247420 .agentchat-controls [role="combobox"] { min-width: 130px; max-width: 240px; }
5092
5275
  .ds-247420 .agentchat-controls .ds-select { min-width: 130px; max-width: 240px; }
5276
+ /* One shared control metric for the most-seen chrome row (mirrors the
5277
+ .ds-dash-toolbar precedent): selects, buttons, export acts all 32px / r-1. */
5278
+ .ds-247420 .agentchat-controls .ds-select { min-height: 32px; padding: 4px 28px 4px 10px; font-size: var(--fs-sm); border-radius: var(--r-1); }
5279
+ .ds-247420 .agentchat-controls .btn, .ds-247420 .agentchat-controls .btn-primary { padding: 5px 12px; min-height: 32px; border-radius: var(--r-1); font-weight: 500; }
5280
+ @media (pointer: coarse) {
5281
+ .ds-247420 .agentchat-controls .ds-select, .ds-247420 .agentchat-controls .btn, .ds-247420 .agentchat-controls .btn-primary { min-height: 44px; }
5282
+ }
5093
5283
 
5094
5284
  /* Narrow viewports: let the agent/model selects share the row two-up, then
5095
5285
  stack full-width on the smallest screens, and drop the status to its own
@@ -5112,7 +5302,7 @@
5112
5302
  gap: .4em;
5113
5303
  white-space: nowrap;
5114
5304
  margin-left: auto;
5115
- font-size: .85em;
5305
+ font-size: var(--fs-tiny);
5116
5306
  color: var(--fg-3);
5117
5307
  }
5118
5308
  /* status disc — a CSS-drawn dot, not a glyph; pulses while streaming */
@@ -5138,7 +5328,7 @@
5138
5328
  display: flex;
5139
5329
  align-items: center;
5140
5330
  gap: var(--space-2, 8px);
5141
- font-size: .85em;
5331
+ font-size: var(--fs-tiny);
5142
5332
  color: var(--fg-3);
5143
5333
  flex-wrap: wrap;
5144
5334
  }
@@ -5179,7 +5369,7 @@
5179
5369
  gap: .5em;
5180
5370
  }
5181
5371
  .ds-247420 .agentchat-title { font-size: 1em; margin: 0; }
5182
- .ds-247420 .agentchat-sub { font-size: .85em; color: var(--fg-3); }
5372
+ .ds-247420 .agentchat-sub { font-size: var(--fs-tiny); color: var(--fg-3); }
5183
5373
  /* Thread wrapper hosts the absolutely-positioned jump-to-latest button. */
5184
5374
  .ds-247420 .agentchat-thread-wrap { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
5185
5375
  .ds-247420 .agentchat-thread {
@@ -5195,7 +5385,7 @@
5195
5385
  .ds-247420 .agentchat-jump {
5196
5386
  position: absolute; right: 16px; bottom: 12px; z-index: 3;
5197
5387
  display: none; align-items: center; gap: .35em;
5198
- padding: .4em .8em; font: inherit; font-size: .8em; cursor: pointer;
5388
+ padding: .4em .8em; font: inherit; font-size: var(--fs-tiny); cursor: pointer;
5199
5389
  border-radius: 999px; border: var(--bw-hair) solid var(--rule);
5200
5390
  background: var(--bg-2); color: var(--fg-2, var(--fg));
5201
5391
  box-shadow: 0 2px 8px color-mix(in srgb, var(--fg) 14%, transparent);
@@ -5239,7 +5429,7 @@
5239
5429
  max-width: 46ch;
5240
5430
  }
5241
5431
  .ds-247420 .agentchat-empty-title { margin: 0; font-size: 1.05em; color: var(--fg-2, var(--fg)); }
5242
- .ds-247420 .agentchat-empty-sub { margin: 0; font-size: .9em; }
5432
+ .ds-247420 .agentchat-empty-sub { margin: 0; font-size: var(--fs-sm); }
5243
5433
  .ds-247420 .agentchat-empty-suggestions {
5244
5434
  display: flex;
5245
5435
  flex-wrap: wrap;
@@ -5250,7 +5440,7 @@
5250
5440
  .ds-247420 .agentchat-empty-suggestion {
5251
5441
  cursor: pointer;
5252
5442
  font: inherit;
5253
- font-size: .85em;
5443
+ font-size: var(--fs-tiny);
5254
5444
  padding: .4em .8em;
5255
5445
  border-radius: 999px;
5256
5446
  border: 1px solid color-mix(in srgb, var(--fg) 16%, transparent);
@@ -5270,7 +5460,7 @@
5270
5460
  text-align: left;
5271
5461
  width: 100%;
5272
5462
  }
5273
- .ds-247420 .agentchat-install-text { margin: 0; font-size: .9em; color: var(--fg-3); }
5463
+ .ds-247420 .agentchat-install-text { margin: 0; font-size: var(--fs-sm); color: var(--fg-3); }
5274
5464
  .ds-247420 .agentchat-install-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--space-1, 4px); }
5275
5465
  .ds-247420 .agentchat-install-row {
5276
5466
  display: flex; align-items: center; gap: var(--space-2, 8px);
@@ -5311,7 +5501,7 @@
5311
5501
  gap: .5em;
5312
5502
  padding: .3em .2em;
5313
5503
  color: var(--fg-3);
5314
- font-size: .85em;
5504
+ font-size: var(--fs-tiny);
5315
5505
  }
5316
5506
  .ds-247420 .agentchat-working-text { color: var(--fg-3); }
5317
5507
  /* Self-contained dots (chat-thinking-dots lives in a kit sheet not bundled
@@ -5374,28 +5564,40 @@
5374
5564
  ConversationList — left-rail "Chats" column.
5375
5565
  ---------------------------------------------------------------------------- */
5376
5566
  .ds-247420 .ds-sessions { display: flex; flex-direction: column; min-height: 0; height: 100%; }
5377
- .ds-247420 .ds-session-head { flex: 0 0 auto; display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3); border-bottom: var(--bw-hair) solid var(--bg-3); }
5567
+ /* One row: quiet icon new-chat beside the search. The list's new-chat must not
5568
+ repeat the rail's primary CTA - two identical green buttons on screen at
5569
+ once read as a layout mistake, and the rail action already owns 'new'. */
5570
+ .ds-247420 .ds-session-head { flex: 0 0 auto; display: flex; flex-direction: row; align-items: center; gap: var(--space-2); padding: var(--space-3); border-bottom: var(--bw-hair) solid var(--bg-3); }
5378
5571
  .ds-247420 .ds-session-new {
5379
- display: flex; align-items: center; gap: var(--space-2); justify-content: center;
5380
- padding: var(--space-2) var(--space-3); min-height: 44px;
5381
- background: var(--accent); color: var(--accent-fg, var(--bg)); border: none;
5572
+ display: inline-flex; align-items: center; justify-content: center; gap: 0;
5573
+ flex: 0 0 auto; order: 2;
5574
+ width: 36px; min-height: 36px; padding: 0;
5575
+ background: transparent; color: var(--fg-2);
5576
+ border: var(--bw-hair) solid var(--rule);
5382
5577
  border-radius: var(--r-1); cursor: pointer; font-family: var(--ff-body);
5383
- font-size: var(--fs-sm); font-weight: 600;
5578
+ font-size: var(--fs-sm); font-weight: 500;
5384
5579
  }
5385
- .ds-247420 .ds-session-new:hover { filter: brightness(1.08); }
5580
+ .ds-247420 .ds-session-new > span { display: none; }
5581
+ .ds-247420 .ds-session-new:hover { background: var(--bg-2); color: var(--fg); }
5582
+ .ds-247420 .ds-session-search { order: 1; flex: 1 1 auto; min-width: 0; }
5386
5583
  .ds-247420 .ds-session-new:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
5387
5584
  .ds-247420 .ds-session-search {
5388
- width: 100%; padding: var(--space-2) var(--space-3); min-height: 44px;
5585
+ width: 100%; padding: var(--space-1) var(--space-3); min-height: 36px;
5389
5586
  background: var(--bg-2); border: var(--bw-hair) solid var(--bg-3); color: var(--fg);
5390
5587
  border-radius: var(--r-1); font-family: var(--ff-body); font-size: var(--fs-sm);
5391
5588
  }
5392
- .ds-247420 .ds-session-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
5589
+ .ds-247420 .ds-session-search:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent); }
5590
+ /* Touch floor (must FOLLOW the base rules - same specificity, order decides). */
5591
+ @media (pointer: coarse) {
5592
+ .ds-247420 .ds-session-new { width: 44px; min-height: 44px; }
5593
+ .ds-247420 .ds-session-search { min-height: 44px; }
5594
+ }
5393
5595
  .ds-247420 .ds-session-list, .ds-247420 .ds-session-groups { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-2); }
5394
5596
  /* Grouped rows (Today/Yesterday/...) lay out like the flat list; the section
5395
5597
  label sticks to the top of the scroll area for Claude-Desktop-style headers. */
5396
5598
  .ds-247420 .ds-session-group { display: flex; flex-direction: column; }
5397
5599
  .ds-247420 .ds-session-group-rows { display: flex; flex-direction: column; gap: 2px; }
5398
- .ds-247420 .ds-session-group-label { position: sticky; top: 0; z-index: 1; background: var(--bg-1, var(--bg)); font-size: var(--fs-tiny); color: var(--fg-3); text-transform: uppercase; letter-spacing: .04em; padding: var(--space-2) var(--space-2) var(--space-1); }
5600
+ .ds-247420 .ds-session-group-label { position: sticky; top: 0; z-index: 1; background: var(--bg-1, var(--bg)); font-size: var(--fs-tiny); font-weight: 600; color: var(--fg-3); text-transform: uppercase; letter-spacing: var(--tr-caps); padding: var(--space-2) var(--space-2) var(--space-1); }
5399
5601
  .ds-247420 .ds-session-row {
5400
5602
  position: relative; display: flex; align-items: center; gap: var(--space-2);
5401
5603
  width: 100%; padding: var(--space-2); min-height: 52px; margin-bottom: 2px;
@@ -5426,9 +5628,22 @@
5426
5628
  SessionDashboard — grid of live-session cards.
5427
5629
  ---------------------------------------------------------------------------- */
5428
5630
  .ds-247420 .ds-dash { display: flex; flex-direction: column; min-height: 0; }
5429
- .ds-247420 .ds-dash-header { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4) 0; }
5631
+ .ds-247420 .ds-dash-header { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-3); row-gap: var(--space-2); flex-wrap: wrap; padding: var(--space-3) var(--space-4) 0; }
5430
5632
  .ds-247420 .ds-dash-count { font-size: var(--fs-sm); color: var(--fg-2); font-weight: 600; }
5431
- .ds-247420 .ds-dash-header .btn, .ds-247420 .ds-dash-header .btn-primary { margin-left: auto; }
5633
+ /* Stop is a quiet destructive control in chrome, not a page-level red CTA;
5634
+ it only goes loud while ARMED (the one-shot press-again confirm). */
5635
+ .ds-247420 .ds-dash-header .btn, .ds-247420 .ds-dash-header .btn-primary {
5636
+ margin-left: 0;
5637
+ padding: 5px 12px; min-height: 32px; border-radius: var(--r-1); font-weight: 500;
5638
+ }
5639
+ .ds-247420 .ds-dash-header .btn-primary.danger {
5640
+ background: transparent; color: var(--warn);
5641
+ border: var(--bw-hair) solid var(--warn);
5642
+ }
5643
+ .ds-247420 .ds-dash-header .btn-primary.danger:hover {
5644
+ background: color-mix(in oklab, var(--warn) 12%, transparent); color: var(--warn);
5645
+ }
5646
+ .ds-247420 .ds-dash-header .btn-primary.danger.is-armed { background: var(--warn); color: var(--paper); border-color: var(--warn); }
5432
5647
  .ds-247420 .ds-dash-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-3); padding: var(--space-4); }
5433
5648
  .ds-247420 .ds-dash-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3); background: var(--bg-2); border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-2); }
5434
5649
  .ds-247420 .ds-dash-card.is-error { border-color: var(--flame); }
@@ -5455,7 +5670,6 @@
5455
5670
  ---------------------------------------------------------------------------- */
5456
5671
  .ds-247420 .ds-context { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-3); }
5457
5672
  .ds-247420 .ds-context .panel { background: var(--bg-2); border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-2); }
5458
- .ds-247420 .ds-context .row { font-size: var(--fs-sm); }
5459
5673
  .ds-247420 .ds-context .row .meta { font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-2); }
5460
5674
  .ds-247420 .ds-context .row .sub { font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
5461
5675
  .ds-247420 .ds-context-actions { display: flex; gap: var(--space-2); }
@@ -5508,7 +5722,18 @@
5508
5722
  .ds-247420 .ds-dash-status.is-running { color: var(--accent); }
5509
5723
 
5510
5724
  /* --- C2: dashboard sort/filter toolbar + stream-state line. --- */
5725
+ /* The toolbar is part of the ONE header row (count | heartbeat ... filter,
5726
+ sort, errors-only, stop): compact controls that align on a shared 32px
5727
+ height, never a stacked full-width form column. */
5511
5728
  .ds-247420 .ds-dash-toolbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
5729
+ .ds-247420 .ds-dash-toolbar .ds-search-input {
5730
+ width: 200px; min-height: 32px; padding: 5px 10px;
5731
+ font-size: var(--fs-sm); border-radius: var(--r-1);
5732
+ }
5733
+ .ds-247420 .ds-dash-toolbar .ds-select, .ds-247420 .ds-dash-toolbar select {
5734
+ min-height: 32px; padding: 4px 10px; font-size: var(--fs-sm);
5735
+ width: auto; border-radius: var(--r-1);
5736
+ }
5512
5737
  .ds-247420 .ds-dash-stream { font-size: var(--fs-tiny); color: var(--fg-3); }
5513
5738
  .ds-247420 .ds-dash-stream.is-lost { color: var(--flame); }
5514
5739
  .ds-247420 .ds-dash-stream.is-connecting { color: var(--amber, #d9a93a); }
@@ -5719,7 +5944,7 @@
5719
5944
  .ds-247420 .chat-msg-flat.you { background: none; }
5720
5945
  .ds-247420 .chat-msg-flat .chat-stack { max-width: var(--measure); width: 100%; margin: 0; align-items: stretch; }
5721
5946
  .ds-247420 .chat-msg-flat.you .chat-stack { align-items: stretch; }
5722
- .ds-247420 .chat-role { font-size: var(--fs-tiny); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); margin-bottom: var(--space-1); }
5947
+ .ds-247420 .chat-role { font-size: var(--fs-tiny); font-weight: 600; text-transform: uppercase; letter-spacing: var(--tr-caps); color: var(--fg-3); margin-bottom: var(--space-1); }
5723
5948
  .ds-247420 .chat-msg-flat.you .chat-role { color: var(--accent); }
5724
5949
  .ds-247420 .chat-msg-flat .chat-bubble { background: none; border: none; border-radius: 0; padding: 0; max-width: 100%; box-shadow: none; transform: none; }
5725
5950
  .ds-247420 .chat-msg-flat.you .chat-bubble { background: none; color: inherit; }
@@ -5760,7 +5985,7 @@
5760
5985
  .ds-247420 .chat-msg .chat-tool.tool-error .chat-tool-status { color: var(--flame); background: color-mix(in oklab, var(--flame) 12%, transparent); }
5761
5986
  .ds-247420 .chat-tool-body { border-top: var(--bw-hair) solid var(--rule); padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
5762
5987
  .ds-247420 .chat-tool-section { display: flex; flex-direction: column; gap: var(--space-1); }
5763
- .ds-247420 .chat-tool-section-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-3); }
5988
+ .ds-247420 .chat-tool-section-label { font-size: var(--fs-tiny); font-weight: 600; text-transform: uppercase; letter-spacing: var(--tr-caps); color: var(--fg-3); }
5764
5989
  .ds-247420 .chat-tool-pre { margin: 0; padding: var(--space-2); background: var(--bg-2); border-radius: var(--r-1); font-family: var(--ff-mono); font-size: var(--fs-tiny); line-height: 1.45; overflow-x: auto; max-height: 320px; overflow-y: auto; }
5765
5990
  .ds-247420 .chat-tool-pre.is-error { color: var(--flame); }
5766
5991
  .ds-247420 .chat-tool-pre.chat-tool-empty { color: var(--fg-3); }
@@ -5799,7 +6024,7 @@
5799
6024
 
5800
6025
  /* Live command-center: status-bucket groups + header breakdown + heartbeat. */
5801
6026
  .ds-247420 .ds-dash-group { display: flex; flex-direction: column; gap: var(--space-2); }
5802
- .ds-247420 .ds-dash-group-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); padding: 0 var(--space-1); }
6027
+ .ds-247420 .ds-dash-group-label { font-size: var(--fs-tiny); font-weight: 600; text-transform: uppercase; letter-spacing: var(--tr-caps); color: var(--fg-3); padding: 0 var(--space-1); }
5803
6028
  .ds-247420 .ds-dash-breakdown { display: flex; align-items: center; gap: var(--space-1); font-size: var(--fs-sm); color: var(--fg-2); }
5804
6029
  .ds-247420 .ds-dash-breakdown .seg.is-running { color: var(--green); font-weight: 600; }
5805
6030
  .ds-247420 .ds-dash-breakdown .seg.is-error { color: var(--flame); font-weight: 600; }
@@ -5825,9 +6050,9 @@
5825
6050
  .ds-247420 .ds-preview-code .token.comment, .ds-247420 .ds-preview-code .token.prolog, .ds-247420 .ds-preview-code .token.doctype, .ds-247420 .ds-preview-code .token.cdata { color: var(--fg-3); }
5826
6051
  .ds-247420 .ds-preview-code .token.punctuation { color: var(--fg-2); }
5827
6052
  .ds-247420 .ds-preview-code .token.property, .ds-247420 .ds-preview-code .token.tag, .ds-247420 .ds-preview-code .token.boolean, .ds-247420 .ds-preview-code .token.number, .ds-247420 .ds-preview-code .token.constant, .ds-247420 .ds-preview-code .token.symbol { color: var(--purple-2, #7F18A4); }
5828
- .ds-247420 .ds-preview-code .token.selector, .ds-247420 .ds-preview-code .token.attr-name, .ds-247420 .ds-preview-code .token.string, .ds-247420 .ds-preview-code .token.char, .ds-247420 .ds-preview-code .token.builtin { color: var(--green-2, #3A9A34); }
5829
- .ds-247420 .ds-preview-code .token.atrule, .ds-247420 .ds-preview-code .token.attr-value, .ds-247420 .ds-preview-code .token.keyword { color: var(--sky, #3A6EFF); }
5830
- .ds-247420 .ds-preview-code .token.function, .ds-247420 .ds-preview-code .token.class-name { color: var(--flame); }
6053
+ .ds-247420 .ds-preview-code .token.selector, .ds-247420 .ds-preview-code .token.attr-name, .ds-247420 .ds-preview-code .token.string, .ds-247420 .ds-preview-code .token.char, .ds-247420 .ds-preview-code .token.builtin { color: var(--code-string, var(--green)); }
6054
+ .ds-247420 .ds-preview-code .token.atrule, .ds-247420 .ds-preview-code .token.attr-value, .ds-247420 .ds-preview-code .token.keyword { color: var(--code-keyword, var(--sky)); }
6055
+ .ds-247420 .ds-preview-code .token.function, .ds-247420 .ds-preview-code .token.class-name { color: var(--code-fn, var(--flame)); }
5831
6056
  .ds-247420 .ds-preview-code.has-gutter { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--space-2); }
5832
6057
  .ds-247420 .ds-preview-code.has-gutter code { display: block; min-width: 0; overflow-x: auto; }
5833
6058
  .ds-247420 .ds-preview-gutter { user-select: none; text-align: right; padding: 0 var(--space-2) 0 0; color: var(--fg-3); border-right: var(--bw-hair) solid var(--rule); font-family: var(--ff-mono); white-space: pre; line-height: inherit; }
@@ -5840,6 +6065,36 @@
5840
6065
  }
5841
6066
  .ds-247420 .ds-preview-media.is-actual { max-width: none; max-height: none; }
5842
6067
 
6068
+ /* ----------------------------------------------------------------------------
6069
+ Compact-button tiers — ONE spec for the small quiet rect buttons that eight
6070
+ surfaces used to clone with drifting metrics/tones. chat.css loads after
6071
+ app-shell.css in the bundle, so these same-specificity rules win by order.
6072
+ Tier A (toolbar-grade, 32px) matches .ds-file-toolbar .btn, the reference;
6073
+ tier B (inline-row-grade, 24px) for actions inside dense row strips.
6074
+ Hover/focus/active-state rules on the originals still apply.
6075
+ ---------------------------------------------------------------------------- */
6076
+ .ds-247420 .row-act, .ds-247420 .ds-dash-errors-toggle, .ds-247420 .agentchat-export-act, .ds-247420 .ds-file-more-btn {
6077
+ min-height: 32px; padding: 5px 12px; border-radius: var(--r-1);
6078
+ font-family: var(--ff-body); font-size: var(--fs-tiny); font-weight: 500;
6079
+ background: transparent; border: var(--bw-hair) solid var(--rule); color: var(--fg-2);
6080
+ cursor: pointer;
6081
+ }
6082
+ .ds-247420 .row-act:hover, .ds-247420 .ds-dash-errors-toggle:hover, .ds-247420 .agentchat-export-act:hover, .ds-247420 .ds-file-more-btn:hover {
6083
+ background: var(--bg-2); color: var(--fg);
6084
+ }
6085
+ .ds-247420 .agentchat-install-copy, .ds-247420 .ds-upload-act, .ds-247420 .ds-session-meta-copy {
6086
+ min-height: 24px; padding: 2px 8px; border-radius: var(--r-1);
6087
+ font-family: var(--ff-body); font-size: var(--fs-tiny);
6088
+ background: transparent; border: var(--bw-hair) solid var(--rule); color: var(--fg-3);
6089
+ cursor: pointer;
6090
+ }
6091
+ .ds-247420 .agentchat-install-copy:hover, .ds-247420 .ds-upload-act:hover, .ds-247420 .ds-session-meta-copy:hover {
6092
+ background: var(--bg-2); color: var(--fg);
6093
+ }
6094
+ @media (pointer: coarse) {
6095
+ .ds-247420 .row-act, .ds-247420 .ds-dash-errors-toggle, .ds-247420 .agentchat-export-act, .ds-247420 .ds-file-more-btn, .ds-247420 .agentchat-install-copy, .ds-247420 .ds-upload-act, .ds-247420 .ds-session-meta-copy { min-height: 44px; }
6096
+ }
6097
+
5843
6098
  /* editor-primitives.css */
5844
6099
  /* editor-primitives.css — chrome for in-engine editors, inspectors, IDEs,
5845
6100
  debug HUDs. All rules under .ds-247420 scope (build prefixes). Tokens