anentrypoint-design 0.0.380 → 0.0.382

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/app-shell.css +16 -0
  2. package/chat.css +102 -62
  3. package/colors_and_type.css +66 -7
  4. package/community.css +104 -70
  5. package/dist/247420.css +1123 -465
  6. package/dist/247420.js +32 -29
  7. package/package.json +1 -1
  8. package/src/components/content/avatar.js +31 -0
  9. package/src/components/content/charts.js +50 -0
  10. package/src/components/content/cli.js +46 -0
  11. package/src/components/content/feedback.js +77 -0
  12. package/src/components/content/fields.js +136 -0
  13. package/src/components/content/hero.js +146 -0
  14. package/src/components/content/lists.js +85 -0
  15. package/src/components/content/panel.js +79 -0
  16. package/src/components/content/row.js +115 -0
  17. package/src/components/content/table.js +97 -0
  18. package/src/components/content/views.js +81 -0
  19. package/src/components/content.js +29 -852
  20. package/src/components/editor-primitives/batch.js +60 -0
  21. package/src/components/editor-primitives/chrome.js +146 -0
  22. package/src/components/editor-primitives/collapse.js +46 -0
  23. package/src/components/editor-primitives/context-menu.js +127 -0
  24. package/src/components/editor-primitives/diagnostics.js +44 -0
  25. package/src/components/editor-primitives/focus-trap.js +26 -0
  26. package/src/components/editor-primitives/json-viewer.js +123 -0
  27. package/src/components/editor-primitives/layout.js +89 -0
  28. package/src/components/editor-primitives/modals.js +89 -0
  29. package/src/components/editor-primitives/pager.js +74 -0
  30. package/src/components/editor-primitives/property-grid.js +57 -0
  31. package/src/components/editor-primitives/shared.js +18 -0
  32. package/src/components/editor-primitives/split-panel.js +101 -0
  33. package/src/components/editor-primitives/toast.js +59 -0
  34. package/src/components/editor-primitives/tree.js +75 -0
  35. package/src/components/editor-primitives.js +35 -1048
  36. package/src/components/freddie/helpers.js +7 -0
  37. package/src/components/freddie.js +21 -21
  38. package/src/components/overlay-primitives/approval-prompt.js +38 -0
  39. package/src/components/overlay-primitives/auth-modal.js +89 -0
  40. package/src/components/overlay-primitives/command-palette.js +101 -0
  41. package/src/components/overlay-primitives/emoji-picker.js +103 -0
  42. package/src/components/overlay-primitives/floating.js +146 -0
  43. package/src/components/overlay-primitives/full-screen.js +45 -0
  44. package/src/components/overlay-primitives/menus.js +131 -0
  45. package/src/components/overlay-primitives/popover.js +51 -0
  46. package/src/components/overlay-primitives/roving-menu.js +73 -0
  47. package/src/components/overlay-primitives/settings-popover.js +85 -0
  48. package/src/components/overlay-primitives/tooltip.js +55 -0
  49. package/src/components/overlay-primitives.js +33 -855
  50. package/src/css/app-shell/base.css +11 -1
  51. package/src/css/app-shell/catalog-theme.css +7 -0
  52. package/src/css/app-shell/chat-polish.css +45 -33
  53. package/src/css/app-shell/data-density.css +46 -24
  54. package/src/css/app-shell/files.css +40 -32
  55. package/src/css/app-shell/hero-content.css +1 -1
  56. package/src/css/app-shell/kits-appended.css +456 -79
  57. package/src/css/app-shell/panel-row.css +6 -1
  58. package/src/css/app-shell/plugins-config.css +1 -1
  59. package/src/css/app-shell/responsive.css +47 -29
  60. package/src/css/app-shell/responsive2-workspace.css +17 -12
  61. package/src/css/app-shell/states-interactions.css +9 -4
  62. package/src/kits/os/freddie-dashboard.css +2 -2
  63. package/src/kits/os/launcher.css +1 -1
  64. package/src/kits/os/theme.css +359 -283
  65. package/src/kits/os/wm.css +2 -2
  66. package/src/kits/slides/deck-stage-style.js +5 -2
  67. package/src/kits/spoint/host-join-lobby.css +1 -1
  68. package/src/kits/spoint/loading-screen.css +1 -1
package/dist/247420.css CHANGED
@@ -147,6 +147,13 @@
147
147
  --ff-body: system-ui, sans-serif;
148
148
  --ff-mono: ui-monospace, Menlo, Consolas, monospace;
149
149
 
150
+ /* Sub-12px tiers exist ONLY for dense OS/data chrome — taskbar strips,
151
+ session chips, tool-call headers, file-row metadata, ID/stat columns.
152
+ Never use them for body copy or ordinary UI text: at these sizes the
153
+ system stack loses its readable x-height, so they are reserved for
154
+ glanceable, secondary, non-prose material. --fs-pico is the floor. */
155
+ --fs-pico: 10px;
156
+ --fs-nano: 11px;
150
157
  --fs-micro: 12px;
151
158
  --fs-tiny: 13px;
152
159
  --fs-xs: 14px;
@@ -247,8 +254,61 @@
247
254
  edges (panel spine, expo numbering). A literal length, not a color. */
248
255
  --ink-offset: 3px;
249
256
 
250
- --z-header: 100;
251
- --z-overlay: 1000;
257
+ /* ============================================================
258
+ Stacking scale — the ONE ordered set of layers anything may
259
+ paint into. Rungs are 100 apart so a future layer can be
260
+ inserted between two neighbours without renumbering the rest,
261
+ and so a component may locally offset (+1/+2) within its own
262
+ rung without colliding with the next one.
263
+
264
+ Order is the contract; the numbers are just how it is spelled.
265
+ Read top to bottom as "what paints over what":
266
+
267
+ --z-below -1 decorative texture UNDER its own content
268
+ (.ds-grain/.ds-halftone print layer)
269
+ --z-base 0 in-flow content; the default plane
270
+ --z-raised 100 a thing lifted above its siblings inside
271
+ one component (code-lang tab, timeline dot,
272
+ selection checkbox, resize handle)
273
+ --z-sticky 200 sticky-within-a-scroller chrome: section
274
+ labels, sticky table headers, save bars.
275
+ Above raised content it scrolls past.
276
+ --z-header 300 the app's own sticky chrome band
277
+ (.app-topbar/.app-chrome)
278
+ --z-drawer 400 off-canvas panels (sidebar/pane/session
279
+ drawers) and their scrim, which must cover
280
+ the header they slide over
281
+ --z-window 500 free-floating window-manager surfaces —
282
+ the OS kit's .wm-root canvas of draggable
283
+ windows. Above the shell, below all
284
+ transient popups.
285
+ --z-dock 600 persistent OS shell furniture that must
286
+ stay above windows: launcher dock, menubar,
287
+ taskbar, os-root
288
+ --z-dropdown 700 menus/popovers anchored to a trigger; they
289
+ must escape the dock that spawned them
290
+ --z-modal 800 blocking dialogs, lightboxes, command
291
+ palettes and their backdrops
292
+ --z-toast 900 transient notifications — above a modal,
293
+ because they report on what the modal did
294
+ --z-tooltip 1000 pointer-following hint; never blocked
295
+ --z-top 1100 last resort: boot/loading veils and
296
+ full-screen takeovers that outrank
297
+ everything, including a tooltip
298
+ ============================================================ */
299
+ --z-below: -1;
300
+ --z-base: 0;
301
+ --z-raised: 100;
302
+ --z-sticky: 200;
303
+ --z-header: 300;
304
+ --z-drawer: 400;
305
+ --z-window: 500;
306
+ --z-dock: 600;
307
+ --z-dropdown: 700;
308
+ --z-modal: 800;
309
+ --z-toast: 900;
310
+ --z-tooltip: 1000;
311
+ --z-top: 1100;
252
312
 
253
313
  --measure: 68ch;
254
314
  --measure-wide: 940px;
@@ -591,11 +651,10 @@
591
651
  scrim; heavier than --shadow-3 and theme-driven (was raw rgba(0,0,0,.4)). */
592
652
  --shadow-overlay: 0 12px 40px color-mix(in oklab, var(--fg) 28%, transparent),
593
653
  0 4px 12px color-mix(in oklab, var(--fg) 16%, transparent);
594
- --z-dropdown: 600;
595
- --z-popover: 700;
596
- --z-modal: 800;
597
- --z-toast: 900;
598
- --z-tooltip: 1000;
654
+ /* --z-popover is an alias, not a rung: popovers and dropdowns are the
655
+ same anchored-to-a-trigger layer and must never be able to drift
656
+ apart. The rungs themselves live with the stacking scale above. */
657
+ --z-popover: var(--z-dropdown);
599
658
  }
600
659
 
601
660
  /* app-shell.css */
@@ -624,7 +683,10 @@
624
683
  color: var(--accent-fg);
625
684
  padding: 8px 16px;
626
685
  text-decoration: none;
627
- z-index: 100;
686
+ /* Must outrank every layer of chrome once focused, or the first Tab press
687
+ lands on a control hidden behind the sticky header (was z-index:100,
688
+ which the header alone now matches). */
689
+ z-index: var(--z-top);
628
690
  border-radius: var(--r-pill);
629
691
  font-weight: 600;
630
692
  font-size: var(--fs-sm);
@@ -679,6 +741,13 @@
679
741
  .ds-247420 .t-mono { font-family: var(--ff-mono); }
680
742
  .ds-247420 .t-body { font-family: var(--ff-body); }
681
743
 
744
+ /* House small-label voice, in two sizes. Every declaration here is sourced
745
+ from a token, so a sheet that cannot join these selector lists (community.css
746
+ and gm-prose.css ship as separate <link>-able exports and must not depend on
747
+ app-shell.css being present) still composes the same voice by referencing the
748
+ same four tokens — --ff-mono / --fs-* / uppercase / --tr-label. That token
749
+ set, not this rule, is the single source of truth; a selector that restates a
750
+ literal instead of the token is the drift this pairing exists to prevent. */
682
751
  .ds-247420 .t-label { font-family: var(--ff-mono); font-size: var(--fs-tiny); text-transform: uppercase; letter-spacing: var(--tr-label); font-weight: 500; }
683
752
  .ds-247420 .t-micro { font-family: var(--ff-mono); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--tr-label); color: var(--fg-3); }
684
753
  .ds-247420 .t-meta { font-family: var(--ff-body); font-size: var(--fs-sm); color: var(--fg-3); }
@@ -1348,7 +1417,12 @@
1348
1417
  }
1349
1418
  .ds-247420 .panel-body { padding: var(--space-2) var(--space-3) var(--space-3); }
1350
1419
  .ds-247420 .panel-body > * { margin: 0; }
1351
- .ds-247420 .panel-body > * + * { margin-top: var(--space-3); }
1420
+ /* Inner sibling rhythm scales with density like the outer panel rhythm, so a
1421
+ compact/spacious surface stays proportional instead of only its outer
1422
+ intervals moving while the panel interiors hold still. Kept strictly below
1423
+ the outer .ds-panel-gap interval at every density — that ordering is what
1424
+ makes proximity report grouping truthfully. */
1425
+ .ds-247420 .panel-body > * + * { margin-top: calc(var(--space-3) * var(--density)); }
1352
1426
  .ds-247420 .panel.panel-wide .panel-body { padding: 0; }
1353
1427
 
1354
1428
  /* ============================================================
@@ -1570,7 +1644,7 @@
1570
1644
  ============================================================ */
1571
1645
  .ds-247420 .ds-grain { position: relative; isolation: isolate; }
1572
1646
  .ds-247420 .ds-grain::after {
1573
- content: ''; position: absolute; inset: 0; z-index: -1;
1647
+ content: ''; position: absolute; inset: 0; z-index: var(--z-below);
1574
1648
  pointer-events: none;
1575
1649
  background-image: var(--grain);
1576
1650
  background-size: 160px 160px;
@@ -1889,7 +1963,7 @@
1889
1963
  brand and let it scroll horizontally. The brand stays on the first row;
1890
1964
  nav wraps to a second row at 100% width (flex-wrap on .app-topbar). */
1891
1965
  .ds-247420 .app-topbar {
1892
- gap: var(--space-2); padding: 12px var(--space-3);
1966
+ gap: var(--space-2); padding: var(--space-2-75) var(--space-3);
1893
1967
  }
1894
1968
  /* When the topbar is folded into .app-chrome it is a flex:0 0 auto child, so
1895
1969
  it sizes to its nav's content and overflows the viewport instead of letting
@@ -1898,7 +1972,7 @@
1898
1972
  .ds-247420 .app-chrome > .app-topbar { max-width: 100%; min-width: 0; flex-basis: 100%; }
1899
1973
  .ds-247420 .app-topbar > nav {
1900
1974
  flex: 1 1 100%; margin-left: 0; order: 3; min-width: 0; max-width: 100%;
1901
- display: flex; gap: 2px; flex-wrap: nowrap;
1975
+ display: flex; gap: var(--space-hair); flex-wrap: nowrap;
1902
1976
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
1903
1977
  /* Fade the trailing edge so a clipped last item (e.g. "source ->" cut to
1904
1978
  "sour") reads as scrollable content, not a broken/truncated label. */
@@ -1907,7 +1981,7 @@
1907
1981
  }
1908
1982
  .ds-247420 .app-topbar nav::-webkit-scrollbar { display: none; }
1909
1983
  .ds-247420 .app-topbar nav a {
1910
- flex: 0 0 auto; padding: 10px 12px; min-height: 44px; white-space: nowrap;
1984
+ flex: 0 0 auto; padding: var(--space-2-5) var(--space-2-75); min-height: 44px; white-space: nowrap;
1911
1985
  }
1912
1986
  .ds-247420 .brand { font-size: var(--fs-tiny); font-weight: 600; }
1913
1987
 
@@ -1930,8 +2004,8 @@
1930
2004
 
1931
2005
  .ds-247420 .row {
1932
2006
  grid-template-columns: minmax(0, 1fr) auto !important;
1933
- gap: var(--space-2); padding: 12px 16px;
1934
- row-gap: 4px !important;
2007
+ gap: var(--space-2); padding: var(--space-2-75) var(--space-3);
2008
+ row-gap: var(--space-1) !important;
1935
2009
  }
1936
2010
  .ds-247420 .row .sub { grid-column: 1 / -1; order: 3; }
1937
2011
  .ds-247420 .row .title { font-size: var(--fs-sm); }
@@ -1942,7 +2016,10 @@
1942
2016
 
1943
2017
  /* Buttons */
1944
2018
  .ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost {
1945
- padding: 11px 16px; font-size: var(--fs-tiny);
2019
+ /* 11px vertical is optical, not scale drift: --space-2-75 (12) would tip
2020
+ the intrinsic box past the 44px min-height floor below and make the
2021
+ floor dead, changing the mobile button rhythm. */
2022
+ padding: 11px var(--space-3); font-size: var(--fs-tiny);
1946
2023
  min-height: 44px; /* Touch target minimum */
1947
2024
  }
1948
2025
 
@@ -1950,13 +2027,13 @@
1950
2027
  .ds-247420 .ds-file-grid {
1951
2028
  display: flex;
1952
2029
  flex-direction: column;
1953
- gap: 3px;
2030
+ gap: var(--space-half);
1954
2031
  }
1955
2032
  .ds-247420 .ds-file-row {
1956
- gap: 8px; padding: 10px 12px;
2033
+ gap: var(--space-2); padding: var(--space-2-5) var(--space-2-75);
1957
2034
  font-size: var(--fs-xs);
1958
2035
  }
1959
- .ds-247420 .ds-file-open { gap: 10px; }
2036
+ .ds-247420 .ds-file-open { gap: var(--space-2-5); }
1960
2037
  /* At mobile row widths, a fixed-size meta column (date/size) plus the
1961
2038
  always-visible action buttons leave the flexible title only a few px —
1962
2039
  not enough for even one legible character before the two collide. Drop
@@ -1973,12 +2050,12 @@
1973
2050
  /* Chat */
1974
2051
  .ds-247420 .chat-stack { max-width: 100%; min-width: 0; }
1975
2052
  .ds-247420 .chat-bubble {
1976
- padding: 10px 12px; font-size: var(--fs-sm);
2053
+ padding: var(--space-2-5) var(--space-2-75); font-size: var(--fs-sm);
1977
2054
  }
1978
2055
  .ds-247420 .chat-avatar { width: 28px; height: 28px; font-size: 11px; }
1979
- .ds-247420 .chat-msg:hover { padding: 4px 0; margin: 0; background: transparent; }
1980
- .ds-247420 .chat-composer { padding: 8px; gap: 6px; }
1981
- .ds-247420 .chat-composer textarea { padding: 10px 12px; font-size: var(--fs-sm); }
2056
+ .ds-247420 .chat-msg:hover { padding: var(--space-1) 0; margin: 0; background: transparent; }
2057
+ .ds-247420 .chat-composer { padding: var(--space-2); gap: var(--space-1-75); }
2058
+ .ds-247420 .chat-composer textarea { padding: var(--space-2-5) var(--space-2-75); font-size: var(--fs-sm); }
1982
2059
 
1983
2060
  /* KPI Cards */
1984
2061
  .ds-247420 .kpi {
@@ -1994,9 +2071,10 @@
1994
2071
  .ds-247420 .empty { padding: var(--space-5); font-size: var(--fs-xs); }
1995
2072
 
1996
2073
  /* Form */
1997
- .ds-247420 .row-form { gap: 10px; padding: var(--space-3); }
2074
+ .ds-247420 .row-form { gap: var(--space-2-5); padding: var(--space-3); }
1998
2075
  .ds-247420 .row-form input,
1999
- .ds-247420 .row-form textarea { padding: 11px 12px; font-size: var(--fs-sm); }
2076
+
2077
+ .ds-247420 .row-form textarea { padding: 11px var(--space-2-75); font-size: var(--fs-sm); }
2000
2078
 
2001
2079
  /* Hero Section — keep fluid base font-size, just unconstrain width on mobile. */
2002
2080
  .ds-247420 .ds-hero { padding: var(--space-6) 0 var(--space-5); }
@@ -2006,14 +2084,14 @@
2006
2084
  /* Table Responsiveness */
2007
2085
  .ds-247420 table { font-size: var(--fs-xs); }
2008
2086
  .ds-247420 table th,
2009
- .ds-247420 table td { padding: 10px 12px; }
2087
+ .ds-247420 table td { padding: var(--space-2-5) var(--space-2-75); }
2010
2088
 
2011
2089
  /* CLI Block */
2012
2090
  .ds-247420 .cli {
2013
- flex-direction: column; align-items: flex-start; gap: 10px;
2014
- padding: 16px 12px; font-size: var(--fs-xs);
2091
+ flex-direction: column; align-items: flex-start; gap: var(--space-2-5);
2092
+ padding: var(--space-3) var(--space-2-75); font-size: var(--fs-xs);
2015
2093
  }
2016
- .ds-247420 .cli .copy { padding: 6px 12px; font-size: var(--fs-micro); }
2094
+ .ds-247420 .cli .copy { padding: var(--space-1-75) var(--space-2-75); font-size: var(--fs-micro); }
2017
2095
  }
2018
2096
 
2019
2097
  /* --------------------------------------------------------------------
@@ -2022,8 +2100,8 @@
2022
2100
  @container (max-width: 760px) {
2023
2101
  .ds-247420 .app-body { grid-template-columns: 1fr !important; }
2024
2102
  .ds-247420 .app-side-shell { border-right: 0; border-bottom: 1px solid var(--rule); }
2025
- .ds-247420 .app-topbar nav { font-size: var(--fs-xs); gap: 14px; }
2026
- .ds-247420 .row { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 4px !important; }
2103
+ .ds-247420 .app-topbar nav { font-size: var(--fs-xs); gap: var(--space-2-75); }
2104
+ .ds-247420 .row { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: var(--space-1) !important; }
2027
2105
  .ds-247420 .row .sub { grid-column: 1 / -1; order: 3; }
2028
2106
  .ds-247420 .ds-changelog-row { grid-template-columns: minmax(70px, 10ch) minmax(0, 1fr) !important; }
2029
2107
  .ds-247420 .ds-changelog-row .title { grid-column: 1 / -1; }
@@ -2035,7 +2113,7 @@
2035
2113
  @media (min-width: 481px) and (max-width: 1024px) {
2036
2114
  /* App Layout — side handled by 900px drawer block; restore for 901-1024 */
2037
2115
  .ds-247420 .app-side a {
2038
- padding: 12px 12px; gap: 8px;
2116
+ padding: var(--space-2-75) var(--space-2-75); gap: var(--space-2);
2039
2117
  grid-template-columns: 16px 1fr auto;
2040
2118
  font-size: var(--fs-xs);
2041
2119
  min-height: 44px;
@@ -2043,14 +2121,14 @@
2043
2121
 
2044
2122
  /* Topbar Navigation (flex container — no grid-template here) */
2045
2123
  .ds-247420 .app-topbar {
2046
- gap: var(--space-3); padding: 12px var(--space-4);
2124
+ gap: var(--space-3); padding: var(--space-2-75) var(--space-4);
2047
2125
  }
2048
2126
  .ds-247420 .app-topbar nav {
2049
- display: flex; gap: 8px; font-size: var(--fs-xs);
2127
+ display: flex; gap: var(--space-2); font-size: var(--fs-xs);
2050
2128
  flex-wrap: wrap;
2051
2129
  }
2052
2130
  .ds-247420 .app-topbar nav a {
2053
- padding: 12px 12px; font-size: var(--fs-xs);
2131
+ padding: var(--space-2-75) var(--space-2-75); font-size: var(--fs-xs);
2054
2132
  min-height: 44px;
2055
2133
  }
2056
2134
  .ds-247420 .brand { font-size: var(--fs-sm); }
@@ -2059,7 +2137,10 @@
2059
2137
  .ds-247420 .app-search {
2060
2138
  display: inline-flex;
2061
2139
  max-width: 280px; font-size: var(--fs-xs);
2062
- padding: 8px 14px;
2140
+ /* 14px inline is between --space-2-75 (12) and --space-3 (16) with no tier;
2141
+ it is the width that centers the search glyph against the 280px max-width
2142
+ field. Snapping either way reads as a mis-centered control. */
2143
+ padding: var(--space-2) 14px;
2063
2144
  }
2064
2145
 
2065
2146
  /* Main Content */
@@ -2071,12 +2152,17 @@
2071
2152
  /* File list — single column rows on tablet (cards only via data-columns) */
2072
2153
  .ds-247420 .ds-file-row {
2073
2154
  grid-template-columns: 24px minmax(0, 1fr) auto auto;
2074
- gap: 12px; padding: 12px 14px;
2155
+ /* 14px inline (no tier between 12 and 16) is the tablet row inset that
2156
+ keeps the 24px icon column optically flush with the panel edge. */
2157
+ gap: var(--space-2-75); padding: var(--space-2-75) 14px;
2075
2158
  }
2076
2159
 
2077
2160
  /* Chat Bubbles */
2078
2161
  .ds-247420 .chat-stack { max-width: min(75%, 420px); }
2079
2162
  .ds-247420 .chat-bubble {
2163
+ /* 11px/14px are the tuned tablet bubble insets; neither is on the scale
2164
+ (11 sits between --space-2-5 and --space-2-75, 14 between --space-2-75
2165
+ and --space-3) and snapping visibly re-pitches every bubble in a thread. */
2080
2166
  padding: 11px 14px; font-size: var(--fs-sm);
2081
2167
  }
2082
2168
  .ds-247420 .chat-avatar { width: 32px; height: 32px; font-size: 12px; }
@@ -2089,7 +2175,10 @@
2089
2175
 
2090
2176
  /* Buttons */
2091
2177
  .ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost {
2092
- padding: 12px 18px; font-size: var(--fs-sm);
2178
+ /* 18px inline has no tier (--space-3 is 16, --space-3-5 is 20); it is the
2179
+ tablet CTA width tuned against the 12px vertical, so snapping changes
2180
+ the button aspect on the most visible control in the kit. */
2181
+ padding: var(--space-2-75) 18px; font-size: var(--fs-sm);
2093
2182
  }
2094
2183
 
2095
2184
  /* Panel - keep the head on the body's left axis at laptop widths too. */
@@ -2103,7 +2192,9 @@
2103
2192
  /* Row */
2104
2193
  .ds-247420 .row {
2105
2194
  grid-template-columns: minmax(90px, 12ch) minmax(0, 1fr) auto;
2106
- gap: var(--space-2); padding: 14px 16px;
2195
+ /* 14px block (no tier between 12 and 16) is the tablet row height tuned
2196
+ against the 12ch code column; snapping re-pitches the whole list. */
2197
+ gap: var(--space-2); padding: 14px var(--space-3);
2107
2198
  }
2108
2199
  }
2109
2200
 
@@ -2161,7 +2252,7 @@
2161
2252
  .ds-247420 .ds-file-grid {
2162
2253
  display: flex;
2163
2254
  flex-direction: column;
2164
- gap: 4px;
2255
+ gap: var(--space-1);
2165
2256
  }
2166
2257
  .ds-247420 .ds-file-grid:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); border-radius: var(--r-2); }
2167
2258
 
@@ -2172,7 +2263,7 @@
2172
2263
  /* The filter is now an inline item in the single .ds-file-controls toolbar row
2173
2264
  (the standalone right-aligned .ds-file-filter strip was removed). */
2174
2265
  .ds-247420 .ds-file-filter-input {
2175
- width: min(280px, 100%); padding: 6px 12px; font-size: var(--fs-sm);
2266
+ width: min(280px, 100%); padding: var(--space-1-75) var(--space-2-75); font-size: var(--fs-sm);
2176
2267
  background: var(--bg); color: var(--fg);
2177
2268
  border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1);
2178
2269
  }
@@ -2182,7 +2273,7 @@
2182
2273
  .ds-247420 .ds-file-sort { display: flex; gap: var(--space-2); padding: 0 var(--space-2) var(--space-1); }
2183
2274
  .ds-247420 .ds-file-sort-btn {
2184
2275
  font-size: var(--fs-tiny); font-family: var(--ff-mono); color: var(--fg-3);
2185
- background: none; border: none; cursor: pointer; padding: 2px 4px; border-radius: var(--r-1);
2276
+ background: none; border: none; cursor: pointer; padding: var(--space-hair) var(--space-1); border-radius: var(--r-1);
2186
2277
  }
2187
2278
  .ds-247420 .ds-file-sort-btn:hover { color: var(--fg-2); background: var(--bg-2); }
2188
2279
  .ds-247420 .ds-file-sort-btn.active { color: var(--accent-ink); }
@@ -2197,9 +2288,9 @@
2197
2288
  .ds-247420 .ds-file-grid { transition: opacity .15s var(--ease); }
2198
2289
  }
2199
2290
  /* EventList loading skeleton (shares the .ds-skel shimmer base above). */
2200
- .ds-247420 .ds-event-row-skeleton { display: flex; align-items: center; gap: var(--space-3); padding: 12px 16px; pointer-events: none; }
2291
+ .ds-247420 .ds-event-row-skeleton { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2-75) var(--space-3); pointer-events: none; }
2201
2292
  .ds-247420 .ds-skel-rank { height: 12px; width: 2.5ch; }
2202
- .ds-247420 .ds-event-state { padding: var(--space-2) 16px; }
2293
+ .ds-247420 .ds-event-state { padding: var(--space-2) var(--space-3); }
2203
2294
  .ds-247420 .ds-skel { display: inline-block; border-radius: var(--r-1); background: var(--bg-2); position: relative; overflow: hidden; }
2204
2295
  .ds-247420 .ds-skel::after {
2205
2296
  content: ''; position: absolute; inset: 0;
@@ -2218,8 +2309,13 @@
2218
2309
  because FileRow wraps the row content in a real button for native keyboard
2219
2310
  semantics. */
2220
2311
  .ds-247420 .ds-file-row {
2221
- display: flex; align-items: center; gap: 10px;
2222
- padding: 11px 16px; background: var(--bg);
2312
+ display: flex; align-items: center; gap: var(--space-2-5);
2313
+ /* 11px vertical is an optical half-step between --space-2-5 (10) and
2314
+ --space-2-75 (12), deliberately off-scale: with the 26px .ds-file-icon
2315
+ and the hairline borders it lands the row at ~50px, comfortably over the
2316
+ 44px touch floor without the 52px a 12px pad would give. Snapping either
2317
+ way visibly re-pitches every row in a long listing. */
2318
+ padding: 11px var(--space-3); background: var(--bg);
2223
2319
  border: var(--bw-hair) solid transparent;
2224
2320
  border-radius: var(--r-2); color: var(--fg);
2225
2321
  cursor: pointer;
@@ -2228,7 +2324,7 @@
2228
2324
  transform var(--dur-snap) var(--ease);
2229
2325
  }
2230
2326
  .ds-247420 .ds-file-open {
2231
- display: flex; align-items: center; gap: 14px;
2327
+ display: flex; align-items: center; gap: var(--space-2-75);
2232
2328
  flex: 1 1 auto; min-width: 0;
2233
2329
  background: none; border: 0; padding: 0; margin: 0;
2234
2330
  color: inherit; font: inherit; text-align: left; cursor: pointer;
@@ -2291,7 +2387,7 @@
2291
2387
  hidden, which left mouse/trackpad users unable to find rename/move/delete
2292
2388
  without accidentally hovering a row), full opacity on hover/focus. */
2293
2389
  .ds-247420 .ds-file-actions {
2294
- display: inline-flex; gap: 2px; align-items: center;
2390
+ display: inline-flex; gap: var(--space-hair); align-items: center;
2295
2391
  opacity: 0.35; transition: opacity var(--dur-base) var(--ease);
2296
2392
  }
2297
2393
  .ds-247420 .ds-file-row:hover .ds-file-actions,
@@ -2336,7 +2432,7 @@
2336
2432
 
2337
2433
  .ds-247420 .ds-file-check {
2338
2434
  display: inline-flex; align-items: center; justify-content: center;
2339
- min-width: 28px; height: 28px; padding: 0 4px;
2435
+ min-width: 28px; height: 28px; padding: 0 var(--space-1);
2340
2436
  background: transparent; border: 0; border-radius: var(--r-1);
2341
2437
  color: var(--fg-3);
2342
2438
  cursor: pointer;
@@ -2368,7 +2464,7 @@
2368
2464
  quiet destructive outline - the app arm-confirms destructive bulk actions
2369
2465
  via ConfirmDialog, so the strip never needs a loud CTA. */
2370
2466
  .ds-247420 .ds-bulkbar .btn, .ds-247420 .ds-bulkbar .btn-primary {
2371
- padding: 5px 12px; min-height: 32px; border-radius: var(--r-1); font-weight: 500;
2467
+ padding: var(--space-1-5) var(--space-2-75); min-height: 32px; border-radius: var(--r-1); font-weight: 500;
2372
2468
  }
2373
2469
  .ds-247420 .ds-bulkbar .btn { background: transparent; border: var(--bw-hair) solid var(--rule); color: var(--fg-2); }
2374
2470
  .ds-247420 .ds-bulkbar .btn:hover { background: var(--bg-2); color: var(--fg); }
@@ -2380,7 +2476,7 @@
2380
2476
 
2381
2477
  /* Density picker — list / compact / thumbnails. */
2382
2478
  .ds-247420 .ds-density {
2383
- display: inline-flex; gap: 2px; padding: 2px;
2479
+ display: inline-flex; gap: var(--space-hair); padding: var(--space-hair);
2384
2480
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1);
2385
2481
  }
2386
2482
  .ds-247420 .ds-density-btn {
@@ -2395,8 +2491,8 @@
2395
2491
  .ds-247420 .ds-density-btn:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
2396
2492
 
2397
2493
  /* Compact density — tighter rows for long listings. */
2398
- .ds-247420 .ds-file-grid[data-density="compact"] { gap: 2px; }
2399
- .ds-247420 .ds-file-grid[data-density="compact"] .ds-file-row { padding: 5px 12px; gap: 10px; }
2494
+ .ds-247420 .ds-file-grid[data-density="compact"] { gap: var(--space-hair); }
2495
+ .ds-247420 .ds-file-grid[data-density="compact"] .ds-file-row { padding: var(--space-1-5) var(--space-2-75); gap: var(--space-2-5); }
2400
2496
  .ds-247420 .ds-file-grid[data-density="compact"] .ds-file-row .title { font-size: var(--fs-xs); }
2401
2497
  .ds-247420 .ds-file-grid[data-density="compact"] .ds-file-row .ds-file-meta { font-size: var(--fs-micro); }
2402
2498
  .ds-247420 .ds-file-grid[data-density="compact"] .ds-file-icon { width: 20px; height: 20px; font-size: 13px; }
@@ -2418,11 +2514,14 @@
2418
2514
  .ds-247420 .ds-file-cell.is-locked { opacity: 0.6; }
2419
2515
  .ds-247420 .ds-file-row.is-locked { opacity: 0.6; }
2420
2516
  .ds-247420 .ds-file-row.is-restricted .title { color: var(--fg-2); }
2421
- /* A fourth, deliberately bordered/mono tag variant for file-permission tags
2517
+ /* 1px vertical pad is deliberately below --space-hair (2px): this mono tag
2518
+ sits inline in a file row and must not add height to it; --space-hair would
2519
+ double the vertical pad and push the tag past the row cap height.
2520
+ A fourth, deliberately bordered/mono tag variant for file-permission tags
2422
2521
  specifically (distinct from .ds-badge for numeric counts and .chip for
2423
2522
  status/label words) - is-noaccess reuses the shared --flame tone token
2424
2523
  so 'no access' reads the same red as chip.tone-error/miss elsewhere. */
2425
- .ds-247420 .ds-file-perm-tag { font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--fg-3); padding: 1px 6px; border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1); white-space: nowrap; }
2524
+ .ds-247420 .ds-file-perm-tag { font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--fg-3); padding: 1px var(--space-1-75); border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1); white-space: nowrap; }
2426
2525
  .ds-247420 .ds-file-perm-tag.is-noaccess { color: var(--flame); border-color: var(--flame); }
2427
2526
  .ds-247420 .ds-file-cell-open {
2428
2527
  display: flex; flex-direction: column; align-items: stretch; gap: var(--space-1);
@@ -2454,7 +2553,7 @@
2454
2553
  }
2455
2554
  .ds-247420 .ds-file-cell-meta { font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--fg-3); text-align: left; }
2456
2555
  .ds-247420 .ds-file-cell-check {
2457
- position: absolute; top: 4px; left: 4px; z-index: 1;
2556
+ position: absolute; top: 4px; left: 4px; z-index: var(--z-raised);
2458
2557
  background: color-mix(in oklab, var(--bg) 78%, transparent);
2459
2558
  }
2460
2559
 
@@ -2491,12 +2590,12 @@
2491
2590
 
2492
2591
  /* Breadcrumb path */
2493
2592
  .ds-247420 .ds-crumb-path {
2494
- display: flex; align-items: center; flex-wrap: wrap; gap: 2px;
2593
+ display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-hair);
2495
2594
  font-size: var(--fs-sm);
2496
2595
  }
2497
2596
  .ds-247420 .ds-crumb-seg {
2498
2597
  background: transparent; border: 0; cursor: pointer;
2499
- padding: 4px 8px; border-radius: var(--r-1);
2598
+ padding: var(--space-1) var(--space-2); border-radius: var(--r-1);
2500
2599
  color: var(--fg-3); font-family: inherit; font-size: var(--fs-sm);
2501
2600
  transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
2502
2601
  /* A single long unbroken segment (hash-named dir) must never force the
@@ -2544,7 +2643,7 @@
2544
2643
  /* Toolbar-scoped buttons: quiet, compact, rectangular - a toolbar is chrome,
2545
2644
  not a CTA row; the stadium pill stays for real page-level actions. */
2546
2645
  .ds-247420 .ds-file-toolbar .btn, .ds-247420 .ds-file-toolbar .btn-ghost {
2547
- padding: 5px 12px; min-height: 32px;
2646
+ padding: var(--space-1-5) var(--space-2-75); min-height: 32px;
2548
2647
  border-radius: var(--r-1);
2549
2648
  font-weight: 500;
2550
2649
  background: transparent;
@@ -2561,7 +2660,7 @@
2561
2660
 
2562
2661
  /* Error banner — dismissible toast row. */
2563
2662
  .ds-247420 .ds-error-banner {
2564
- padding: 10px 14px; border-radius: var(--r-2);
2663
+ padding: var(--space-2-5) var(--space-2-75); border-radius: var(--r-2);
2565
2664
  background: color-mix(in oklab, var(--warn) 14%, var(--bg));
2566
2665
  border: var(--bw-hair) solid color-mix(in oklab, var(--warn) 40%, transparent);
2567
2666
  color: var(--warn); font-size: var(--fs-sm); cursor: pointer;
@@ -2600,7 +2699,7 @@
2600
2699
  .ds-247420 .ds-dropzone--wrap { position: relative; border: none; border-radius: 0; background: transparent; }
2601
2700
  .ds-247420 .ds-dropzone--wrap > .ds-dropzone-inner { display: none; }
2602
2701
  .ds-247420 .ds-dropzone--wrap.dragover > .ds-dropzone-inner {
2603
- display: flex; position: absolute; inset: 0; z-index: 5;
2702
+ display: flex; position: absolute; inset: 0; z-index: var(--z-raised);
2604
2703
  margin: 0; padding: var(--space-3);
2605
2704
  align-items: center; justify-content: center;
2606
2705
  background: color-mix(in srgb, var(--bg) 84%, transparent);
@@ -2618,11 +2717,11 @@
2618
2717
  }
2619
2718
 
2620
2719
  /* Upload progress */
2621
- .ds-247420 .ds-upload-progress { display: flex; flex-direction: column; gap: 6px; }
2720
+ .ds-247420 .ds-upload-progress { display: flex; flex-direction: column; gap: var(--space-1-75); }
2622
2721
  .ds-247420 .ds-upload-item {
2623
2722
  display: grid; grid-template-columns: minmax(0, 1fr) 120px 44px;
2624
2723
  gap: var(--space-2); align-items: center;
2625
- padding: 8px 12px; border-radius: var(--r-2);
2724
+ padding: var(--space-2) var(--space-2-75); border-radius: var(--r-2);
2626
2725
  background: var(--bg-2); font-size: var(--fs-xs);
2627
2726
  }
2628
2727
  .ds-247420 .ds-upload-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -2666,7 +2765,7 @@
2666
2765
  }
2667
2766
  .ds-247420 .ds-upload-actions { display: inline-flex; gap: var(--space-1); justify-content: flex-end; }
2668
2767
  .ds-247420 .ds-upload-act {
2669
- padding: 2px 10px; min-height: 24px; cursor: pointer;
2768
+ padding: var(--space-hair) var(--space-2-5); min-height: 24px; cursor: pointer;
2670
2769
  background: var(--bg); border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1);
2671
2770
  color: var(--fg-2); font-family: var(--ff-body); font-size: var(--fs-micro);
2672
2771
  }
@@ -2692,7 +2791,7 @@
2692
2791
 
2693
2792
  /* -- Modals ------------------------------------------------- */
2694
2793
  .ds-247420 .ds-modal-backdrop {
2695
- position: fixed; inset: 0; z-index: var(--z-modal, 800);
2794
+ position: fixed; inset: 0; z-index: var(--z-modal);
2696
2795
  display: flex; align-items: center; justify-content: center;
2697
2796
  /* Notch/home-indicator safe: near-fullscreen modals must not slide under. */
2698
2797
  padding: max(var(--space-3), env(safe-area-inset-top))
@@ -2736,7 +2835,7 @@
2736
2835
  border-top: var(--bw-hair) solid var(--rule);
2737
2836
  }
2738
2837
  .ds-247420 .ds-modal-input {
2739
- width: 100%; padding: 10px 12px;
2838
+ width: 100%; padding: var(--space-2-5) var(--space-2-75);
2740
2839
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule);
2741
2840
  border-radius: var(--r-2); color: var(--fg);
2742
2841
  font-family: inherit; font-size: var(--fs-sm);
@@ -2748,10 +2847,10 @@
2748
2847
  }
2749
2848
  /* PromptDialog's optional roots-chip row (destination-path prompts with more
2750
2849
  than one allowed root) - same chip idiom the cwd editor's roots row uses. */
2751
- .ds-247420 .ds-prompt-roots { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
2850
+ .ds-247420 .ds-prompt-roots { display: flex; align-items: center; gap: var(--space-1-75); flex-wrap: wrap; margin-top: var(--space-2); }
2752
2851
  .ds-247420 .ds-prompt-root-chip {
2753
2852
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule); color: var(--fg-2);
2754
- border-radius: var(--r-pill); padding: 3px 10px; font: inherit; font-size: var(--fs-tiny);
2853
+ border-radius: var(--r-pill); padding: var(--space-half) var(--space-2-5); font: inherit; font-size: var(--fs-tiny);
2755
2854
  cursor: pointer;
2756
2855
  }
2757
2856
  .ds-247420 .ds-prompt-root-chip:hover { border-color: var(--accent); color: var(--fg); }
@@ -2760,7 +2859,7 @@
2760
2859
  /* In-body modal error (role=alert): mutation failures (409/403) surface INSIDE
2761
2860
  the dialog, not behind the fixed overlay. */
2762
2861
  .ds-247420 .ds-modal-error {
2763
- margin: var(--space-2) 0 0; padding: 8px 10px;
2862
+ margin: var(--space-2) 0 0; padding: var(--space-2) var(--space-2-5);
2764
2863
  border: var(--bw-hair) solid var(--flame); border-radius: var(--r-2);
2765
2864
  background: color-mix(in oklab, var(--flame) 12%, var(--bg));
2766
2865
  color: var(--flame); font-size: var(--fs-xs);
@@ -2788,7 +2887,7 @@
2788
2887
  color: var(--fg-3); white-space: nowrap;
2789
2888
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
2790
2889
  }
2791
- .ds-247420 .ds-preview-actions { display: inline-flex; gap: 2px; margin-left: auto; }
2890
+ .ds-247420 .ds-preview-actions { display: inline-flex; gap: var(--space-hair); margin-left: auto; }
2792
2891
  .ds-247420 .ds-preview-body {
2793
2892
  flex: 1; min-height: 0; overflow: auto;
2794
2893
  padding: var(--space-3) var(--space-4);
@@ -2875,7 +2974,7 @@
2875
2974
  .ds-247420 .ds-file-stage { padding: var(--space-3) var(--space-2); }
2876
2975
  /* Preview head: let it wrap and drop the nowrap meta (duplicated in body)
2877
2976
  so the close button can never be pushed past the modal edge. */
2878
- .ds-247420 .ds-preview-head { flex-wrap: wrap; row-gap: 4px; }
2977
+ .ds-247420 .ds-preview-head { flex-wrap: wrap; row-gap: var(--space-1); }
2879
2978
  .ds-247420 .ds-preview-meta { display: none; }
2880
2979
  }
2881
2980
 
@@ -3001,6 +3100,13 @@
3001
3100
  transition: color var(--dur-base) var(--ease), background var(--dur-base) var(--ease);
3002
3101
  }
3003
3102
  .ds-247420 .ds-segmented .ds-seg-btn:hover { color: var(--fg); }
3103
+ /* Touch floor — a segmented control is a primary mode switch but renders ~30px
3104
+ tall from its 4px padding, below the 44px minimum the rest of the system
3105
+ holds. Grows the hit area only; the pill's visual size is unchanged at
3106
+ fine-pointer sizes. */
3107
+ @media (pointer: coarse) {
3108
+ .ds-247420 .ds-segmented .ds-seg-btn { min-height: 44px; padding-inline: var(--space-3); }
3109
+ }
3004
3110
  .ds-247420 .ds-segmented .ds-seg-btn:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
3005
3111
  .ds-247420 .ds-segmented .ds-seg-btn.is-on {
3006
3112
  background: var(--bg); color: var(--fg);
@@ -3028,7 +3134,7 @@
3028
3134
  flex: 1; min-height: 0; gap: var(--space-3);
3029
3135
  }
3030
3136
  .ds-247420 .chat-head {
3031
- display: flex; align-items: baseline; gap: 8px;
3137
+ display: flex; align-items: baseline; gap: var(--space-2);
3032
3138
  padding: var(--space-3) 0 var(--space-2);
3033
3139
  font-family: var(--ff-mono); font-size: var(--fs-xs);
3034
3140
  color: var(--fg-3); text-transform: lowercase; letter-spacing: 0.02em;
@@ -3066,10 +3172,10 @@
3066
3172
  .ds-247420 .chat-empty-title { font-size: var(--fs-sm); margin: 0 0 var(--space-1); }
3067
3173
  .ds-247420 .chat-empty-sub { font-size: var(--fs-tiny); margin: 0; opacity: .7; }
3068
3174
 
3069
- .ds-247420 .chat-msg { display: flex; gap: 12px; align-items: flex-start; padding: 6px 0; position: relative; min-width: 0; }
3175
+ .ds-247420 .chat-msg { display: flex; gap: var(--space-2-75); align-items: flex-start; padding: var(--space-1-75) 0; position: relative; min-width: 0; }
3070
3176
  .ds-247420 .chat-msg.you { flex-direction: row-reverse; }
3071
3177
  .ds-247420 .chat-msg.you .chat-stack { align-items: flex-end; }
3072
- .ds-247420 .chat-msg:hover { background: color-mix(in oklab, var(--fg) 4%, transparent); padding: 6px 0; margin: 0; border-radius: var(--r-0); transition: background var(--dur-base) var(--ease); }
3178
+ .ds-247420 .chat-msg:hover { background: color-mix(in oklab, var(--fg) 4%, transparent); padding: var(--space-1-75) 0; margin: 0; border-radius: var(--r-0); transition: background var(--dur-base) var(--ease); }
3073
3179
 
3074
3180
  .ds-247420 .chat-avatar {
3075
3181
  width: 36px; height: 36px; flex-shrink: 0;
@@ -3091,13 +3197,16 @@
3091
3197
  }
3092
3198
 
3093
3199
  .ds-247420 .chat-stack {
3094
- display: flex; flex-direction: column; gap: 4px;
3200
+ display: flex; flex-direction: column; gap: var(--space-1);
3095
3201
  max-width: min(70%, 56ch); min-width: 0;
3096
3202
  flex: 0 1 auto; overflow: hidden;
3097
3203
  }
3098
3204
 
3099
3205
  .ds-247420 .chat-bubble {
3100
- padding: 10px 14px; background: var(--bg-2); color: var(--fg);
3206
+ /* 14px inline has no tier (--space-2-75 is 12, --space-3 is 16). It is the
3207
+ shared bubble/attachment inset used by .chat-file/.chat-pdf-head below;
3208
+ snapping only this one would visibly desync the bubble from its cards. */
3209
+ padding: var(--space-2-5) 14px; background: var(--bg-2); color: var(--fg);
3101
3210
  max-width: 100%;
3102
3211
  border-radius: var(--r-2); line-height: 1.55;
3103
3212
  word-wrap: break-word; overflow-wrap: anywhere;
@@ -3115,7 +3224,9 @@
3115
3224
  .ds-247420 .chat-bubble code {
3116
3225
  font-family: var(--ff-mono); font-size: 0.92em;
3117
3226
  background: color-mix(in oklab, var(--fg) 10%, transparent);
3118
- padding: 1px 6px; border-radius: var(--r-0);
3227
+ /* 1px block is deliberately under --space-hair (2px): inline <code> must not
3228
+ grow the line box of the prose it sits inside. */
3229
+ padding: 1px var(--space-1-75); border-radius: var(--r-0);
3119
3230
  }
3120
3231
  .ds-247420 .chat-msg.you .chat-bubble code { background: color-mix(in oklab, var(--fg) 10%, transparent); }
3121
3232
  .ds-247420 .chat-bubble a {
@@ -3142,17 +3253,23 @@
3142
3253
  .ds-247420 .chat-bubble.chat-md h3 { font-size: 1.04em; }
3143
3254
  .ds-247420 .chat-bubble.chat-md p { margin: var(--space-2) 0; }
3144
3255
  .ds-247420 .chat-bubble.chat-md ul,
3256
+
3145
3257
  .ds-247420 .chat-bubble.chat-md ol { margin: var(--space-2) 0; padding-left: 22px; }
3146
3258
  .ds-247420 .chat-bubble.chat-md li { margin: var(--space-1) 0; }
3147
3259
  .ds-247420 .chat-bubble.chat-md blockquote {
3148
- margin: var(--space-2) 0; padding: 4px 12px;
3149
- border-left: 3px solid color-mix(in oklab, currentColor 30%, transparent);
3260
+ margin: var(--space-2) 0; padding: var(--space-1) var(--space-2-75);
3261
+ /* DELIBERATE, but slimmed to the --bw-rule tier. This is a real markdown
3262
+ <blockquote> inside a chat bubble: the left rule is the standard
3263
+ typographic quotation mark, not a colored alert stripe (the tone is a
3264
+ currentColor mix that inherits the bubble's own ink — never an accent).
3265
+ A 3px off-scale literal read as the generic tell; 2px reads as type. */
3266
+ border-left: var(--bw-rule) solid color-mix(in oklab, currentColor 30%, transparent);
3150
3267
  color: color-mix(in oklab, currentColor 75%, transparent); font-style: italic;
3151
3268
  }
3152
3269
  .ds-247420 .chat-bubble.chat-md pre {
3153
3270
  background: var(--bg);
3154
3271
  border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
3155
- padding: 12px 16px; border-radius: var(--r-1); overflow-x: auto;
3272
+ padding: var(--space-2-75) var(--space-3); border-radius: var(--r-1); overflow-x: auto;
3156
3273
  font-family: var(--ff-mono); font-size: var(--fs-xs); line-height: 1.55;
3157
3274
  color: var(--fg); margin: var(--space-2) 0;
3158
3275
  }
@@ -3166,11 +3283,11 @@
3166
3283
  }
3167
3284
  /* Markdown tables + horizontal rules: agents routinely emit them, but they were
3168
3285
  unstyled (bare unspaced cells, vanished rules). */
3169
- .ds-247420 .chat-bubble.chat-md table { border-collapse: collapse; width: auto; max-width: 100%; margin: 8px 0; font-size: .95em; display: block; overflow-x: auto; }
3286
+ .ds-247420 .chat-bubble.chat-md table { border-collapse: collapse; width: auto; max-width: 100%; margin: var(--space-2) 0; font-size: .95em; display: block; overflow-x: auto; }
3170
3287
  .ds-247420 .chat-bubble.chat-md th,
3171
- .ds-247420 .chat-bubble.chat-md td { border: var(--bw-hair) solid var(--rule); padding: 4px 10px; text-align: left; }
3288
+ .ds-247420 .chat-bubble.chat-md td { border: var(--bw-hair) solid var(--rule); padding: var(--space-1) var(--space-2-5); text-align: left; }
3172
3289
  .ds-247420 .chat-bubble.chat-md th { background: color-mix(in oklab, var(--fg) 5%, transparent); font-weight: 600; }
3173
- .ds-247420 .chat-bubble.chat-md hr { border: 0; border-top: var(--bw-hair) solid var(--rule); margin: 12px 0; }
3290
+ .ds-247420 .chat-bubble.chat-md hr { border: 0; border-top: var(--bw-hair) solid var(--rule); margin: var(--space-2-75) 0; }
3174
3291
 
3175
3292
  /* Mermaid diagram blocks — rendered SVG swapped in over the fenced source by
3176
3293
  src/mermaid.js's renderMermaidBlocksUnder(); the source .pre stays in the
@@ -3178,7 +3295,7 @@
3178
3295
  .ds-247420 .ds-mermaid-block {
3179
3296
  position: relative; margin: var(--space-2) 0;
3180
3297
  border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
3181
- border-radius: var(--r-1); background: var(--bg); padding: 12px 16px;
3298
+ border-radius: var(--r-1); background: var(--bg); padding: var(--space-2-75) var(--space-3);
3182
3299
  }
3183
3300
  .ds-247420 .ds-mermaid-diagram { overflow-x: auto; display: flex; justify-content: center; }
3184
3301
  .ds-247420 .ds-mermaid-diagram svg { max-width: 100%; height: auto; }
@@ -3187,7 +3304,7 @@
3187
3304
  font: inherit; font-size: var(--fs-xs); line-height: 1;
3188
3305
  background: color-mix(in oklab, var(--fg) 8%, transparent);
3189
3306
  color: var(--fg); border: none; border-radius: var(--r-1);
3190
- padding: 4px 8px; cursor: pointer;
3307
+ padding: var(--space-1) var(--space-2); cursor: pointer;
3191
3308
  }
3192
3309
  .ds-247420 .ds-mermaid-toggle:hover { background: color-mix(in oklab, var(--fg) 14%, transparent); }
3193
3310
 
@@ -3220,8 +3337,8 @@
3220
3337
  min-width: 0;
3221
3338
  }
3222
3339
  .ds-247420 .chat-code-head {
3223
- display: flex; align-items: center; gap: 10px;
3224
- padding: 8px 12px;
3340
+ display: flex; align-items: center; gap: var(--space-2-5);
3341
+ padding: var(--space-2) var(--space-2-75);
3225
3342
  background: color-mix(in oklab, var(--fg) 6%, var(--bg-2));
3226
3343
  border-bottom: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
3227
3344
  font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3);
@@ -3231,7 +3348,7 @@
3231
3348
  .ds-247420 .chat-code-head .name { color: var(--fg-2); font-weight: 500; }
3232
3349
  .ds-247420 .chat-code-head .spread { flex: 1; }
3233
3350
  .ds-247420 .chat-bubble.chat-code pre {
3234
- margin: 0; padding: 12px 16px; background: transparent;
3351
+ margin: 0; padding: var(--space-2-75) var(--space-3); background: transparent;
3235
3352
  font-family: var(--ff-mono); font-size: var(--fs-xs); line-height: 1.55;
3236
3353
  overflow-x: auto; color: var(--fg); border-radius: 0;
3237
3354
  }
@@ -3263,12 +3380,12 @@
3263
3380
  }
3264
3381
  .ds-247420 .chat-image img { display: block; width: 100%; height: auto; max-height: 360px; object-fit: cover; }
3265
3382
  .ds-247420 .chat-image .cap,
3266
- .ds-247420 .chat-image .caption { display: block; padding: 8px 12px; font-size: var(--fs-xs); color: var(--fg-3); font-family: var(--ff-mono); }
3383
+ .ds-247420 .chat-image .caption { display: block; padding: var(--space-2) var(--space-2-75); font-size: var(--fs-xs); color: var(--fg-3); font-family: var(--ff-mono); }
3267
3384
 
3268
3385
  .ds-247420 .chat-msg.you .chat-file,
3269
3386
  .ds-247420 .chat-msg .chat-file,
3270
3387
  .ds-247420 .chat-file {
3271
- display: flex; align-items: center; gap: 12px; padding: 12px 14px;
3388
+ display: flex; align-items: center; gap: var(--space-2-75); padding: var(--space-2-75) 14px;
3272
3389
  background: var(--bg-2); border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
3273
3390
  border-radius: var(--r-1); text-decoration: none; color: var(--fg);
3274
3391
  max-width: min(100%, 360px);
@@ -3281,12 +3398,12 @@
3281
3398
  background: var(--bg-3);
3282
3399
  color: var(--fg-2); border-radius: var(--r-0); flex-shrink: 0; font-family: var(--ff-mono);
3283
3400
  }
3284
- .ds-247420 .chat-file > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
3401
+ .ds-247420 .chat-file > div { display: flex; flex-direction: column; gap: var(--space-hair); min-width: 0; }
3285
3402
  .ds-247420 .chat-file .name {
3286
3403
  font-weight: 600; font-size: var(--fs-sm);
3287
3404
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
3288
3405
  }
3289
- .ds-247420 .chat-file .meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
3406
+ .ds-247420 .chat-file .meta { display: flex; flex-direction: column; gap: var(--space-hair); min-width: 0; flex: 1; }
3290
3407
  .ds-247420 .chat-file .size { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); }
3291
3408
  .ds-247420 .chat-file .go { font-family: var(--ff-mono); font-size: 16px; color: var(--fg-3); flex-shrink: 0; }
3292
3409
  .ds-247420 .chat-file:hover .go { color: var(--accent-ink); }
@@ -3302,7 +3419,7 @@
3302
3419
  }
3303
3420
  .ds-247420 .chat-msg:hover .chat-pdf { border-color: var(--rule); }
3304
3421
  .ds-247420 .chat-pdf-head {
3305
- display: flex; align-items: center; gap: 10px; padding: 10px 14px;
3422
+ display: flex; align-items: center; gap: var(--space-2-5); padding: var(--space-2-5) 14px;
3306
3423
  background: color-mix(in oklab, var(--fg) 5%, var(--bg-2));
3307
3424
  border-bottom: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
3308
3425
  }
@@ -3317,7 +3434,7 @@
3317
3434
  .ds-247420 .chat-msg.you .chat-link,
3318
3435
  .ds-247420 .chat-msg .chat-link,
3319
3436
  .ds-247420 .chat-link {
3320
- display: grid; grid-template-columns: 80px 1fr; gap: 12px; padding: 10px;
3437
+ display: grid; grid-template-columns: 80px 1fr; gap: var(--space-2-75); padding: var(--space-2-5);
3321
3438
  background: var(--bg-2);
3322
3439
  border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
3323
3440
  border-radius: var(--r-1); text-decoration: none; color: var(--fg);
@@ -3331,28 +3448,28 @@
3331
3448
  .ds-247420 .chat-link:not(:has(.thumb)):not(:has(img)) { grid-template-columns: 1fr; }
3332
3449
  .ds-247420 .chat-link .thumb,
3333
3450
  .ds-247420 .chat-link img.thumb { width: 80px; height: 80px; border-radius: var(--r-0); object-fit: cover; background: var(--bg-3) center/cover no-repeat; }
3334
- .ds-247420 .chat-link .meta { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
3451
+ .ds-247420 .chat-link .meta { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
3335
3452
  .ds-247420 .chat-link .host { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); text-transform: lowercase; }
3336
3453
  .ds-247420 .chat-link .title { font-weight: 600; font-size: var(--fs-sm); line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
3337
3454
  .ds-247420 .chat-link .desc { font-size: var(--fs-xs); color: var(--fg-2); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
3338
3455
 
3339
3456
  .ds-247420 .chat-meta {
3340
- display: flex; align-items: center; gap: 6px;
3457
+ display: flex; align-items: center; gap: var(--space-1-75);
3341
3458
  font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3);
3342
- padding: 0 6px; letter-spacing: 0.02em;
3459
+ padding: 0 var(--space-1-75); letter-spacing: 0.02em;
3343
3460
  }
3344
3461
  .ds-247420 .chat-meta .who { font-weight: 600; color: var(--fg-2); }
3345
3462
  .ds-247420 .chat-meta .who::after { content: ' ·'; color: var(--fg-3); font-weight: 400; }
3346
3463
  .ds-247420 .chat-meta .t { color: var(--fg-3); }
3347
- .ds-247420 .chat-meta .tick { color: var(--fg-3); margin-left: 2px; letter-spacing: -2px; font-family: var(--ff-mono); }
3464
+ .ds-247420 .chat-meta .tick { color: var(--fg-3); margin-left: var(--space-hair); letter-spacing: -2px; font-family: var(--ff-mono); }
3348
3465
  .ds-247420 .chat-meta .tick.read { color: var(--accent-ink); }
3349
3466
 
3350
3467
  .ds-247420 .chat-reactions {
3351
- display: flex; gap: 4px; flex-wrap: wrap; margin-top: 2px;
3468
+ display: flex; gap: var(--space-1); flex-wrap: wrap; margin-top: var(--space-hair);
3352
3469
  }
3353
3470
  .ds-247420 .chat-reactions .rxn {
3354
- display: inline-flex; align-items: center; gap: 4px;
3355
- padding: 2px 8px; background: var(--bg-2);
3471
+ display: inline-flex; align-items: center; gap: var(--space-1);
3472
+ padding: var(--space-hair) var(--space-2); background: var(--bg-2);
3356
3473
  border: 1px solid color-mix(in oklab, var(--fg) 10%, transparent);
3357
3474
  border-radius: var(--r-pill); font-size: var(--fs-xs);
3358
3475
  cursor: pointer; user-select: none;
@@ -3369,7 +3486,7 @@
3369
3486
  .ds-247420 .chat-reactions .rxn .n { font-family: var(--ff-mono); font-weight: 600; font-size: 11px; color: var(--fg-2); }
3370
3487
  .ds-247420 .chat-reactions .rxn.you .n { color: var(--accent-ink); }
3371
3488
 
3372
- .ds-247420 .chat-typing { display: inline-flex; gap: 4px; align-items: center; }
3489
+ .ds-247420 .chat-typing { display: inline-flex; gap: var(--space-1); align-items: center; }
3373
3490
  .ds-247420 .chat-typing span {
3374
3491
  width: 6px; height: 6px; border-radius: 50%; background: var(--fg-3);
3375
3492
  }
@@ -3437,7 +3554,7 @@
3437
3554
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--flame) 22%, transparent);
3438
3555
  }
3439
3556
  .ds-247420 .chat-composer textarea {
3440
- flex: 1; min-width: 0; padding: 8px 4px;
3557
+ flex: 1; min-width: 0; padding: var(--space-2) var(--space-1);
3441
3558
  background: none; color: var(--fg);
3442
3559
  border: none; border-radius: 0;
3443
3560
  font-family: inherit; font-size: var(--fs-sm);
@@ -3491,7 +3608,7 @@
3491
3608
  .ds-247420 .composer-btn { transition: none; }
3492
3609
  }
3493
3610
 
3494
- .ds-247420 .aicat-portrait { display: inline-flex; align-items: center; gap: 10px; padding: 4px 0; }
3611
+ .ds-247420 .aicat-portrait { display: inline-flex; align-items: center; gap: var(--space-2-5); padding: var(--space-1) 0; }
3495
3612
  .ds-247420 .aicat-face {
3496
3613
  width: 32px; height: 32px; font-size: 24px;
3497
3614
  display: inline-flex; align-items: center; justify-content: center;
@@ -3722,7 +3839,12 @@
3722
3839
  min-height: 120px;
3723
3840
  display: flex; align-items: center; justify-content: center;
3724
3841
  text-align: center; color: var(--fg-3);
3725
- transition: all var(--dur-snap) var(--ease);
3842
+ /* Explicit list, never `all` — the only things `.drop-zone.active` changes
3843
+ are the dashed border tone, the tinted fill and the label colour. `all`
3844
+ also animated padding/min-height/border-width, so a drop target visibly
3845
+ resized mid-drag instead of snapping. */
3846
+ transition: background var(--dur-snap) var(--ease), border-color var(--dur-snap) var(--ease),
3847
+ color var(--dur-snap) var(--ease);
3726
3848
  }
3727
3849
  .ds-247420 .drop-zone.active {
3728
3850
  border-color: var(--accent);
@@ -3762,7 +3884,7 @@
3762
3884
  border-radius: var(--r-2);
3763
3885
  box-shadow: var(--shadow-overlay);
3764
3886
  min-width: 160px;
3765
- z-index: calc(var(--z-overlay, 1000) + 1);
3887
+ z-index: var(--z-dropdown);
3766
3888
  padding: 4px 0;
3767
3889
  }
3768
3890
 
@@ -4141,7 +4263,7 @@
4141
4263
  position: absolute; top: -40px; left: 0;
4142
4264
  background: var(--fg); color: var(--bg);
4143
4265
  padding: 8px 16px; border-radius: var(--r-1);
4144
- text-decoration: none; z-index: var(--z-overlay, 1000);
4266
+ text-decoration: none; z-index: var(--z-top);
4145
4267
  }
4146
4268
  .ds-247420 .skip-to-main:focus { top: 10px; }
4147
4269
 
@@ -4261,7 +4383,7 @@
4261
4383
  padding: var(--space-3) var(--space-4);
4262
4384
  max-width: 320px;
4263
4385
  box-shadow: var(--shadow-overlay);
4264
- z-index: calc(var(--z-overlay, 1000) + 10);
4386
+ z-index: var(--z-toast);
4265
4387
  }
4266
4388
 
4267
4389
  @keyframes toast-slide-in {
@@ -4435,8 +4557,9 @@
4435
4557
  width: 280px; max-width: 80%;
4436
4558
  transform: translateX(-100%);
4437
4559
  transition: transform var(--dur-base, 240ms) var(--ease, ease);
4438
- /* Above the sticky chrome (z-header): scrim > chrome > content budget. */
4439
- z-index: calc(var(--z-header, 100) + 2);
4560
+ /* Drawer rung, above the sticky chrome it slides over. +1 puts the panel
4561
+ itself over its own scrim (--z-drawer), which is the layer below it. */
4562
+ z-index: calc(var(--z-drawer) + 1);
4440
4563
  background: var(--bg);
4441
4564
  border-right: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
4442
4565
  overflow-y: auto;
@@ -4477,8 +4600,9 @@
4477
4600
  display: none;
4478
4601
  position: absolute; inset: 0;
4479
4602
  background: color-mix(in oklab, var(--bg) 60%, transparent);
4480
- /* Above the sticky chrome so nav behind an open drawer is not clickable. */
4481
- z-index: calc(var(--z-header, 100) + 1);
4603
+ /* Above the sticky chrome so nav behind an open drawer is not clickable.
4604
+ Base of the drawer rung — the panel itself sits one above this. */
4605
+ z-index: var(--z-drawer);
4482
4606
  }
4483
4607
  @container (max-width: 900px) {
4484
4608
  .ds-247420 .app-body.side-open .app-side-scrim { display: block; }
@@ -4490,9 +4614,10 @@
4490
4614
  .ds-247420 .app-side-toggle {
4491
4615
  display: none;
4492
4616
  position: absolute; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
4493
- /* Above the sticky topbar/chrome (z-header) and the drawer/scrim so the
4494
- translucent blurred chrome never paints over or intercepts the toggle. */
4495
- z-index: calc(var(--z-header, 100) + 3);
4617
+ /* Above the sticky topbar/chrome and the drawer/scrim so the translucent
4618
+ blurred chrome never paints over or intercepts the toggle. Top of the
4619
+ drawer rung: scrim < panel < toggle. */
4620
+ z-index: calc(var(--z-drawer) + 2);
4496
4621
  /* 44x44 minimum hit area (WCAG 2.5.5 / Apple HIG) - 36px is below the
4497
4622
  reliable-tap threshold on touch. */
4498
4623
  width: 44px; height: 44px;
@@ -4594,7 +4719,7 @@
4594
4719
  /* Column resize handles: a thin keyboard-accessible separator pinned to the
4595
4720
  right edge of each chrome track; drag (or ArrowLeft/Right) writes a clamped
4596
4721
  inline --ws-*-w. */
4597
- .ds-247420 .ws-resizer { grid-row: 1 / -1; align-self: stretch; justify-self: end; width: 8px; margin-right: -4px; z-index: 5; cursor: col-resize; background: transparent; border: none; padding: 0; touch-action: none; }
4722
+ .ds-247420 .ws-resizer { grid-row: 1 / -1; align-self: stretch; justify-self: end; width: 8px; margin-right: -4px; z-index: var(--z-raised); cursor: col-resize; background: transparent; border: none; padding: 0; touch-action: none; }
4598
4723
  .ds-247420 .ws-resizer::after { content: ""; display: block; width: 2px; height: 100%; margin: 0 auto; background: transparent; transition: background var(--dur-snap) var(--ease); }
4599
4724
  .ds-247420 .ws-resizer:hover::after, .ds-247420 .ws-resizer:focus-visible::after { background: var(--accent); }
4600
4725
  .ds-247420 .ws-resizer:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: -2px; }
@@ -4783,7 +4908,7 @@
4783
4908
  .ds-247420 .ws-pane {
4784
4909
  position: fixed; inset: 0 0 0 auto;
4785
4910
  width: min(340px, 85vw);
4786
- z-index: 42; transform: translateX(110%);
4911
+ z-index: calc(var(--z-drawer) + 1); transform: translateX(110%);
4787
4912
  transition: transform var(--dur-base) var(--ease);
4788
4913
  }
4789
4914
  .ds-247420 .ws-shell.ws-pane-open .ws-pane { transform: translateX(0); width: min(340px, 85vw); }
@@ -4792,7 +4917,7 @@
4792
4917
  .ds-247420 .ws-pane-drawer-toggle { display: inline-flex; }
4793
4918
  /* Scrim is always present from this stage down so it FADES with the drawer
4794
4919
  instead of hard-appearing; pointer-events gate keeps it inert while closed. */
4795
- .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); }
4920
+ .ds-247420 .ws-scrim { display: block; opacity: 0; pointer-events: none; position: fixed; inset: 0; z-index: var(--z-drawer); background: color-mix(in srgb, var(--fg) 38%, transparent); transition: opacity var(--dur-base) var(--ease); }
4796
4921
  .ds-247420 .ws-shell.ws-sessions-open .ws-scrim, .ds-247420 .ws-shell.ws-pane-open .ws-scrim { opacity: 1; pointer-events: auto; }
4797
4922
  }
4798
4923
 
@@ -4814,7 +4939,7 @@
4814
4939
  /* Immune to the desktop collapse var (--ws-sessions-w:0px persisted from
4815
4940
  a desktop session would open an invisible 0-width drawer). */
4816
4941
  width: min(max(var(--ws-sessions-w), 280px), 80vw);
4817
- z-index: 42; transform: translateX(-110%);
4942
+ z-index: calc(var(--z-drawer) + 1); transform: translateX(-110%);
4818
4943
  transition: transform var(--dur-base) var(--ease);
4819
4944
  border-right: var(--bw-hair) solid var(--bg-3);
4820
4945
  overscroll-behavior: contain;
@@ -4841,7 +4966,9 @@
4841
4966
  grid-template-columns: minmax(0, 1fr);
4842
4967
  grid-template-areas: "content";
4843
4968
  }
4844
- .ds-247420 .ws-rail { position: fixed; inset: 0 auto 0 0; width: var(--ws-rail-w-collapsed); z-index: 40; }
4969
+ /* Persistent chrome, not a drawer: it stays put while the session/pane
4970
+ drawers slide over it, so it sits on the header rung below them. */
4971
+ .ds-247420 .ws-rail { position: fixed; inset: 0 auto 0 0; width: var(--ws-rail-w-collapsed); z-index: var(--z-header); }
4845
4972
  .ds-247420 .ws-rail .ws-rail-brand,
4846
4973
  .ds-247420 .ws-rail .ws-rail-action-label,
4847
4974
  .ds-247420 .ws-rail .ws-rail-item-label,
@@ -4965,7 +5092,7 @@
4965
5092
  }
4966
5093
 
4967
5094
  /* PhaseWalk */
4968
- .ds-247420 .ds-phasewalk { display: inline-flex; gap: 2px; vertical-align: middle; }
5095
+ .ds-247420 .ds-phasewalk { display: inline-flex; gap: var(--space-hair); vertical-align: middle; }
4969
5096
  .ds-247420 .ds-phasewalk-seg {
4970
5097
  width: 18px; height: 10px; border-radius: var(--r-hair);
4971
5098
  background: var(--bg-3); position: relative;
@@ -4974,6 +5101,10 @@
4974
5101
  .ds-247420 .ds-phasewalk-seg.is-gap { background: var(--warn); }
4975
5102
  /* Standalone PhaseWalk reserves headroom for the labels instead of letting
4976
5103
  them escape upward and overlap the element above. */
5104
+ /* 15px is load-bearing, not off-scale drift: it must equal the absolute
5105
+ `top: -15px` the label below is lifted by, so the label clears the segments
5106
+ without a gap. Snapping the pad to --space-3 (16px) alone would desync the
5107
+ pair. */
4977
5108
  .ds-247420 .ds-phasewalk { padding-top: 15px; }
4978
5109
  .ds-247420 .ds-phasewalk-lbl {
4979
5110
  position: absolute; top: -15px; left: 0;
@@ -4986,25 +5117,25 @@
4986
5117
 
4987
5118
  /* TreeNode */
4988
5119
  .ds-247420 .ds-tree-node {
4989
- padding: 5px 10px; border-left: var(--bw-rule) solid var(--bg-3);
4990
- margin: 2px 0 2px 16px; font-size: var(--fs-tiny);
5120
+ padding: var(--space-1-5) var(--space-2-5); border-left: var(--bw-rule) solid var(--bg-3);
5121
+ margin: var(--space-hair) 0 var(--space-hair) var(--space-3); font-size: var(--fs-tiny);
4991
5122
  min-width: 0; overflow-wrap: anywhere;
4992
5123
  }
4993
5124
  @media (max-width: 400px) {
4994
- .ds-247420 .ds-tree-node { margin-left: 8px; padding-left: 8px; }
5125
+ .ds-247420 .ds-tree-node { margin-left: var(--space-2); padding-left: var(--space-2); }
4995
5126
  }
4996
5127
  .ds-247420 .ds-tree-node.is-phase { border-color: var(--accent); background: var(--bg-3); font-weight: 600; }
4997
5128
  .ds-247420 .ds-tree-node.is-deviation { border-color: var(--warn); background: var(--danger-surface); color: var(--warn); }
4998
5129
  .ds-247420 .ds-tree-node.is-mutable-resolve { border-color: var(--success); }
4999
5130
  .ds-247420 .ds-tree-node.is-prd-add { border-color: var(--amber); }
5000
- .ds-247420 .ds-tree-node-ts { margin-right: 8px; color: var(--fg-3); }
5001
- .ds-247420 .ds-tree-node-pills { margin-left: 6px; }
5002
- .ds-247420 .ds-tree-node-reason { margin-top: 2px; color: var(--fg-2); }
5003
- .ds-247420 .ds-tree-node-deviation { margin-top: 2px; }
5004
- .ds-247420 .ds-tree-node-residuals { margin-top: 2px; color: var(--fg-3); }
5131
+ .ds-247420 .ds-tree-node-ts { margin-right: var(--space-2); color: var(--fg-3); }
5132
+ .ds-247420 .ds-tree-node-pills { margin-left: var(--space-1-75); }
5133
+ .ds-247420 .ds-tree-node-reason { margin-top: var(--space-hair); color: var(--fg-2); }
5134
+ .ds-247420 .ds-tree-node-deviation { margin-top: var(--space-hair); }
5135
+ .ds-247420 .ds-tree-node-residuals { margin-top: var(--space-hair); color: var(--fg-3); }
5005
5136
 
5006
5137
  /* BarRow */
5007
- .ds-247420 .ds-bar-row { display: flex; align-items: center; gap: 8px; margin: 3px 0; font-size: var(--fs-tiny); }
5138
+ .ds-247420 .ds-bar-row { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-half) 0; font-size: var(--fs-tiny); }
5008
5139
  .ds-247420 .ds-bar-row-label { width: 100px; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
5009
5140
  .ds-247420 .ds-bar-bg { flex: 1; min-width: 60px; background: var(--bg-3); border-radius: var(--r-hair); height: 6px; overflow: hidden; }
5010
5141
  .ds-247420 .ds-bar-fill { background: var(--fg-3); height: 100%; border-radius: var(--r-hair); }
@@ -5023,11 +5154,11 @@
5023
5154
  .ds-247420 .ds-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-1); }
5024
5155
  }
5025
5156
  .ds-247420 .ds-stats-grid-empty { padding: var(--space-3); color: var(--fg-3); font-size: var(--fs-tiny); }
5026
- .ds-247420 .ds-stat { min-width: 0; background: var(--bg-3); border-radius: var(--r-0); padding: 10px 12px; }
5157
+ .ds-247420 .ds-stat { min-width: 0; background: var(--bg-3); border-radius: var(--r-0); padding: var(--space-2-5) var(--space-2-75); }
5027
5158
  .ds-247420 .ds-stat-val { font-size: clamp(18px, 5cqi, 22px); font-weight: 700; color: var(--accent-ink); overflow-wrap: anywhere; }
5028
5159
  .ds-247420 .ds-stat-val.rate-big { font-size: clamp(24px, 7cqi, 32px); color: var(--success); }
5029
5160
  .ds-247420 .ds-stat-val.err-rate { font-size: clamp(24px, 7cqi, 32px); color: var(--warn); }
5030
- .ds-247420 .ds-stat-lbl { font-size: var(--fs-micro); color: var(--fg-3); margin-top: 2px; }
5161
+ .ds-247420 .ds-stat-lbl { font-size: var(--fs-micro); color: var(--fg-3); margin-top: var(--space-hair); }
5031
5162
 
5032
5163
  /* RateCell — tone-colored numeric table cell (success-rate / percentile-latency
5033
5164
  columns), ported from docstudio's endpointsView() success-rate coloring.
@@ -5044,20 +5175,38 @@
5044
5175
  .ds-247420 .ds-inline-row { display: flex; align-items: center; gap: var(--space-2, 8px); }
5045
5176
 
5046
5177
  /* SubGrid */
5047
- .ds-247420 .ds-sub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 6px; margin-top: 8px; }
5178
+ .ds-247420 .ds-sub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: var(--space-1-75); margin-top: var(--space-2); }
5048
5179
  .ds-247420 .ds-sub-grid-empty { padding: var(--space-3); color: var(--fg-3); font-size: var(--fs-tiny); }
5049
5180
  .ds-247420 .ds-sub-btn {
5050
- padding: 6px 10px; background: var(--bg-3); border: var(--bw-hair) solid var(--bg-3);
5181
+ padding: var(--space-1-75) var(--space-2-5); background: var(--bg-3); border: var(--bw-hair) solid var(--bg-3);
5051
5182
  border-radius: var(--r-0); font-size: var(--fs-tiny); cursor: pointer; color: var(--fg);
5052
5183
  text-align: left; font-family: var(--ff-body);
5053
5184
  }
5054
5185
  .ds-247420 .ds-sub-btn:hover { border-color: var(--accent); color: var(--accent-ink); }
5055
5186
  .ds-247420 .ds-sub-btn span { display: block; font-size: 18px; font-weight: 700; color: var(--accent-ink); }
5056
5187
 
5057
- /* SessionRow — base .ds-session-row (layout, hover/focus/active states,
5058
- rail-tone indicators) is canonically defined in chat.css alongside the
5059
- rest of the chat session-list component; this file only carries the
5060
- dev/admin-row sub-parts (id/counts/devcnt/span) that decorate it. */
5188
+ /* SessionRow — the RICH treatment (hover/focus/active, rail tones, nesting,
5189
+ inline rename/delete) lives in chat.css with the rest of the chat session
5190
+ list. But SessionRow is part of this data-density family and is used by kits
5191
+ that never link chat.css (gm_inspector links only colors_and_type +
5192
+ app-shell + editor-primitives), where the component rendered with NO layout
5193
+ at all: gap resolved to `normal`, so id/counts/devcnt/phasewalk/span all
5194
+ butted together at 0px. The layout floor therefore belongs here, next to the
5195
+ sub-parts it positions, so the component is never shipped shapeless.
5196
+ chat.css still layers its interactive states on top; these declarations are
5197
+ identical to the ones there, so a kit loading both gets the same result. */
5198
+ .ds-247420 .ds-session-row {
5199
+ position: relative; display: flex; align-items: center; gap: var(--space-2);
5200
+ width: 100%; padding: var(--space-2); min-height: 52px; margin-bottom: var(--space-hair);
5201
+ background: transparent; border: none; border-radius: var(--r-1);
5202
+ text-align: left; color: var(--fg);
5203
+ }
5204
+ /* Only an interactive row gets the pointer affordance (chat.css sets cursor
5205
+ unconditionally because every row there is clickable; here rows are often
5206
+ static readouts). */
5207
+ .ds-247420 .ds-session-row[role="button"], .ds-247420 a.ds-session-row { cursor: pointer; }
5208
+
5209
+ /* Sub-parts that decorate the row above. */
5061
5210
  .ds-247420 .ds-session-row-id {
5062
5211
  font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--accent-ink);
5063
5212
  flex: 0 1 160px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
@@ -5076,7 +5225,7 @@
5076
5225
  /* DevRow */
5077
5226
  .ds-247420 .ds-dev-row {
5078
5227
  background: var(--danger-surface); border-left: var(--bw-chunk) solid var(--warn);
5079
- padding: 8px 12px; margin: 4px 0; border-radius: var(--r-hair); font-size: var(--fs-tiny);
5228
+ padding: var(--space-2) var(--space-2-75); margin: var(--space-1) 0; border-radius: var(--r-hair); font-size: var(--fs-tiny);
5080
5229
  }
5081
5230
  .ds-247420 .ds-dev-row strong { color: var(--warn); }
5082
5231
 
@@ -5093,17 +5242,17 @@
5093
5242
  /* Embedded in a WM window the viewport calc is meaningless — fill the container. */
5094
5243
  .ds-247420 .fd-root .ds-live-log { height: 100%; max-height: none; min-height: 0; flex: 1 1 auto; }
5095
5244
  .ds-247420 .ds-live-log-empty { height: auto; min-height: 0; padding: var(--space-3); color: var(--fg-3); }
5096
- .ds-247420 .ds-live-log-entry { padding: 2px 8px; border-bottom: var(--bw-hair) solid var(--bg-3); overflow-wrap: anywhere; }
5245
+ .ds-247420 .ds-live-log-entry { padding: var(--space-hair) var(--space-2); border-bottom: var(--bw-hair) solid var(--bg-3); overflow-wrap: anywhere; }
5097
5246
  .ds-247420 .ds-live-log-entry:hover { background: var(--bg-3); }
5098
- .ds-247420 .ds-live-log-ts { margin-right: 6px; color: var(--fg-3); }
5099
- .ds-247420 .ds-live-log-subtag { margin-right: 6px; padding: 0 5px; border-radius: var(--r-hair); font-size: var(--fs-micro); }
5100
- .ds-247420 .ds-live-log-preview { margin-left: 6px; color: var(--fg-3); word-break: break-word; }
5247
+ .ds-247420 .ds-live-log-ts { margin-right: var(--space-1-75); color: var(--fg-3); }
5248
+ .ds-247420 .ds-live-log-subtag { margin-right: var(--space-1-75); padding: 0 var(--space-1-5); border-radius: var(--r-hair); font-size: var(--fs-micro); }
5249
+ .ds-247420 .ds-live-log-preview { margin-left: var(--space-1-75); color: var(--fg-3); word-break: break-word; }
5101
5250
 
5102
5251
  /* Touch floors for the dense controls (not covered by the mobile width blocks). */
5103
5252
  @media (pointer: coarse) {
5104
5253
  .ds-247420 .ds-sub-btn { min-height: 44px; }
5105
5254
  .ds-247420 .ds-session-row { min-height: 44px; }
5106
- .ds-247420 .ds-live-log-entry { padding-block: 6px; }
5255
+ .ds-247420 .ds-live-log-entry { padding-block: var(--space-1-75); }
5107
5256
  }
5108
5257
 
5109
5258
 
@@ -5126,11 +5275,121 @@
5126
5275
  /* == appended: ui-kits == */
5127
5276
  /* ============================================================
5128
5277
  ui_kit responsive helpers (kits-grids sweep) */
5129
- .ds-247420 .ds-section-pad { padding: clamp(6px, 1.2vw, 16px); }
5130
- .ds-247420 .ds-panel-gap { margin: var(--space-2) 0; }
5131
- .ds-247420 .ds-panel-duo { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); margin: var(--space-2) 0; }
5278
+ /* App-surface root. .ds-section carries a --space-8 (96px) editorial rhythm
5279
+ that is correct between landing-page sections and wrong as the ROOT wrapper
5280
+ of an Operate surface, where .app-main has already padded the region used
5281
+ there it just pushes the page heading a screen-inch down and adds dead space
5282
+ below the last panel. This is the app-mode counterpart: no outer margin, and
5283
+ it owns the heading -> lede -> first-panel cadence so each kit stops
5284
+ re-deriving it. Pair with .ds-section-pad for the shadow inset. */
5285
+ .ds-247420 .ds-app-surface { margin: 0; display: flow-root; }
5286
+ /* Operate surfaces run the compact heading ceiling. --fs-h1 tops out at 64px,
5287
+ a display size that makes the page TITLE outweigh the data it labels; the
5288
+ app scale (--fs-h1-app, 22-30px) is what these tokens exist for. Applied
5289
+ here rather than as a data-attribute on each kit shell so any surface using
5290
+ this root gets the app voice without a per-kit opt-in that kits forget. */
5291
+ /* Descendant, not direct-child: a kit that wraps its title in a head row (an
5292
+ h1 beside a theme toggle, say) still gets the app voice. The direct-child
5293
+ form silently missed exactly that shape and left those titles at the 64px
5294
+ display ceiling -- the surface opted in but the rule did not reach the
5295
+ heading. Nested .ds-section content is unaffected because nothing re-raises
5296
+ the size below this point. */
5297
+ .ds-247420 .ds-app-surface h1, .ds-247420 .ds-app-surface .t-h1 { font-size: var(--fs-h1-app); line-height: 1.15; }
5298
+ .ds-247420 .ds-app-surface h2, .ds-247420 .ds-app-surface .t-h2 { font-size: var(--fs-h2-app); }
5299
+ .ds-247420 .ds-app-surface h3, .ds-247420 .ds-app-surface .t-h3 { font-size: var(--fs-h3-app); }
5300
+ /* The lede is supporting chrome under an app title, not a marketing stand-first:
5301
+ it drops to body size and keeps a readable measure instead of --fs-xl. */
5302
+ .ds-247420 .ds-app-surface > .lede, .ds-247420 .ds-app-surface > .t-lede { font-size: var(--fs-body); max-width: 60ch; }
5303
+ .ds-247420 .ds-app-surface > h1,
5304
+ .ds-247420 .ds-app-surface > h2 { margin-bottom: var(--space-2); }
5305
+ /* The lede belongs to the heading above it, so it sits tight to that heading
5306
+ and separates generously from the content it introduces. */
5307
+ .ds-247420 .ds-app-surface > .lede,
5308
+ .ds-247420 .ds-app-surface > .t-lede { margin-bottom: calc(var(--space-6) * var(--density)); }
5309
+ /* No leading margin on the first block or trailing margin on the last — the
5310
+ shell owns the region's outer edges. */
5311
+ .ds-247420 .ds-app-surface > :first-child { margin-top: 0; }
5312
+ .ds-247420 .ds-app-surface > :last-child { margin-bottom: 0; }
5313
+
5314
+ /* Section padding is the shell's job (.app-main owns --pad-x). This only adds
5315
+ the small inset a kit root needs so panel shadows are not clipped by the
5316
+ scroll container, and it scales with density like every other app metric —
5317
+ the old clamp(6px,1.2vw,16px) sized against the VIEWPORT inside a
5318
+ container-query layout that measures everything else in cqi. */
5319
+ .ds-247420 .ds-section-pad { padding: calc(var(--space-1) * var(--density)); }
5320
+
5321
+ /* Separation between sibling panels. This is the OUTER rhythm: it must exceed
5322
+ .panel-body's 16px inner sibling gap, otherwise proximity says two unrelated
5323
+ panels belong together more tightly than two rows inside one panel. The old
5324
+ value was --space-2 (8px), which inverted exactly that relationship and made
5325
+ the class named "gap" the only rule in the system that removed separation. */
5326
+ .ds-247420 .ds-panel-gap { margin: calc(var(--space-5) * var(--density)) 0; }
5327
+ /* Density-scaled sibling rhythm for any run of stacked panels, so the cadence
5328
+ holds without each kit re-declaring a margin per panel. */
5329
+ .ds-247420 .ds-panel-gap + .ds-panel-gap { margin-top: calc(var(--space-5) * var(--density)); }
5330
+
5331
+ /* A panel inside a gap-owning parent (grid/flex row). .panel ships a 24px
5332
+ bottom margin for the stacked case; inside a row that margin fights the
5333
+ parent's gap and makes the last row of a wrapping grid sit on a different
5334
+ rhythm than the columns. The container owns separation, so the panel drops
5335
+ its own. Also stretches to the row's height so a short panel next to a tall
5336
+ one does not leave a ragged bottom edge. */
5337
+ /* Drops only the panel's own bottom margin — the row container owns separation.
5338
+ Height is deliberately NOT forced here: whether panels in a row should match
5339
+ heights depends on whether they are a SET (trio: equal peers, matching edge
5340
+ reads as one band) or a PAIR of different things (duo: a 4-bar chart beside a
5341
+ 5-row table, where forcing equality just relocates the dead space inside the
5342
+ shorter panel). Each container decides via align-items below. */
5343
+ .ds-247420 .ds-panel-flush { margin-bottom: 0; }
5344
+
5345
+ /* Paired panels. Container-relative (the shell is the CQ container), so the
5346
+ split collapses when the PANELS are cramped rather than when the viewport
5347
+ crosses an arbitrary width — with a sidebar open those are far apart.
5348
+ minmax(0,1fr) lets a scrolling table shrink instead of forcing overflow. */
5349
+ .ds-247420 .ds-panel-duo {
5350
+ display: grid;
5351
+ grid-template-columns: repeat(2, minmax(0, 1fr));
5352
+ gap: calc(var(--space-3) * var(--density));
5353
+ margin: calc(var(--space-5) * var(--density)) 0;
5354
+ /* A duo pairs two DIFFERENT things (a 4-bar chart beside a 5-row table).
5355
+ Stretching them to a common height does not create equality, it just moves
5356
+ the shorter panel's dead space inside its own body. Each takes its natural
5357
+ height and they align at the top, where the eye actually starts. */
5358
+ align-items: start;
5359
+ }
5360
+ @container (max-width: 900px) {
5361
+ .ds-247420 .ds-panel-duo { grid-template-columns: minmax(0, 1fr); }
5362
+ }
5363
+ /* Fallback for kit roots that are not themselves a container (older kit shells
5364
+ mount outside .app/.ds-stage); harmless where the CQ rule already applies. */
5365
+ @media (max-width: 760px) {
5366
+ .ds-247420 .ds-panel-duo { grid-template-columns: minmax(0, 1fr); }
5367
+ }
5368
+
5369
+ /* Three equal reference panels. Real grid tracks, NOT percentage flex-basis:
5370
+ three 33.33% bases plus two gaps exceed 100% and wrap the last panel onto
5371
+ its own row. Steps 3 -> 2 -> 1 on container width so the panels reflow when
5372
+ they are actually cramped rather than at a viewport number that ignores how
5373
+ much chrome the shell is holding. */
5374
+ .ds-247420 .ds-panel-trio {
5375
+ display: grid;
5376
+ grid-template-columns: repeat(3, minmax(0, 1fr));
5377
+ gap: calc(var(--space-3) * var(--density));
5378
+ margin: calc(var(--space-5) * var(--density)) 0;
5379
+ /* A trio IS a set of equal peers, so a shared bottom edge reads as one band
5380
+ rather than three ragged cards — the opposite call from .ds-panel-duo
5381
+ above, and the reason these are two classes and not one. */
5382
+ align-items: stretch;
5383
+ }
5384
+ .ds-247420 .ds-panel-trio > .panel { height: 100%; }
5385
+ @container (max-width: 1100px) {
5386
+ .ds-247420 .ds-panel-trio { grid-template-columns: repeat(2, minmax(0, 1fr)); }
5387
+ }
5388
+ @container (max-width: 720px) {
5389
+ .ds-247420 .ds-panel-trio { grid-template-columns: minmax(0, 1fr); }
5390
+ }
5132
5391
  @media (max-width: 760px) {
5133
- .ds-247420 .ds-panel-duo { grid-template-columns: 1fr; }
5392
+ .ds-247420 .ds-panel-trio { grid-template-columns: minmax(0, 1fr); }
5134
5393
  }
5135
5394
  /* wide dense rows/tables scroll inside their panel, never the page */
5136
5395
  .ds-247420 .ds-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
@@ -5143,7 +5402,7 @@
5143
5402
  margin: var(--space-3) auto;
5144
5403
  background: var(--bg-2);
5145
5404
  border-radius: var(--r-2);
5146
- padding: clamp(16px, 5vw, 64px);
5405
+ padding: clamp(var(--space-3), 5vw, var(--space-7));
5147
5406
  box-sizing: border-box;
5148
5407
  display: flex;
5149
5408
  overflow: hidden;
@@ -5158,18 +5417,39 @@
5158
5417
  }
5159
5418
  .ds-247420 .ds-deck-slide { flex: 1; display: flex; min-width: 0; }
5160
5419
  .ds-247420 .ds-deck-controls {
5420
+ /* 14px sits between --space-2-75 (12) and --space-3 (16) with no tier; it is
5421
+ the deck control spacing tuned against the mono glyph run. */
5161
5422
  display: flex; align-items: center; justify-content: center; gap: 14px;
5162
- padding: 8px; font-family: var(--ff-mono); font-size: var(--fs-sm);
5423
+ padding: var(--space-2); font-family: var(--ff-mono); font-size: var(--fs-sm);
5163
5424
  }
5164
5425
  .ds-247420 .ds-deck-count { color: var(--fg-3); }
5165
5426
  @media (pointer: coarse) {
5166
5427
  .ds-247420 .ds-deck-controls .btn { min-height: 44px; min-width: 44px; }
5167
5428
  }
5429
+ /* Kit small-label voice — one local composition of the house `.t-label` recipe
5430
+ (base.css) for every eyebrow/label in the appended kit blocks below. These
5431
+ previously each restated the four declarations with drifted tracking
5432
+ (0.1em / 0.06em / --tr-label) and drifted size (11px / --fs-micro); they now
5433
+ share --fs-nano + --tr-label. Members declare only their real differences.
5434
+ --fs-nano because these are dense kit chrome, never body or UI text. */
5435
+ .ds-247420 .ds-slide-eyebrow,
5436
+ .ds-247420 .ds-field-eyebrow,
5437
+ .ds-247420 .ds-auth-field-label,
5438
+ .ds-247420 .ds-lightbox-tag {
5439
+ font-family: var(--ff-mono);
5440
+ font-size: var(--fs-nano);
5441
+ letter-spacing: var(--tr-label);
5442
+ text-transform: uppercase;
5443
+ color: var(--panel-text-3);
5444
+ }
5445
+
5446
+ /* Deliberate overrides: the deck slide eyebrow sits on the app --fg ramp (it is
5447
+ full-bleed slide chrome, not panel chrome) and owns its own bottom gutter. */
5168
5448
  .ds-247420 .ds-slide-eyebrow {
5169
- font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.1em;
5170
- text-transform: uppercase; color: var(--fg-3); margin-bottom: clamp(12px, 2.5cqw, 24px);
5449
+ color: var(--fg-3);
5450
+ margin-bottom: clamp(var(--space-2-75), 2.5cqw, var(--space-4));
5171
5451
  }
5172
- .ds-247420 .ds-slide-col { display: flex; flex-direction: column; justify-content: center; gap: clamp(12px, 2.5cqw, 24px); min-width: 0; }
5452
+ .ds-247420 .ds-slide-col { display: flex; flex-direction: column; justify-content: center; gap: clamp(var(--space-2-75), 2.5cqw, var(--space-4)); min-width: 0; }
5173
5453
  .ds-247420 .ds-slide-col--start { align-items: flex-start; }
5174
5454
  .ds-247420 .ds-slide-col--narrow { max-width: 38ch; }
5175
5455
  .ds-247420 .ds-slide-col--quote { max-width: 42ch; }
@@ -5183,15 +5463,17 @@
5183
5463
  font-size: clamp(var(--fs-h3), 4.5cqw, var(--fs-h1));
5184
5464
  line-height: var(--lh-snug); color: var(--fg); font-weight: 500; min-width: 0;
5185
5465
  }
5186
- .ds-247420 .ds-slide-h1--lead { margin-bottom: 12px; }
5466
+ .ds-247420 .ds-slide-h1--lead { margin-bottom: var(--space-2-75); }
5187
5467
  .ds-247420 .ds-slide-quote-body {
5188
5468
  font-size: clamp(var(--fs-lg), 3.5cqw, var(--fs-h2));
5189
5469
  line-height: var(--lh-snug); color: var(--fg); font-weight: 400; font-style: italic;
5190
5470
  }
5191
5471
  .ds-247420 .ds-slide-cite { font-family: var(--ff-mono); font-size: var(--fs-sm); color: var(--fg-3); }
5192
5472
  .ds-247420 .ds-slide-bullet {
5193
- display: flex; gap: clamp(8px, 2vw, 18px); align-items: baseline;
5194
- border-bottom: 1px solid var(--rule); padding: 12px 0; flex-wrap: wrap;
5473
+ /* 18px ceiling has no tier (--space-3 is 16, --space-3-5 is 20); it is the
5474
+ bullet key/value split tuned against the clamp(56px,18%,100px) key column. */
5475
+ display: flex; gap: clamp(var(--space-2), 2vw, 18px); align-items: baseline;
5476
+ border-bottom: 1px solid var(--rule); padding: var(--space-2-75) 0; flex-wrap: wrap;
5195
5477
  }
5196
5478
  .ds-247420 .ds-slide-bullet-key {
5197
5479
  flex: 0 1 clamp(56px, 18%, 100px); min-width: 0;
@@ -5199,19 +5481,36 @@
5199
5481
  color: var(--slide-accent, var(--accent-ink));
5200
5482
  }
5201
5483
  .ds-247420 .ds-slide-bullet-val { color: var(--fg-2); font-size: var(--fs-lg); min-width: 0; }
5202
- .ds-247420 .ds-slide-split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(12px, 3vw, 32px); margin-top: 12px; }
5484
+ .ds-247420 .ds-slide-split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(var(--space-2-75), 3vw, var(--space-5)); margin-top: var(--space-2-75); }
5203
5485
  @media (max-width: 760px) {
5204
5486
  .ds-247420 .ds-slide-split { grid-template-columns: 1fr; }
5205
5487
  }
5206
5488
  .ds-247420 .ds-slide-split-cell {
5207
- padding: 18px; background: var(--bg-2); border-radius: var(--r-2);
5489
+ padding: var(--space-3-5); background: var(--bg-2); border-radius: var(--r-2);
5208
5490
  color: var(--fg-2); font-size: var(--fs-lg); line-height: var(--lh-base); min-width: 0;
5209
5491
  }
5210
- .ds-247420 .ds-slide-split-cell--accent { border-left: 3px solid var(--slide-accent, var(--accent)); }
5492
+ /* DELIBERATE accent spine this modifier's only job is to mark the emphasized
5493
+ half of a split slide (see ui_kits/slide_deck/app.js), so the rule is the
5494
+ whole component, not decoration on a card. Routed through the house
5495
+ .panel-spine idiom (::before rail at --bw-chunk, squared leading corners)
5496
+ instead of an off-scale 3px border-left. */
5497
+ .ds-247420 .ds-slide-split-cell--accent {
5498
+ position: relative;
5499
+ padding-left: calc(var(--space-3-5) + var(--bw-chunk));
5500
+ border-radius: 0 var(--r-2) var(--r-2) 0;
5501
+ }
5502
+ .ds-247420 .ds-slide-split-cell--accent::before {
5503
+ content: ''; position: absolute; left: 0; top: 0; bottom: 0;
5504
+ width: var(--bw-chunk); background: var(--slide-accent, var(--accent));
5505
+ border-radius: var(--bw-chunk) 0 0 var(--bw-chunk);
5506
+ }
5211
5507
 
5212
5508
  /* --- error 404 --------------------------------------------- */
5213
5509
  .ds-247420 .ds-err-hero {
5214
- padding: clamp(16px, 5vw, 36px) clamp(12px, 4vw, 22px);
5510
+ /* 36px/22px clamp ceilings and the 14px gap are off-scale on purpose: this
5511
+ hero is centred around a clamp(56px,20vw,120px) numeral and the insets are
5512
+ tuned to it, not to the panel rhythm the --space-* scale encodes. */
5513
+ padding: clamp(var(--space-3), 5vw, 36px) clamp(var(--space-2-75), 4vw, 22px);
5215
5514
  text-align: center; display: flex; flex-direction: column; gap: 14px; align-items: center;
5216
5515
  }
5217
5516
  .ds-247420 .ds-err-numeral {
@@ -5219,25 +5518,25 @@
5219
5518
  line-height: 1; color: var(--panel-text-3); letter-spacing: -0.03em;
5220
5519
  }
5221
5520
  .ds-247420 .ds-err-path {
5222
- display: inline-flex; gap: 6px; align-items: baseline; flex-wrap: wrap; max-width: 100%;
5521
+ display: inline-flex; gap: var(--space-1-75); align-items: baseline; flex-wrap: wrap; max-width: 100%;
5223
5522
  font-family: var(--ff-mono); font-size: 13px; color: var(--panel-text-2);
5224
- background: var(--panel-1); padding: 6px 12px; border-radius: var(--r-0);
5523
+ background: var(--panel-1); padding: var(--space-1-75) var(--space-2-75); border-radius: var(--r-0);
5225
5524
  overflow-wrap: anywhere; word-break: break-all;
5226
5525
  }
5227
5526
 
5228
5527
  /* --- gallery ------------------------------------------------ */
5229
5528
  .ds-247420 .ds-tile-grid {
5230
- padding: clamp(8px, 2.5vw, 16px);
5231
- display: grid; grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr)); gap: 8px;
5529
+ padding: clamp(var(--space-2), 2.5vw, var(--space-3));
5530
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr)); gap: var(--space-2);
5232
5531
  }
5233
5532
  .ds-247420 .ds-tile-grid--tight { grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); }
5234
5533
  .ds-247420 .ds-swatch-grid {
5235
- padding: clamp(8px, 2.5vw, 16px);
5236
- display: grid; grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr)); gap: 12px;
5534
+ padding: clamp(var(--space-2), 2.5vw, var(--space-3));
5535
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr)); gap: var(--space-2-75);
5237
5536
  }
5238
5537
  .ds-247420 .ds-gallery-tile {
5239
- cursor: pointer; display: flex; flex-direction: column; gap: 6px;
5240
- padding: 12px; border-radius: var(--r-1); min-height: clamp(120px, 18vw, 160px);
5538
+ cursor: pointer; display: flex; flex-direction: column; gap: var(--space-1-75);
5539
+ padding: var(--space-2-75); border-radius: var(--r-1); min-height: clamp(120px, 18vw, 160px);
5241
5540
  border: 0; text-align: left; font: inherit; color: inherit;
5242
5541
  background: var(--tile-tone, var(--panel-1));
5243
5542
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
@@ -5251,20 +5550,23 @@
5251
5550
  .ds-247420 .ds-lightbox {
5252
5551
  position: fixed; inset: 0; background: var(--scrim);
5253
5552
  display: flex; align-items: center; justify-content: center;
5254
- padding: clamp(12px, 4vw, 32px);
5255
- padding-bottom: max(clamp(12px, 4vw, 32px), env(safe-area-inset-bottom));
5256
- z-index: 50;
5553
+ padding: clamp(var(--space-2-75), 4vw, var(--space-5));
5554
+ padding-bottom: max(clamp(var(--space-2-75), 4vw, var(--space-5)), env(safe-area-inset-bottom));
5555
+ z-index: var(--z-modal);
5257
5556
  }
5258
5557
  .ds-247420 .ds-lightbox-card {
5259
- background: var(--panel-0); border-radius: var(--r-2); padding: clamp(16px, 4vw, 28px);
5558
+ /* 28px ceiling has no tier (--space-4 is 24, --space-5 is 32); it is the
5559
+ lightbox card inset tuned against the min(520px,100%) card width. */
5560
+ background: var(--panel-0); border-radius: var(--r-2); padding: clamp(var(--space-3), 4vw, 28px);
5260
5561
  width: min(520px, 100%); min-width: 0;
5261
5562
  max-height: calc(100vh - 24px);
5262
5563
  max-height: calc(100dvh - 24px);
5263
5564
  overflow: auto;
5264
- display: flex; flex-direction: column; gap: 14px;
5565
+ display: flex; flex-direction: column; gap: 14px; /* off-scale, matches the card inset above */
5265
5566
  }
5266
5567
  .ds-247420 .ds-lightbox-preview {
5267
- padding: clamp(16px, 6vw, 36px); border-radius: var(--r-1); text-align: center;
5568
+ /* 36px ceiling has no tier (--space-5 is 32, --space-6 is 48). */
5569
+ padding: clamp(var(--space-3), 6vw, 36px); border-radius: var(--r-1); text-align: center;
5268
5570
  font-family: var(--ff-mono); white-space: pre-line; font-size: clamp(16px, 5vw, 24px);
5269
5571
  background: var(--tile-tone, var(--panel-1));
5270
5572
  }
@@ -5274,25 +5576,31 @@
5274
5576
  @media (max-width: 480px) {
5275
5577
  .ds-247420 .ds-topbar-search { flex-basis: 100%; }
5276
5578
  }
5277
- .ds-247420 .ds-empty-state { padding: clamp(16px, 5vw, 24px); text-align: center; color: var(--panel-text-3); }
5579
+ .ds-247420 .ds-empty-state { padding: clamp(var(--space-3), 5vw, var(--space-4)); text-align: center; color: var(--panel-text-3); }
5278
5580
  .ds-247420 .ds-empty-state-glyph { font-size: clamp(24px, 6vw, 32px); }
5279
- .ds-247420 .ds-empty-state-msg { margin: 6px 0; }
5581
+ .ds-247420 .ds-empty-state-msg { margin: var(--space-1-75) 0; }
5280
5582
  .ds-247420 .ds-empty-state-hint { margin: 0; font-size: var(--fs-sm); }
5281
5583
 
5282
5584
  /* --- system primer ------------------------------------------ */
5585
+ /* The three primer panels below share one fluid inset,
5586
+ clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px), and a 14/18px gap. None of
5587
+ 10/14/18 is a --space-* tier (the scale jumps 8 -> 10 -> 12 -> 16 -> 20) and
5588
+ the three values are tuned as a set against the 64px label columns, so the
5589
+ panels stay optically identical to each other. Snapping any one of them
5590
+ desyncs the family; they are deliberate literals, not un-migrated drift. */
5283
5591
  .ds-247420 .ds-swatch-grid-sm {
5284
5592
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(110px, 100%), 1fr));
5285
- gap: 12px; padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px);
5593
+ gap: var(--space-2-75); padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px);
5286
5594
  }
5287
5595
  .ds-247420 .ds-swatch-grid-lg { grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); }
5288
- .ds-247420 .ds-swatch-col { display: flex; flex-direction: column; gap: 6px; }
5596
+ .ds-247420 .ds-swatch-col { display: flex; flex-direction: column; gap: var(--space-1-75); }
5289
5597
  .ds-247420 .ds-swatch-chip { height: 48px; border-radius: var(--r-1); border: 1px solid var(--rule); background: var(--swatch, var(--panel-1)); }
5290
5598
  .ds-247420 .ds-swatch-chip--big { height: 64px; }
5291
5599
  .ds-247420 .ds-swatch-name { font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
5292
5600
  .ds-247420 .ds-type-panel { padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px); display: flex; flex-direction: column; gap: 14px; }
5293
5601
  .ds-247420 .ds-type-row {
5294
5602
  display: flex; align-items: baseline; gap: 14px;
5295
- border-bottom: 1px solid var(--rule); padding-bottom: 8px; flex-wrap: wrap;
5603
+ border-bottom: 1px solid var(--rule); padding-bottom: var(--space-2); flex-wrap: wrap;
5296
5604
  }
5297
5605
  .ds-247420 .ds-type-row-label { flex: 0 0 64px; font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
5298
5606
  .ds-247420 .ds-type-sample {
@@ -5300,7 +5608,7 @@
5300
5608
  font-size: var(--sample-size, var(--fs-body));
5301
5609
  }
5302
5610
  .ds-247420 .ds-prim-panel { padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px); display: flex; flex-direction: column; gap: 18px; }
5303
- .ds-247420 .ds-prim-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
5611
+ .ds-247420 .ds-prim-row { display: flex; gap: var(--space-2-5); flex-wrap: wrap; align-items: center; }
5304
5612
  .ds-247420 .ds-prim-label { flex: 0 0 64px; font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
5305
5613
 
5306
5614
  /* == appended: content-site == */
@@ -5356,7 +5664,7 @@
5356
5664
  matching the "color reserved for meaning, not decoration" pattern seen in
5357
5665
  docstudio's admin table. */
5358
5666
  .ds-247420 .ds-table-sort-btn {
5359
- display: inline-flex; align-items: center; gap: 4px;
5667
+ display: inline-flex; align-items: center; gap: var(--space-1);
5360
5668
  background: none; border: none; padding: 0; margin: 0;
5361
5669
  font: inherit; font-weight: inherit; color: inherit; cursor: pointer;
5362
5670
  }
@@ -5367,15 +5675,29 @@
5367
5675
 
5368
5676
  /* == appended: settings kit cleanup == */
5369
5677
  /* == appended: settings kit == */
5370
- .ds-247420 .ds-settings-main { padding: var(--space-2, 8px); }
5371
- .ds-247420 .ds-settings-body { padding: 14px 18px; }
5372
- .ds-247420 .ds-settings-body-stack { display: flex; flex-direction: column; gap: var(--space-2-5, 10px); }
5373
- .ds-247420 .ds-field-block { margin: var(--space-2-5, 10px) 0; }
5374
- .ds-247420 .ds-field-eyebrow {
5375
- font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.06em;
5376
- text-transform: uppercase; color: var(--panel-text-3);
5377
- }
5378
- .ds-247420 .ds-hint-sm { font-size: 12px; color: var(--panel-text-2); }
5678
+ /* .app-main already owns this region's padding; this only supplies the inset
5679
+ that keeps panel shadows off the scroll edge (see .ds-section-pad). */
5680
+ .ds-247420 .ds-settings-main { padding: calc(var(--space-1) * var(--density)); }
5681
+ /* .panel-body already pads the panel interior — this sat inside it and
5682
+ double-padded every field, on an off-scale 14/18 pair. The body is now a
5683
+ flow container that owns only the RHYTHM between fields, not a second inset. */
5684
+ .ds-247420 .ds-settings-body { padding: 0; }
5685
+ .ds-247420 .ds-settings-body-stack { display: flex; flex-direction: column; gap: calc(var(--space-2-5) * var(--density)); }
5686
+ /* Field rhythm: the label/control/hint cluster is tight internally, so fields
5687
+ need a clearly larger interval between them than within them, or the whole
5688
+ form reads as one undifferentiated column. Margin-collapse-free (flow root
5689
+ siblings) — first/last are zeroed so the panel body sets the outer edge. */
5690
+ .ds-247420 .ds-field-block { display: flex; flex-direction: column; gap: var(--space-1-75); margin: calc(var(--space-4) * var(--density)) 0 0; }
5691
+ .ds-247420 .ds-settings-body > .ds-field-block:first-child { margin-top: 0; }
5692
+ /* Field width is a hint about expected input length. A name or handle stretched
5693
+ across a 1000px desktop column tells the user to type a paragraph and leaves
5694
+ the eye no left-to-right anchor; capping the control (not the row) keeps the
5695
+ label/hint full-width for wrapping while the input reads as the right size.
5696
+ Textareas keep a wider cap since prose genuinely uses the room. */
5697
+ .ds-247420 .ds-field-block > .input { max-width: 44ch; width: 100%; }
5698
+ .ds-247420 .ds-field-block > textarea.input { max-width: 72ch; }
5699
+ /* .ds-field-eyebrow joins the kit small-label voice above with no overrides. */
5700
+ .ds-247420 .ds-hint-sm { font-size: var(--fs-xs); color: var(--panel-text-2); }
5379
5701
  .ds-247420 .ds-note-quiet { margin: 0; color: var(--panel-text-2); }
5380
5702
  .ds-247420 .ds-btn-row { display: flex; gap: var(--space-2, 8px); flex-wrap: wrap; }
5381
5703
  .ds-247420 .ds-btn-row-tight { gap: var(--space-1-75, 6px); }
@@ -5386,84 +5708,103 @@
5386
5708
  /* Raw --mascot text measures 3.11:1 on paper (fails 4.5:1); --mascot-deep is
5387
5709
  the text-safe tone, same accent/accent-ink split used everywhere else. */
5388
5710
  .ds-247420 .ds-btn-mascot { color: var(--mascot-deep); }
5711
+ /* Sticky commit bar. It floats OVER the form it commits, so it needs real
5712
+ elevation and a larger top margin than the form's own field rhythm —
5713
+ otherwise it reads as one more field rather than as the action for all of
5714
+ them. Spacing is density-scaled like the rest of the surface. */
5389
5715
  .ds-247420 .ds-savebar {
5390
- position: sticky; bottom: 8px; display: flex; align-items: center;
5391
- justify-content: flex-end; gap: 8px; flex-wrap: wrap; padding: 10px;
5392
- background: var(--panel-2); border-radius: var(--r-1); margin: 8px 0;
5716
+ position: sticky; bottom: var(--space-2); z-index: var(--z-sticky);
5717
+ display: flex; align-items: center;
5718
+ justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap;
5719
+ padding: calc(var(--space-2-75) * var(--density)) calc(var(--space-3) * var(--density));
5720
+ background: var(--panel-2); border-radius: var(--r-1);
5721
+ margin: calc(var(--space-5) * var(--density)) 0 var(--space-2);
5722
+ box-shadow: var(--shadow-2, var(--shadow-1));
5393
5723
  }
5394
5724
  .ds-247420 .ds-savebar-note { flex: 1 1 160px; min-width: 0; color: var(--panel-text-2); }
5395
- .ds-247420 .ds-settings-modal { min-width: min(320px, calc(100vw - 32px)); max-width: 480px; }
5396
- .ds-247420 .ds-modal-body-form { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
5397
- .ds-247420 .ds-modal-note { margin: 0 0 8px; color: var(--panel-text-2); font-size: 14px; }
5725
+ .ds-247420 .ds-settings-modal { min-width: min(320px, calc(100vw - var(--space-5))); max-width: 480px; }
5726
+ .ds-247420 .ds-modal-body-form { padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2-75); }
5727
+ .ds-247420 .ds-modal-note { margin: 0; color: var(--panel-text-2); font-size: var(--fs-xs); }
5398
5728
  .ds-247420 .ds-draft-preview {
5399
- background: var(--panel-1); padding: 12px; border-radius: var(--r-0);
5400
- font-size: 13px; color: var(--panel-text-2); max-height: 120px;
5729
+ background: var(--panel-1); padding: var(--space-2-75); border-radius: var(--r-0);
5730
+ font-size: var(--fs-micro); color: var(--panel-text-2); max-height: 120px;
5401
5731
  overflow-y: auto; font-family: var(--ff-mono); overflow-wrap: anywhere;
5402
5732
  }
5403
- .ds-247420 .ds-modal-actions { display: flex; gap: 8px; margin-top: 12px; justify-content: space-between; flex-wrap: wrap; }
5733
+ /* Destructive-choice actions get a clearly larger interval than the body's own
5734
+ gap — the decision must not read as the next line of the explanation. */
5735
+ .ds-247420 .ds-modal-actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); justify-content: space-between; flex-wrap: wrap; }
5404
5736
 
5405
5737
  /* == appended: signin kit cleanup == */
5406
5738
  /* -- signin kit (ui_kits/signin) -- */
5407
5739
  .ds-247420 .ds-auth-wrap { padding: var(--space-2, 8px); display: flex; flex-direction: column; align-items: center; }
5408
- .ds-247420 .ds-auth-col { width: 100%; max-width: 440px; display: flex; flex-direction: column; gap: 8px; margin: clamp(12px, 4vw, 24px) 0; min-width: 0; }
5409
- .ds-247420 .ds-auth-form { padding: clamp(12px, 3vw, 18px); display: flex; flex-direction: column; gap: 10px; }
5740
+ .ds-247420 .ds-auth-col { width: 100%; max-width: 440px; display: flex; flex-direction: column; gap: var(--space-2); margin: clamp(var(--space-2-75), 4vw, var(--space-4)) 0; min-width: 0; }
5741
+ /* 18px ceiling: no tier between --space-3 (16) and --space-3-5 (20). */
5742
+ .ds-247420 .ds-auth-form { padding: clamp(var(--space-2-75), 3vw, 18px); display: flex; flex-direction: column; gap: var(--space-2-5); }
5410
5743
  .ds-247420 .ds-auth-sent { align-items: center; text-align: center; }
5411
5744
  .ds-247420 .ds-auth-sent-glyph { font-size: 32px; color: var(--panel-accent); }
5412
5745
  .ds-247420 .ds-auth-sent-title { margin: 0; font-weight: 600; }
5413
5746
  .ds-247420 .ds-auth-sent-sub { margin: 0; color: var(--panel-text-2); overflow-wrap: anywhere; }
5414
- .ds-247420 .ds-auth-field { display: flex; flex-direction: column; gap: 4px; }
5415
- .ds-247420 .ds-auth-field-label { font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--panel-text-3); }
5416
- .ds-247420 .ds-auth-row-between { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
5417
- .ds-247420 .ds-auth-remember { display: flex; align-items: center; gap: 6px; cursor: pointer; }
5747
+ .ds-247420 .ds-auth-field { display: flex; flex-direction: column; gap: var(--space-1); }
5748
+ /* .ds-auth-field-label joins the kit small-label voice above, no overrides. */
5749
+ .ds-247420 .ds-auth-row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
5750
+ .ds-247420 .ds-auth-remember { display: flex; align-items: center; gap: var(--space-1-75); cursor: pointer; }
5418
5751
  .ds-247420 .ds-auth-remember-text { color: var(--panel-text-2); font-size: 13px; }
5419
5752
  .ds-247420 .ds-auth-forgot { font-size: 13px; }
5420
- .ds-247420 .ds-auth-error { padding: 8px 10px; background: var(--panel-1); border-radius: var(--r-0); color: var(--danger); font-size: 13px; overflow-wrap: anywhere; }
5421
- .ds-247420 .ds-auth-providers { display: flex; gap: 8px; flex-wrap: wrap; }
5422
- .ds-247420 .ds-auth-provider-btn { flex: 1 1 100px; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px; }
5753
+ .ds-247420 .ds-auth-error { padding: var(--space-2) var(--space-2-5); background: var(--panel-1); border-radius: var(--r-0); color: var(--danger); font-size: 13px; overflow-wrap: anywhere; }
5754
+ .ds-247420 .ds-auth-providers { display: flex; gap: var(--space-2); flex-wrap: wrap; }
5755
+ .ds-247420 .ds-auth-provider-btn { flex: 1 1 100px; min-width: 0; display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-2-5); }
5423
5756
  .ds-247420 .ds-auth-provider-btn--loading { opacity: 0.7; pointer-events: none; }
5424
5757
  .ds-247420 .ds-auth-provider-glyph { font-family: var(--ff-mono); color: var(--panel-text-3); display: inline-flex; }
5425
- .ds-247420 .ds-auth-modes { display: flex; justify-content: center; gap: 14px; margin-top: 8px; font-size: 13px; flex-wrap: wrap; }
5758
+ .ds-247420 .ds-auth-modes { display: flex; justify-content: center; gap: 14px; /* off-scale, matches the auth form inset */ margin-top: var(--space-2); font-size: 13px; flex-wrap: wrap; }
5426
5759
  .ds-247420 .ds-auth-mode-link { color: var(--panel-text-3); text-decoration: none; }
5427
5760
  .ds-247420 .ds-auth-mode-link--active { color: var(--panel-text); text-decoration: underline; }
5428
- .ds-247420 .ds-auth-fineprint { text-align: center; font-size: 12px; color: var(--panel-text-3); margin: 6px 0; }
5761
+ .ds-247420 .ds-auth-fineprint { text-align: center; font-size: 12px; color: var(--panel-text-3); margin: var(--space-1-75) 0; }
5429
5762
 
5430
5763
  /* == appended: gallery-misc kit cleanup == */
5431
5764
  /* --- shared helpers (converted from inline styles) --- */
5432
5765
  .ds-247420 .ds-m0 { margin: 0; }
5433
5766
  .ds-247420 .ds-text-2 { color: var(--panel-text-2); }
5434
5767
  .ds-247420 .ds-text-3 { color: var(--panel-text-3); }
5435
- .ds-247420 .ds-kit-head { display: flex; align-items: center; justify-content: space-between; gap: clamp(8px, 2vw, 16px); flex-wrap: wrap; }
5768
+ .ds-247420 .ds-kit-head { display: flex; align-items: center; justify-content: space-between; gap: clamp(var(--space-2), 2vw, var(--space-3)); flex-wrap: wrap; }
5436
5769
 
5437
5770
  /* --- gallery kit --- */
5438
5771
  .ds-247420 .ds-tile-cap { flex: 1; display: flex; align-items: center; justify-content: center; font-family: var(--ff-mono); white-space: pre-line; color: var(--panel-text-2); font-size: 18px; min-width: 0; text-align: center; }
5439
- .ds-247420 .ds-tile-meta { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-size: 12px; flex-wrap: wrap; min-width: 0; }
5772
+ .ds-247420 .ds-tile-meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-1-75); font-size: 12px; flex-wrap: wrap; min-width: 0; }
5440
5773
  .ds-247420 .ds-tile-glyph { font-family: var(--ff-mono); color: var(--panel-text-3); }
5441
5774
  .ds-247420 .ds-tile-label { color: var(--panel-text); overflow-wrap: anywhere; }
5442
5775
  .ds-247420 .ds-gal-swatch { height: 64px; border-radius: var(--r-0); background: var(--swatch, var(--panel-1)); }
5443
- .ds-247420 .ds-gal-swatch-meta { display: flex; justify-content: space-between; gap: 6px; flex-wrap: wrap; font-family: var(--ff-mono); font-size: 11px; min-width: 0; }
5776
+ .ds-247420 .ds-gal-swatch-meta { display: flex; justify-content: space-between; gap: var(--space-1-75); flex-wrap: wrap; font-family: var(--ff-mono); font-size: 11px; min-width: 0; }
5444
5777
  .ds-247420 .ds-gal-swatch-name { color: var(--panel-text); }
5445
5778
  .ds-247420 .ds-gal-swatch-hint { color: var(--panel-text-3); overflow-wrap: anywhere; }
5446
- .ds-247420 .ds-lightbox-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
5447
- .ds-247420 .ds-lightbox-tag { font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--panel-text-3); }
5779
+ .ds-247420 .ds-lightbox-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
5780
+ /* .ds-lightbox-tag joins the kit small-label voice above, no overrides. */
5448
5781
 
5449
5782
  /* --- error_404 kit --- */
5450
- .ds-247420 .ds-err-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-top: 6px; }
5451
- .ds-247420 .ds-err-chips { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; margin-top: 4px; }
5783
+ .ds-247420 .ds-err-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; justify-content: center; margin-top: var(--space-1-75); }
5784
+ .ds-247420 .ds-err-chips { display: flex; gap: var(--space-1-75); flex-wrap: wrap; justify-content: center; margin-top: var(--space-1); }
5452
5785
 
5453
5786
  /* == appended: terminal-capp kit cleanup == */
5454
5787
  /* --- terminal kit ------------------------------------------ */
5455
- .ds-247420 .ds-section-pad-sm { padding: 8px; }
5456
- .ds-247420 .ds-kit-head-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
5788
+ .ds-247420 .ds-section-pad-sm { padding: var(--space-2); }
5789
+ .ds-247420 .ds-kit-head-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
5457
5790
  .ds-247420 .ds-cli-cmt .cmd { color: var(--fg-3); }
5458
5791
  .ds-247420 .ds-cli-out .cmd { color: var(--fg-2); }
5459
5792
  .ds-247420 .ds-cli-ok .prompt, .ds-247420 .ds-cli-ok .cmd { color: var(--accent-ink); }
5460
5793
  .ds-247420 .ds-cli-warn .prompt, .ds-247420 .ds-cli-warn .cmd { color: var(--mascot-deep); }
5461
5794
  .ds-247420 .ds-cli-log .prompt { color: var(--fg-3); }
5462
5795
  .ds-247420 .ds-cli-log .cmd { color: var(--fg-2); font-family: var(--ff-mono); }
5463
- .ds-247420 .ds-term-body { padding: 14px 18px; display: flex; flex-direction: column; gap: 4px; background: var(--bg-2); border-radius: var(--r-1); }
5796
+ .ds-247420 .ds-term-body { padding: var(--space-2-75) var(--space-3-5); display: flex; flex-direction: column; gap: var(--space-1); background: var(--bg-2); border-radius: var(--r-1); }
5464
5797
  .ds-247420 .ds-term-body--tall { min-height: 280px; }
5465
- .ds-247420 .ds-term-input-row { margin-top: 6px; }
5466
- .ds-247420 .ds-term-input { flex: 1; min-width: 0; background: transparent; border: 0; outline: 0; font-family: var(--ff-mono); font-size: 13px; color: var(--fg); }
5798
+ .ds-247420 .ds-term-input-row { margin-top: var(--space-1-75); }
5799
+ .ds-247420 .ds-term-input { flex: 1; min-width: 0; background: transparent; border: 0; outline: 0; font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--fg); }
5800
+ /* The input itself is a prompt line, not a form control, so it is NOT floored
5801
+ to 44px (that would break the terminal's line rhythm). Instead the whole
5802
+ prompt ROW becomes the tap target, and the font goes to 16px so focusing it
5803
+ does not trigger iOS zoom — a sub-16px input is what causes that. */
5804
+ @media (pointer: coarse) {
5805
+ .ds-247420 .ds-term-input-row { min-height: 44px; align-items: center; }
5806
+ .ds-247420 .ds-term-input { font-size: max(16px, var(--fs-micro)); }
5807
+ }
5467
5808
  /* full-viewport render root (community-app) */
5468
5809
  .ds-247420 .ds-root-viewport { height: 100vh; height: 100dvh; }
5469
5810
 
@@ -5527,7 +5868,7 @@
5527
5868
  }
5528
5869
  .ds-247420 .ds-sheet-preview-table thead th {
5529
5870
  position: sticky; top: 0; background: var(--bg-2); color: var(--fg-3);
5530
- font-weight: 600; z-index: 1;
5871
+ font-weight: 600; z-index: var(--z-sticky);
5531
5872
  }
5532
5873
  .ds-247420 .ds-sheet-preview-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
5533
5874
  .ds-247420 .ds-sheet-preview-empty { padding: var(--space-3, 16px); color: var(--fg-3); }
@@ -5538,6 +5879,191 @@
5538
5879
  }
5539
5880
  .ds-247420 .ds-sheet-preview-error-action:hover { background: var(--bg-2); }
5540
5881
  .ds-247420 .ds-sheet-preview-error-action:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 2px; }
5882
+
5883
+ /* == appended: community kit message list == */
5884
+ /* ui_kits/community mounts CommunityShell (the .cm-* family) but renders its
5885
+ OWN message list in ds-* markup, and its index.html links app-shell.css
5886
+ WITHOUT community.css. So these live here, not in community.css: the .cm-*
5887
+ sheet never reaches this page, and .ds-community-* is ds-family markup by
5888
+ the lint-classes taxonomy anyway. Every rule below deliberately mirrors the
5889
+ .chat-msg / .chat-avatar / .chat-stack primitives in chat-polish.css so the
5890
+ community thread and the chat kit read as one message language. */
5891
+
5892
+ /* Page root — owns the full viewport column so CommunityShell's own 100dvh
5893
+ flex shell has a height to resolve against, with the topbar/status chrome
5894
+ stacked around it. */
5895
+ .ds-247420 .ds-community-page {
5896
+ display: flex;
5897
+ flex-direction: column;
5898
+ min-height: 100vh;
5899
+ min-height: 100dvh;
5900
+ min-width: 0;
5901
+ }
5902
+ /* Main column inside the shell — .cm-main's ds-family counterpart: header
5903
+ pinned, message list taking the remaining height and doing the scrolling. */
5904
+ .ds-247420 .ds-community-main {
5905
+ display: flex;
5906
+ flex-direction: column;
5907
+ flex: 1;
5908
+ min-width: 0;
5909
+ min-height: 0;
5910
+ }
5911
+
5912
+ /* Thread scroller. Same rhythm as .chat-thread (column + --space-3 gap +
5913
+ own overflow), so messages breathe on the same interval as the chat kit. */
5914
+ .ds-247420 .ds-community-messages {
5915
+ display: flex;
5916
+ flex-direction: column;
5917
+ gap: var(--space-3);
5918
+ flex: 1;
5919
+ min-height: 0;
5920
+ overflow-y: auto;
5921
+ padding: var(--space-3);
5922
+ scrollbar-width: thin;
5923
+ scrollbar-color: var(--bg-3) transparent;
5924
+ }
5925
+ .ds-247420 .ds-community-messages::-webkit-scrollbar { width: 8px; }
5926
+ .ds-247420 .ds-community-messages::-webkit-scrollbar-thumb { background: var(--bg-3); border-radius: var(--r-0); }
5927
+
5928
+ /* One message — avatar rail + body stack, matching .chat-msg's flex/gap and
5929
+ its quiet tonal hover (no border, per the zero-border aesthetic). */
5930
+ .ds-247420 .ds-community-msg {
5931
+ display: flex;
5932
+ align-items: flex-start;
5933
+ gap: var(--space-2-75);
5934
+ padding: var(--space-1-75) var(--space-2);
5935
+ margin: 0;
5936
+ border-radius: var(--r-1);
5937
+ min-width: 0;
5938
+ transition: background var(--dur-base) var(--ease);
5939
+ }
5940
+ .ds-247420 .ds-community-msg:hover { background: color-mix(in oklab, var(--fg) 4%, transparent); }
5941
+
5942
+ /* Identity disc. The inline `background:` from app.js supplies the per-author
5943
+ tone; this owns the SHAPE — a circle, which is the whole reason the avatar
5944
+ was rendering as a coloured bar with no rule. Footprint + type match
5945
+ .chat-avatar exactly. */
5946
+ .ds-247420 .ds-community-avatar {
5947
+ flex: 0 0 36px;
5948
+ width: 36px;
5949
+ height: 36px;
5950
+ border-radius: 50%;
5951
+ display: inline-flex;
5952
+ align-items: center;
5953
+ justify-content: center;
5954
+ overflow: hidden;
5955
+ color: var(--ink);
5956
+ font-family: var(--ff-mono);
5957
+ font-size: var(--fs-micro);
5958
+ font-weight: 600;
5959
+ line-height: 1;
5960
+ user-select: none;
5961
+ }
5962
+
5963
+ /* Body stack — name + time on one baseline, text beneath. .chat-stack's
5964
+ column/gap idiom, without the bubble max-width (this is a flat list row,
5965
+ not a two-sided bubble thread). */
5966
+ .ds-247420 .ds-community-msg-body {
5967
+ display: flex;
5968
+ flex-wrap: wrap;
5969
+ align-items: baseline;
5970
+ gap: var(--space-1) var(--space-2);
5971
+ flex: 1;
5972
+ min-width: 0;
5973
+ }
5974
+ /* Author. The inline `color:` from app.js carries the per-author tone; weight
5975
+ and size are what make it read as the row's title. */
5976
+ .ds-247420 .ds-community-msg-name {
5977
+ font-weight: 600;
5978
+ font-size: var(--fs-sm);
5979
+ line-height: 1.3;
5980
+ }
5981
+ /* Timestamp — the quiet mono meta voice used by .cm-user-tag / row .meta. */
5982
+ .ds-247420 .ds-community-msg-time {
5983
+ font-family: var(--ff-mono);
5984
+ font-size: var(--fs-micro);
5985
+ color: var(--fg-3);
5986
+ line-height: 1.3;
5987
+ }
5988
+ /* Message body claims the full second line of the wrapping body row. */
5989
+ .ds-247420 .ds-community-msg-text {
5990
+ flex: 1 0 100%;
5991
+ margin: 0;
5992
+ min-width: 0;
5993
+ color: var(--fg-2);
5994
+ font-size: var(--fs-sm);
5995
+ line-height: var(--lh-base);
5996
+ overflow-wrap: anywhere;
5997
+ }
5998
+
5999
+ @media (prefers-reduced-motion: reduce) {
6000
+ .ds-247420 .ds-community-msg { transition: none; }
6001
+ }
6002
+
6003
+ /* == appended: cross-kit note / swatch / chat-page / caret == */
6004
+
6005
+ /* "about this kit" explanatory block — 8 kits render a run of <p> lines here
6006
+ (often carrying inline Chip()/<code>) inside a .panel body. This is
6007
+ SECONDARY copy annotating the demo above it, so it takes the quiet voice:
6008
+ one step down from body, on the --fg-2 ramp, with a comfortable reading
6009
+ line-height. It owns only the RHYTHM between its lines; the panel body still
6010
+ owns the inset, so this must not re-pad. */
6011
+ .ds-247420 .ds-pattern-notes {
6012
+ display: flex;
6013
+ flex-direction: column;
6014
+ gap: var(--space-2);
6015
+ color: var(--fg-2);
6016
+ font-size: var(--fs-sm);
6017
+ line-height: var(--lh-base);
6018
+ max-width: var(--measure);
6019
+ min-width: 0;
6020
+ }
6021
+ .ds-247420 .ds-pattern-notes p { margin: 0; overflow-wrap: anywhere; }
6022
+ /* Inline literals inside a note read as quoted machinery, not as body copy —
6023
+ same tonal chip treatment .chat-bubble code uses. */
6024
+ .ds-247420 .ds-pattern-notes code {
6025
+ font-family: var(--ff-mono);
6026
+ font-size: 0.92em;
6027
+ background: color-mix(in oklab, var(--fg) 8%, transparent);
6028
+ padding: 0 var(--space-1);
6029
+ border-radius: var(--r-hair);
6030
+ }
6031
+ .ds-247420 .ds-pattern-notes strong { color: var(--fg); font-weight: 600; }
6032
+
6033
+ /* Swatch cell wrapper (system_primer pairs it with .ds-swatch-col, which owns
6034
+ the column/gap). This adds only what the wrapper itself needs: a minimum-zero
6035
+ track so long token names ellipsize inside the grid instead of widening it. */
6036
+ .ds-247420 .ds-swatch { min-width: 0; }
6037
+ .ds-247420 .ds-swatch .ds-swatch-name { overflow-wrap: anywhere; }
6038
+
6039
+ /* Chat kit page root — the thread must own the leftover column height rather
6040
+ than growing the page, so the composer stays on screen. Pairs with
6041
+ .ds-chat-layout (flex column, flex:1) which is already defined above. */
6042
+ .ds-247420 .chat-kit-page {
6043
+ display: flex;
6044
+ flex-direction: column;
6045
+ flex: 1;
6046
+ min-height: 0;
6047
+ min-width: 0;
6048
+ }
6049
+
6050
+ /* Terminal caret — a solid block that sits on the last demo line. Sized in ch
6051
+ so it tracks the mono column it follows. The blink is motion, so it is
6052
+ declared ONLY inside prefers-reduced-motion: no-preference (the same
6053
+ opt-in shape .cm-ch-spinner / .cm-vs-label::before use); with reduced
6054
+ motion the caret is a steady block, still marking the cursor position. */
6055
+ .ds-247420 .cursor-blink {
6056
+ display: inline-block;
6057
+ width: 1ch;
6058
+ height: 1em;
6059
+ margin-left: var(--space-1);
6060
+ background: var(--accent);
6061
+ vertical-align: text-bottom;
6062
+ }
6063
+ @media (prefers-reduced-motion: no-preference) {
6064
+ .ds-247420 .cursor-blink { animation: ds-cursor-blink 1s step-end infinite; }
6065
+ @keyframes ds-cursor-blink { 50% { opacity: 0; } }
6066
+ }
5541
6067
  /* ============================================================
5542
6068
  Git status panel + diff view — changed-file list, unified diff.
5543
6069
  ============================================================ */
@@ -5655,7 +6181,7 @@
5655
6181
  ============================================================ */
5656
6182
 
5657
6183
  .ds-247420 .ds-plugins-overlay {
5658
- position: fixed; inset: 0; z-index: var(--z-modal, 1000);
6184
+ position: fixed; inset: 0; z-index: var(--z-modal);
5659
6185
  background: color-mix(in oklab, var(--ink) 35%, transparent);
5660
6186
  display: flex; align-items: center; justify-content: center;
5661
6187
  padding: var(--space-3);
@@ -5917,6 +6443,25 @@
5917
6443
  All tokens sourced from colors_and_type.css.
5918
6444
  ============================================================ */
5919
6445
 
6446
+ /* ============================================================
6447
+ Small-label voice — the local composition of the house `.t-micro`
6448
+ recipe (src/css/app-shell/base.css). This sheet is a standalone
6449
+ published export consumed via its own <link>, so it cannot join the
6450
+ `.t-micro` selector list; it composes by referencing the identical
6451
+ token set instead. Every selector below that needs the label voice
6452
+ JOINS this rule and declares only what it deliberately differs on —
6453
+ never a second copy of these four declarations.
6454
+ ============================================================ */
6455
+ .ds-247420 .cm-vs-label,
6456
+ .ds-247420 .vx-section-label,
6457
+ .ds-247420 .vx-chip-tag {
6458
+ font-family: var(--ff-mono);
6459
+ font-size: var(--fs-micro);
6460
+ text-transform: uppercase;
6461
+ letter-spacing: var(--tr-label);
6462
+ color: var(--fg-3);
6463
+ }
6464
+
5920
6465
  /* ============================================================
5921
6466
  Shell — top-level flex container for the community layout
5922
6467
  ============================================================ */
@@ -5955,8 +6500,8 @@
5955
6500
  display: flex;
5956
6501
  flex-direction: column;
5957
6502
  align-items: center;
5958
- gap: 8px;
5959
- padding: 12px 0;
6503
+ gap: var(--space-2);
6504
+ padding: var(--space-2-75) 0;
5960
6505
  background: color-mix(in oklab, var(--bg) 70%, var(--ink));
5961
6506
  overflow-y: auto;
5962
6507
  overflow-x: hidden;
@@ -6025,7 +6570,7 @@
6025
6570
  right: -2px;
6026
6571
  min-width: 18px;
6027
6572
  height: 18px;
6028
- padding: 0 5px;
6573
+ padding: 0 var(--space-1-5);
6029
6574
  background: var(--warn);
6030
6575
  color: var(--paper);
6031
6576
  font-family: var(--ff-mono);
@@ -6070,7 +6615,7 @@
6070
6615
  height: 2px;
6071
6616
  background: color-mix(in oklab, var(--fg) 12%, transparent);
6072
6617
  border-radius: var(--r-hair);
6073
- margin: 4px 0;
6618
+ margin: var(--space-1) 0;
6074
6619
  flex-shrink: 0;
6075
6620
  }
6076
6621
 
@@ -6091,8 +6636,8 @@
6091
6636
  display: flex;
6092
6637
  align-items: center;
6093
6638
  justify-content: space-between;
6094
- gap: 8px;
6095
- padding: 14px 16px;
6639
+ gap: var(--space-2);
6640
+ padding: var(--space-2-75) var(--space-3);
6096
6641
  background: var(--bg-2);
6097
6642
  box-shadow: 0 1px 0 color-mix(in oklab, var(--fg) 8%, transparent);
6098
6643
  font-weight: 600;
@@ -6119,10 +6664,10 @@
6119
6664
  min-height: 0;
6120
6665
  overflow-y: auto;
6121
6666
  overflow-x: hidden;
6122
- padding: 8px 0 16px;
6667
+ padding: var(--space-2) 0 var(--space-3);
6123
6668
  display: flex;
6124
6669
  flex-direction: column;
6125
- gap: 2px;
6670
+ gap: var(--space-hair);
6126
6671
  scrollbar-width: thin;
6127
6672
  scrollbar-color: color-mix(in oklab, var(--fg) 18%, transparent) transparent;
6128
6673
  }
@@ -6139,15 +6684,15 @@
6139
6684
  .ds-247420 .cm-channel-category {
6140
6685
  display: flex;
6141
6686
  flex-direction: column;
6142
- margin-top: 12px;
6687
+ margin-top: var(--space-2-75);
6143
6688
  }
6144
- .ds-247420 .cm-channel-category:first-child { margin-top: 4px; }
6689
+ .ds-247420 .cm-channel-category:first-child { margin-top: var(--space-1); }
6145
6690
 
6146
6691
  .ds-247420 .cm-category-header {
6147
6692
  display: flex;
6148
6693
  align-items: center;
6149
- gap: 4px;
6150
- padding: 4px 8px 4px 8px;
6694
+ gap: var(--space-1);
6695
+ padding: var(--space-1) var(--space-2);
6151
6696
  font-family: var(--ff-body);
6152
6697
  font-size: var(--fs-micro);
6153
6698
  font-weight: 600;
@@ -6181,6 +6726,10 @@
6181
6726
  text-overflow: ellipsis;
6182
6727
  white-space: nowrap;
6183
6728
  }
6729
+ /* Deliberately NOT the small-label voice: this is the `+` affordance sitting
6730
+ inside .cm-category-header, which IS uppercase + tracked. The zeroed
6731
+ letter-spacing and text-transform are resets of that inherited voice, not a
6732
+ copy of it — a bare glyph must not be tracked apart or case-folded. */
6184
6733
  .ds-247420 .cm-cat-extra {
6185
6734
  font-family: var(--ff-mono);
6186
6735
  font-size: var(--fs-micro);
@@ -6195,7 +6744,7 @@
6195
6744
  justify-content: center;
6196
6745
  width: 28px;
6197
6746
  height: 28px;
6198
- padding: 4px;
6747
+ padding: var(--space-1);
6199
6748
  border: 0;
6200
6749
  background: transparent;
6201
6750
  color: var(--fg-3);
@@ -6217,8 +6766,11 @@
6217
6766
  .ds-247420 .cm-cat-channels {
6218
6767
  display: flex;
6219
6768
  flex-direction: column;
6769
+ /* gap:1px is OFF-SCALE ON PURPOSE — channel rows are meant to read as one
6770
+ near-continuous stack with only a hairline seam between them. --space-hair
6771
+ (2px) doubles the seam and breaks the rows into visibly separate pills. */
6220
6772
  gap: 1px;
6221
- padding: 2px 0;
6773
+ padding: var(--space-hair) 0;
6222
6774
  }
6223
6775
 
6224
6776
  /* ============================================================
@@ -6226,15 +6778,15 @@
6226
6778
  ============================================================ */
6227
6779
  .ds-247420 .cm-channel-item-wrap {
6228
6780
  position: relative;
6229
- padding: 0 8px;
6781
+ padding: 0 var(--space-2);
6230
6782
  }
6231
6783
 
6232
6784
  .ds-247420 .cm-channel-item {
6233
6785
  position: relative;
6234
6786
  display: flex;
6235
6787
  align-items: center;
6236
- gap: 8px;
6237
- padding: 6px 8px;
6788
+ gap: var(--space-2);
6789
+ padding: var(--space-1-75) var(--space-2);
6238
6790
  border-radius: var(--r-1);
6239
6791
  color: var(--fg-3);
6240
6792
  cursor: pointer;
@@ -6350,7 +6902,7 @@
6350
6902
  flex-shrink: 0;
6351
6903
  min-width: 16px;
6352
6904
  height: 16px;
6353
- padding: 0 5px;
6905
+ padding: 0 var(--space-1-5);
6354
6906
  background: var(--warn);
6355
6907
  color: var(--paper);
6356
6908
  font-family: var(--ff-mono);
@@ -6366,7 +6918,7 @@
6366
6918
  .ds-247420 .cm-ch-actions {
6367
6919
  display: inline-flex;
6368
6920
  align-items: center;
6369
- gap: 2px;
6921
+ gap: var(--space-hair);
6370
6922
  opacity: 0;
6371
6923
  transition: opacity var(--dur-snap) var(--ease);
6372
6924
  flex-shrink: 0;
@@ -6376,7 +6928,7 @@
6376
6928
  .ds-247420 .cm-ch-action-btn {
6377
6929
  width: 28px;
6378
6930
  height: 28px;
6379
- padding: 4px;
6931
+ padding: var(--space-1);
6380
6932
  display: inline-flex;
6381
6933
  align-items: center;
6382
6934
  justify-content: center;
@@ -6401,15 +6953,16 @@
6401
6953
  .ds-247420 .cm-ch-voice-users {
6402
6954
  display: flex;
6403
6955
  flex-direction: column;
6956
+ /* gap:1px — same hairline-seam rationale as .cm-cat-channels above. */
6404
6957
  gap: 1px;
6405
- padding: 2px 8px 4px 32px;
6958
+ padding: var(--space-hair) var(--space-2) var(--space-1) var(--space-5);
6406
6959
  }
6407
6960
 
6408
6961
  .ds-247420 .cm-ch-voice-user {
6409
6962
  display: flex;
6410
6963
  align-items: center;
6411
- gap: 8px;
6412
- padding: 3px 6px;
6964
+ gap: var(--space-2);
6965
+ padding: var(--space-half) var(--space-1-75);
6413
6966
  border-radius: var(--r-1);
6414
6967
  color: var(--fg-2);
6415
6968
  font-size: var(--fs-xs);
@@ -6463,8 +7016,8 @@
6463
7016
  .ds-247420 .cm-voice-strip {
6464
7017
  display: none;
6465
7018
  flex-direction: column;
6466
- gap: 8px;
6467
- padding: 10px 12px;
7019
+ gap: var(--space-2);
7020
+ padding: var(--space-2-5) var(--space-2-75);
6468
7021
  background: color-mix(in oklab, var(--green) 18%, var(--bg-2));
6469
7022
  color: var(--fg);
6470
7023
  box-shadow: 0 -1px 0 color-mix(in oklab, var(--fg) 10%, transparent);
@@ -6472,16 +7025,15 @@
6472
7025
  }
6473
7026
  .ds-247420 .cm-voice-strip.open { display: flex; }
6474
7027
 
7028
+ /* Joins the small-label voice above. Deliberate overrides: --green (this is a
7029
+ live-recording indicator, not neutral chrome) and weight 700 (it sits next to
7030
+ a pulsing dot and must read as the loudest thing in the strip). */
6475
7031
  .ds-247420 .cm-vs-label {
6476
- font-family: var(--ff-mono);
6477
- font-size: var(--fs-micro);
6478
- text-transform: uppercase;
6479
- letter-spacing: var(--tr-caps);
6480
7032
  color: var(--green);
6481
7033
  font-weight: 700;
6482
7034
  display: inline-flex;
6483
7035
  align-items: center;
6484
- gap: 6px;
7036
+ gap: var(--space-1-75);
6485
7037
  }
6486
7038
  .ds-247420 .cm-vs-label::before {
6487
7039
  content: '';
@@ -6515,7 +7067,7 @@
6515
7067
  color: var(--fg-2);
6516
7068
  display: flex;
6517
7069
  align-items: center;
6518
- gap: 6px;
7070
+ gap: var(--space-1-75);
6519
7071
  flex-wrap: wrap;
6520
7072
  }
6521
7073
 
@@ -6523,9 +7075,9 @@
6523
7075
  display: inline-flex;
6524
7076
  align-items: center;
6525
7077
  justify-content: center;
6526
- gap: 6px;
7078
+ gap: var(--space-1-75);
6527
7079
  height: 28px;
6528
- padding: 0 10px;
7080
+ padding: 0 var(--space-2-5);
6529
7081
  background: color-mix(in oklab, var(--fg) 10%, transparent);
6530
7082
  color: var(--fg);
6531
7083
  border: 0;
@@ -6553,8 +7105,8 @@
6553
7105
  .ds-247420 .cm-user-panel {
6554
7106
  display: flex;
6555
7107
  align-items: center;
6556
- gap: 8px;
6557
- padding: 8px 8px;
7108
+ gap: var(--space-2);
7109
+ padding: var(--space-2);
6558
7110
  background: color-mix(in oklab, var(--fg) 5%, var(--bg-2));
6559
7111
  flex-shrink: 0;
6560
7112
  }
@@ -6607,6 +7159,8 @@
6607
7159
  text-overflow: ellipsis;
6608
7160
  white-space: nowrap;
6609
7161
  }
7162
+ /* Deliberately NOT the small-label voice: a user's handle/tag is content, not
7163
+ chrome, so it stays sentence-case and untracked. Mono + micro + --fg-3 only. */
6610
7164
  .ds-247420 .cm-user-tag {
6611
7165
  font-family: var(--ff-mono);
6612
7166
  font-size: var(--fs-micro);
@@ -6619,7 +7173,7 @@
6619
7173
  .ds-247420 .cm-user-controls {
6620
7174
  display: inline-flex;
6621
7175
  align-items: center;
6622
- gap: 2px;
7176
+ gap: var(--space-hair);
6623
7177
  }
6624
7178
 
6625
7179
  .ds-247420 .cm-user-btn {
@@ -6654,8 +7208,8 @@
6654
7208
  .ds-247420 .cm-chat-header {
6655
7209
  display: flex;
6656
7210
  align-items: center;
6657
- gap: 10px;
6658
- padding: 12px 16px;
7211
+ gap: var(--space-2-5);
7212
+ padding: var(--space-2-75) var(--space-3);
6659
7213
  background: var(--bg);
6660
7214
  box-shadow: 0 1px 0 color-mix(in oklab, var(--fg) 8%, transparent);
6661
7215
  flex-shrink: 0;
@@ -6685,8 +7239,8 @@
6685
7239
  .ds-247420 .cm-chat-header-topic {
6686
7240
  flex: 1;
6687
7241
  min-width: 0;
6688
- padding-left: 12px;
6689
- margin-left: 4px;
7242
+ padding-left: var(--space-2-75);
7243
+ margin-left: var(--space-1);
6690
7244
  border-left: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
6691
7245
  color: var(--fg-3);
6692
7246
  font-size: var(--fs-xs);
@@ -6698,7 +7252,7 @@
6698
7252
  .ds-247420 .cm-chat-header-toolbar {
6699
7253
  display: inline-flex;
6700
7254
  align-items: center;
6701
- gap: 4px;
7255
+ gap: var(--space-1);
6702
7256
  flex-shrink: 0;
6703
7257
  }
6704
7258
 
@@ -6714,7 +7268,7 @@
6714
7268
  overflow-y: auto;
6715
7269
  overflow-x: hidden;
6716
7270
  background: var(--bg-2);
6717
- padding: 16px 0;
7271
+ padding: var(--space-3) 0;
6718
7272
  scrollbar-width: thin;
6719
7273
  scrollbar-color: color-mix(in oklab, var(--fg) 18%, transparent) transparent;
6720
7274
  transition: width var(--dur-base) var(--ease), flex-basis var(--dur-base) var(--ease);
@@ -6736,7 +7290,7 @@
6736
7290
  }
6737
7291
 
6738
7292
  .ds-247420 .cm-member-category {
6739
- padding: 12px 16px 6px;
7293
+ padding: var(--space-2-75) var(--space-3) var(--space-1-75);
6740
7294
  font-family: var(--ff-body);
6741
7295
  font-size: var(--fs-micro);
6742
7296
  font-weight: 600;
@@ -6748,9 +7302,9 @@
6748
7302
  .ds-247420 .cm-member-item {
6749
7303
  display: flex;
6750
7304
  align-items: center;
6751
- gap: 10px;
6752
- padding: 6px 12px;
6753
- margin: 0 8px;
7305
+ gap: var(--space-2-5);
7306
+ padding: var(--space-1-75) var(--space-2-75);
7307
+ margin: 0 var(--space-2);
6754
7308
  border-radius: var(--r-1);
6755
7309
  color: var(--fg-2);
6756
7310
  cursor: pointer;
@@ -6815,8 +7369,8 @@
6815
7369
  display: inline-flex;
6816
7370
  flex-direction: column;
6817
7371
  align-items: center;
6818
- gap: 6px;
6819
- padding: 10px;
7372
+ gap: var(--space-1-75);
7373
+ padding: var(--space-2-5);
6820
7374
  border-radius: var(--r-2);
6821
7375
  background: var(--bg-2);
6822
7376
  transition: box-shadow var(--dur-snap) var(--ease), background var(--dur-snap) var(--ease);
@@ -6866,7 +7420,7 @@
6866
7420
  @media (max-width: 900px) {
6867
7421
  .ds-247420 .cm-channel-sidebar {
6868
7422
  position: absolute;
6869
- z-index: 20;
7423
+ z-index: calc(var(--z-drawer) + 1);
6870
7424
  top: 0;
6871
7425
  left: 72px;
6872
7426
  bottom: 0;
@@ -6879,7 +7433,7 @@
6879
7433
  .ds-247420 .cm-member-list.open {
6880
7434
  display: flex;
6881
7435
  position: absolute;
6882
- z-index: 20;
7436
+ z-index: calc(var(--z-drawer) + 1);
6883
7437
  top: 0;
6884
7438
  right: 0;
6885
7439
  bottom: 0;
@@ -6899,7 +7453,7 @@
6899
7453
  content: '';
6900
7454
  position: absolute;
6901
7455
  inset: 0;
6902
- z-index: 15;
7456
+ z-index: var(--z-drawer);
6903
7457
  background: color-mix(in oklab, var(--ink) 40%, transparent);
6904
7458
  pointer-events: none;
6905
7459
  }
@@ -6915,7 +7469,7 @@
6915
7469
  .ds-247420 .cm-server-back {
6916
7470
  width: 44px;
6917
7471
  height: 44px;
6918
- padding: 4px;
7472
+ padding: var(--space-1);
6919
7473
  }
6920
7474
  .ds-247420 .cm-channel-sidebar,
6921
7475
  .ds-247420 .cm-channel-sidebar.open {
@@ -7061,7 +7615,12 @@
7061
7615
  gap: var(--space-2);
7062
7616
  padding: var(--space-1) var(--space-2);
7063
7617
  background: var(--bg-2);
7064
- border-left: 3px solid var(--accent);
7618
+ /* Hairline, not a 3px accent bar. This is a transient status strip pinned
7619
+ above the composer (role=status, "Replying to <author>"), not a card or a
7620
+ callout — the tinted fill already carries the attachment. A chunky left
7621
+ bar here was the generic accent-stripe tell; the real accent still lands
7622
+ on .cm-rb-author. */
7623
+ border-left: var(--bw-hair) solid var(--rule-strong);
7065
7624
  font-size: 0.85rem;
7066
7625
  }
7067
7626
  .ds-247420 .cm-rb-label { flex: none; color: var(--fg-2); }
@@ -7109,7 +7668,7 @@
7109
7668
  color: inherit;
7110
7669
  font: inherit;
7111
7670
  font-weight: 600;
7112
- padding: 2px var(--space-2);
7671
+ padding: var(--space-hair) var(--space-2);
7113
7672
  border-radius: var(--r-1);
7114
7673
  cursor: pointer;
7115
7674
  }
@@ -7339,13 +7898,7 @@
7339
7898
  border-top: var(--bw-hair) solid var(--rule);
7340
7899
  }
7341
7900
  .ds-247420 .vx-section { display: flex; flex-direction: column; gap: var(--space-2); }
7342
- .ds-247420 .vx-section-label {
7343
- font-family: var(--ff-mono);
7344
- font-size: var(--fs-micro);
7345
- letter-spacing: var(--tr-label);
7346
- text-transform: uppercase;
7347
- color: var(--fg-3);
7348
- }
7901
+ /* Joins the small-label voice above with no overrides — it IS the plain voice. */
7349
7902
  .ds-247420 .vx-segmented { display: flex; gap: var(--space-1); }
7350
7903
  .ds-247420 .vx-seg {
7351
7904
  flex: 1;
@@ -7394,7 +7947,7 @@
7394
7947
  display: flex; gap: var(--space-2);
7395
7948
  overflow-x: auto;
7396
7949
  flex: 1;
7397
- padding-bottom: 2px;
7950
+ padding-bottom: var(--space-hair);
7398
7951
  }
7399
7952
  .ds-247420 .vx-chip {
7400
7953
  display: inline-flex; align-items: center; gap: var(--space-1);
@@ -7413,9 +7966,11 @@
7413
7966
  .ds-247420 .vx-chip-dot { width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--fg-3); flex-shrink: 0; }
7414
7967
  .ds-247420 .vx-chip-name { font-weight: 600; }
7415
7968
  .ds-247420 .vx-chip-dur { font-family: var(--ff-mono); color: var(--fg-3); }
7969
+ /* Joins the small-label voice above. Deliberate overrides: --green + weight 700
7970
+ because this is the "LIVE" badge on a session chip, same signal role as
7971
+ .cm-vs-label. */
7416
7972
  .ds-247420 .vx-chip-tag {
7417
- font-family: var(--ff-mono); font-size: var(--fs-micro);
7418
- color: var(--green); font-weight: 700; letter-spacing: var(--tr-caps);
7973
+ color: var(--green); font-weight: 700;
7419
7974
  }
7420
7975
 
7421
7976
  /* VoiceControls — vx-vc-* */
@@ -7450,7 +8005,7 @@
7450
8005
  @media (max-width: 900px) {
7451
8006
  .ds-247420 .cm-thread-panel {
7452
8007
  position: absolute;
7453
- z-index: 20;
8008
+ z-index: calc(var(--z-drawer) + 1);
7454
8009
  top: 0; right: 0; bottom: 0;
7455
8010
  height: auto;
7456
8011
  width: min(320px, 90vw);
@@ -7471,7 +8026,7 @@
7471
8026
  .ds-247420 .cm-tp-list { flex: 1; min-height: 0; overflow-y: auto; }
7472
8027
  .ds-247420 .cm-tp-item {
7473
8028
  position: relative; /* anchors .cm-tp-dot to the row, not the panel */
7474
- display: flex; flex-direction: column; gap: 2px;
8029
+ display: flex; flex-direction: column; gap: var(--space-hair);
7475
8030
  width: 100%; text-align: left; cursor: pointer;
7476
8031
  padding: var(--space-2); border: none; background: transparent;
7477
8032
  border-bottom: var(--bw-hair) solid var(--rule);
@@ -7496,7 +8051,7 @@
7496
8051
  list surface in the kit uses one shimmer language, never a bare spinner. */
7497
8052
  .ds-247420 .cm-channel-item-skeleton, .ds-247420 .cm-member-item-skeleton {
7498
8053
  display: flex; align-items: center; gap: var(--space-2);
7499
- padding: var(--space-2); margin: 2px var(--space-1);
8054
+ padding: var(--space-2); margin: var(--space-hair) var(--space-1);
7500
8055
  }
7501
8056
  .ds-247420 .cm-channel-item-skeleton .ds-skel-icon, .ds-247420 .cm-member-item-skeleton .ds-skel-icon {
7502
8057
  width: 20px; height: 20px; border-radius: var(--r-round, 50%); flex: none; background: var(--bg-3);
@@ -7505,7 +8060,7 @@
7505
8060
  height: 12px; width: 60%; border-radius: var(--r-1); background: var(--bg-3);
7506
8061
  }
7507
8062
  .ds-247420 .cm-list-item-skeleton {
7508
- display: flex; flex-direction: column; gap: 6px;
8063
+ display: flex; flex-direction: column; gap: var(--space-1-75);
7509
8064
  padding: var(--space-2) var(--space-3); border-bottom: var(--bw-hair) solid var(--rule);
7510
8065
  }
7511
8066
  .ds-247420 .cm-list-item-skeleton .ds-skel-title { height: 12px; width: 55%; border-radius: var(--r-1); background: var(--bg-3); }
@@ -7537,8 +8092,10 @@
7537
8092
  .ds-247420 .cm-forum-item-replies { font-size: var(--fs-0, 12px); color: var(--fg-2, var(--fg)); opacity: .8; white-space: nowrap; }
7538
8093
  .ds-247420 .cm-forum-item-snippet { font-size: var(--fs-0, 12px); color: var(--fg-2, var(--fg)); opacity: .85; }
7539
8094
  .ds-247420 .cm-forum-item-meta { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; font-size: var(--fs-micro, 11px); color: var(--fg-2, var(--fg)); opacity: .7; }
7540
- .ds-247420 .cm-forum-item-tags { display: inline-flex; gap: 4px; }
7541
- .ds-247420 .cm-forum-tag { padding: 1px 6px; border-radius: var(--r-1); background: var(--bg-3); border: var(--bw-hair) solid var(--rule); }
8095
+ .ds-247420 .cm-forum-item-tags { display: inline-flex; gap: var(--space-1); }
8096
+ /* 1px vertical is OFF-SCALE ON PURPOSE the tag is an inline chip inside the
8097
+ forum meta row; --space-hair (2px) tips it past the row height. */
8098
+ .ds-247420 .cm-forum-tag { padding: 1px var(--space-1-75); border-radius: var(--r-1); background: var(--bg-3); border: var(--bw-hair) solid var(--rule); }
7542
8099
 
7543
8100
  /* PageView — cm-page / cm-page-* */
7544
8101
  .ds-247420 .cm-page { display: flex; flex-direction: column; height: 100%; min-height: 0; overflow-y: auto; background: var(--bg-1, var(--bg-2)); color: var(--fg); }
@@ -7565,6 +8122,9 @@
7565
8122
  .ds-247420 .fd-chat-thread { flex: 1 1 auto; min-height: 240px; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-2, 10px); padding: var(--space-2, 10px); }
7566
8123
  .ds-247420 .fd-page-error { white-space: pre-wrap; overflow-wrap: anywhere; }
7567
8124
  /* Visually-hidden polite live region — announces async busy/done to SR users. */
8125
+ /* margin:-1px is OFF-SCALE ON PURPOSE — the canonical visually-hidden idiom;
8126
+ the negative margin cancels the 1px box so the live region contributes zero
8127
+ layout. A --space-* rung would reintroduce a measurable gap. */
7568
8128
  .ds-247420 .fd-sr-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
7569
8129
  /* page-level responsive: tighten padding on narrow viewports */
7570
8130
  @media (max-width: 640px) {
@@ -7604,8 +8164,12 @@
7604
8164
  .ds-247420 .agentchat-controls .ds-select { min-width: 130px; max-width: 240px; }
7605
8165
  /* One shared control metric for the most-seen chrome row (mirrors the
7606
8166
  .ds-dash-toolbar precedent): selects, buttons, export acts all 32px / r-1. */
7607
- .ds-247420 .agentchat-controls .ds-select { min-height: 32px; padding: 4px 28px 4px 10px; font-size: var(--fs-sm); border-radius: var(--r-1); }
7608
- .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; }
8167
+ /* The 28px right pad is OFF-SCALE ON PURPOSE: it is not rhythm but clearance
8168
+ for the native select's dropdown arrow, which the UA draws at a fixed inset.
8169
+ Snapping to --space-5 (32px) or --space-4 (24px) either wastes a column of
8170
+ text width or lets long option labels run under the arrow. */
8171
+ .ds-247420 .agentchat-controls .ds-select { min-height: 32px; padding: var(--space-1) 28px var(--space-1) var(--space-2-5); font-size: var(--fs-sm); border-radius: var(--r-1); }
8172
+ .ds-247420 .agentchat-controls .btn, .ds-247420 .agentchat-controls .btn-primary { padding: var(--space-1-5) var(--space-2-75); min-height: 32px; border-radius: var(--r-1); font-weight: 500; }
7609
8173
  @media (pointer: coarse) {
7610
8174
  .ds-247420 .agentchat-controls .ds-select, .ds-247420 .agentchat-controls .btn, .ds-247420 .agentchat-controls .btn-primary { min-height: 44px; }
7611
8175
  }
@@ -7625,6 +8189,12 @@
7625
8189
  .ds-247420 .agentchat-controls [role="combobox"] { flex-basis: 100%; }
7626
8190
  }
7627
8191
 
8192
+ /* The .4em/.5em gaps on this status line, .agentchat-head below, and the
8193
+ narrow-viewport .agentchat-controls override are em-based ON PURPOSE, not
8194
+ un-migrated literals: each is the gap between a label and its own inline
8195
+ text/disc, so it must track that element's font-size (these rows are scaled
8196
+ by font-size alone at narrow widths). A --space-* px rung would hold the gap
8197
+ fixed while the type around it shrank. */
7628
8198
  .ds-247420 .agentchat-status {
7629
8199
  display: inline-flex;
7630
8200
  align-items: center;
@@ -7675,7 +8245,7 @@
7675
8245
  border: 1px solid var(--rule);
7676
8246
  color: inherit;
7677
8247
  border-radius: var(--r-1);
7678
- padding: 2px 8px;
8248
+ padding: var(--space-hair) var(--space-2);
7679
8249
  cursor: pointer;
7680
8250
  font: inherit;
7681
8251
  }
@@ -7688,7 +8258,7 @@
7688
8258
  border: var(--bw-hair) solid var(--rule);
7689
8259
  color: var(--fg);
7690
8260
  border-radius: var(--r-1);
7691
- padding: 4px 8px;
8261
+ padding: var(--space-1) var(--space-2);
7692
8262
  font: inherit;
7693
8263
  }
7694
8264
  .ds-247420 .agentchat-cwd-input:focus-visible { outline: none; box-shadow: var(--focus-ring-inset); }
@@ -7701,12 +8271,12 @@
7701
8271
  .ds-247420 .agentchat-cwd-editing { flex-direction: column; align-items: stretch; }
7702
8272
  .ds-247420 .agentchat-cwd-row { display: flex; align-items: center; gap: var(--space-2, 8px); flex-wrap: wrap; }
7703
8273
  .ds-247420 .agentchat-cwd-roots, .ds-247420 .agentchat-cwd-recent {
7704
- display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
8274
+ display: flex; align-items: center; gap: var(--space-1-75); flex-wrap: wrap;
7705
8275
  }
7706
8276
  .ds-247420 .agentchat-cwd-recent-label { font-size: var(--fs-tiny); color: var(--fg-3); }
7707
8277
  .ds-247420 .agentchat-cwd-chip {
7708
8278
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule); color: var(--fg-2);
7709
- border-radius: var(--r-pill); padding: 3px 10px; font: inherit; font-size: var(--fs-tiny);
8279
+ border-radius: var(--r-pill); padding: var(--space-half) var(--space-2-5); font: inherit; font-size: var(--fs-tiny);
7710
8280
  cursor: pointer;
7711
8281
  }
7712
8282
  .ds-247420 .agentchat-cwd-chip:hover { border-color: var(--accent); color: var(--fg); }
@@ -7714,17 +8284,17 @@
7714
8284
  .ds-247420 .agentchat-cwd-browse {
7715
8285
  border: var(--bw-hair) solid var(--rule); border-radius: var(--r-1);
7716
8286
  padding: var(--space-2, 8px); background: var(--bg-2);
7717
- display: flex; flex-direction: column; gap: 6px;
8287
+ display: flex; flex-direction: column; gap: var(--space-1-75);
7718
8288
  max-height: 220px;
7719
8289
  }
7720
8290
  .ds-247420 .agentchat-cwd-browse-list { overflow-y: auto; display: flex; flex-direction: column; max-height: 160px; }
7721
8291
  .ds-247420 .agentchat-cwd-browse-item {
7722
8292
  background: none; border: none; color: var(--fg-2); text-align: left;
7723
- padding: 6px 8px; border-radius: var(--r-1); font: inherit; font-size: var(--fs-tiny);
8293
+ padding: var(--space-1-75) var(--space-2); border-radius: var(--r-1); font: inherit; font-size: var(--fs-tiny);
7724
8294
  cursor: pointer;
7725
8295
  }
7726
8296
  .ds-247420 .agentchat-cwd-browse-item:hover, .ds-247420 .agentchat-cwd-browse-item:focus-visible { background: var(--bg-3, var(--bg)); color: var(--fg); }
7727
- .ds-247420 .agentchat-cwd-browse-loading, .ds-247420 .agentchat-cwd-browse-empty { padding: 6px 8px; font-size: var(--fs-tiny); color: var(--fg-3); }
8297
+ .ds-247420 .agentchat-cwd-browse-loading, .ds-247420 .agentchat-cwd-browse-empty { padding: var(--space-1-75) var(--space-2); font-size: var(--fs-tiny); color: var(--fg-3); }
7728
8298
 
7729
8299
  /* head + thread */
7730
8300
  .ds-247420 .agentchat-head {
@@ -7745,14 +8315,14 @@
7745
8315
  .ds-247420 .agentchat-side-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; border-left: var(--bw-hair) solid var(--bg-3); }
7746
8316
  .ds-247420 .agentchat-side-panel-head {
7747
8317
  display: flex; align-items: center; justify-content: space-between;
7748
- padding: var(--space-2, 8px) var(--space-3, 12px); border-bottom: var(--bw-hair) solid var(--bg-3);
8318
+ padding: var(--space-2, 8px) var(--space-3, 16px); border-bottom: var(--bw-hair) solid var(--bg-3);
7749
8319
  flex: 0 0 auto;
7750
8320
  }
7751
8321
  .ds-247420 .agentchat-side-panel-title { font-size: var(--fs-tiny); font-weight: 600; color: var(--fg-2); text-transform: uppercase; letter-spacing: var(--tr-label); }
7752
8322
  .ds-247420 .agentchat-side-panel-close {
7753
8323
  display: inline-flex; align-items: center; justify-content: center;
7754
8324
  background: none; border: none; color: var(--fg-3); cursor: pointer;
7755
- padding: 4px; border-radius: var(--r-1);
8325
+ padding: var(--space-1); border-radius: var(--r-1);
7756
8326
  }
7757
8327
  .ds-247420 .agentchat-side-panel-close:hover { background: var(--bg-2); color: var(--fg); }
7758
8328
  .ds-247420 .agentchat-side-panel-close:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
@@ -7776,8 +8346,11 @@
7776
8346
 
7777
8347
  /* Jump-to-latest: hidden until the thread scroll listener adds .show. */
7778
8348
  .ds-247420 .agentchat-jump {
7779
- position: absolute; right: 16px; bottom: 12px; z-index: 3;
8349
+ position: absolute; right: 16px; bottom: 12px; z-index: var(--z-raised);
7780
8350
  display: none; align-items: center; gap: .35em;
8351
+ /* em, not --space-*: this pill must scale with its own --fs-tiny text so the
8352
+ capsule stays proportional when a host overrides the chat font size. A px
8353
+ rung would fix the padding while the label grew/shrank inside it. */
7781
8354
  padding: .4em .8em; font: inherit; font-size: var(--fs-tiny); cursor: pointer;
7782
8355
  border-radius: var(--r-pill); border: var(--bw-hair) solid var(--rule);
7783
8356
  background: var(--bg-2); color: var(--fg-2, var(--fg));
@@ -7789,6 +8362,9 @@
7789
8362
 
7790
8363
  /* Streaming caret: a thin blinking bar at the live edge of an assistant turn. */
7791
8364
  .ds-247420 .chat-stream-caret {
8365
+ /* margin-left:1px is OFF-SCALE ON PURPOSE — a hairline optical nudge that
8366
+ separates the caret bar from the last glyph without reading as a space
8367
+ character. --space-hair (2px) is already wide enough to look like one. */
7792
8368
  display: inline-block; width: 2px; height: 1.05em; margin-left: 1px;
7793
8369
  vertical-align: text-bottom; background: var(--accent, var(--fg));
7794
8370
  animation: chat-caret-blink 1s step-end infinite;
@@ -7797,11 +8373,11 @@
7797
8373
  @media (prefers-reduced-motion: reduce) { .ds-247420 .chat-stream-caret { animation: none; opacity: .8; } }
7798
8374
 
7799
8375
  /* Per-message hover-revealed action row (copy / retry / edit). */
7800
- .ds-247420 .chat-msg-actions { display: flex; gap: 2px; margin-top: 3px; opacity: 0; transition: opacity var(--dur-snap, .12s) var(--ease, ease); }
8376
+ .ds-247420 .chat-msg-actions { display: flex; gap: var(--space-hair); margin-top: var(--space-half); opacity: 0; transition: opacity var(--dur-snap, .12s) var(--ease, ease); }
7801
8377
  .ds-247420 .chat-msg:hover .chat-msg-actions, .ds-247420 .chat-msg:focus-within .chat-msg-actions { opacity: 1; }
7802
8378
  .ds-247420 .chat-msg-action {
7803
- display: inline-flex; align-items: center; justify-content: center; gap: 4px;
7804
- min-width: 26px; height: 26px; padding: 0 6px; cursor: pointer;
8379
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
8380
+ min-width: 26px; height: 26px; padding: 0 var(--space-1-75); cursor: pointer;
7805
8381
  border: none; border-radius: var(--r-1, 4px); background: none; color: var(--fg-3);
7806
8382
  font-family: var(--ff-body); font-size: var(--fs-tiny);
7807
8383
  }
@@ -7810,7 +8386,12 @@
7810
8386
  .ds-247420 .chat-msg-action:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 1px; opacity: 1; }
7811
8387
  .ds-247420 .chat-msg-action.is-copied { color: var(--accent-ink); opacity: 1; }
7812
8388
 
7813
- /* Empty state: a fresh thread is an invitation, not a void. */
8389
+ /* Empty state: a fresh thread is an invitation, not a void.
8390
+ The em-based gap/padding through this block and the suggestion chips below
8391
+ are OFF the --space-* px scale ON PURPOSE: the empty state is typeset copy
8392
+ whose rhythm must track its own font-size (hosts scale this panel down on
8393
+ narrow viewports via font-size alone). Fixed px rungs here would decouple
8394
+ the chip padding from the label and break the capsule proportions. */
7814
8395
  .ds-247420 .agentchat-empty {
7815
8396
  margin: auto;
7816
8397
  display: flex;
@@ -7874,7 +8455,7 @@
7874
8455
  font-family: var(--ff-mono); font-size: var(--fs-sm); color: var(--fg-2, var(--fg));
7875
8456
  }
7876
8457
  .ds-247420 .agentchat-install-copy {
7877
- flex: 0 0 auto; cursor: pointer; padding: 2px 8px; min-height: 24px;
8458
+ flex: 0 0 auto; cursor: pointer; padding: var(--space-hair) var(--space-2); min-height: 24px;
7878
8459
  border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-1, 4px);
7879
8460
  background: none; color: var(--fg-3);
7880
8461
  font-family: var(--ff-body); font-size: var(--fs-tiny);
@@ -7885,7 +8466,7 @@
7885
8466
 
7886
8467
  /* Host-supplied transcript export actions riding the controls row. */
7887
8468
  .ds-247420 .agentchat-export-act {
7888
- cursor: pointer; padding: 4px 10px; min-height: 32px;
8469
+ cursor: pointer; padding: var(--space-1) var(--space-2-5); min-height: 32px;
7889
8470
  border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-1, 4px);
7890
8471
  background: none; color: var(--fg-3);
7891
8472
  font-family: var(--ff-body); font-size: var(--fs-tiny);
@@ -7893,7 +8474,10 @@
7893
8474
  .ds-247420 .agentchat-export-act:hover { background: var(--bg-2); color: var(--fg); }
7894
8475
  .ds-247420 .agentchat-export-act:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 1px; }
7895
8476
 
7896
- /* "working" tail: a long silent tool call shouldn't read as frozen. */
8477
+ /* "working" tail: a long silent tool call shouldn't read as frozen.
8478
+ em gap/padding here and on .chat-thinking below is deliberate — both tails
8479
+ are inline status text sized off --fs-tiny, and their inset must shrink with
8480
+ the type, not sit on a fixed px rung. */
7897
8481
  .ds-247420 .agentchat-working {
7898
8482
  display: flex;
7899
8483
  align-items: center;
@@ -7905,7 +8489,7 @@
7905
8489
  .ds-247420 .agentchat-working-text { color: var(--fg-3); }
7906
8490
  /* Self-contained dots (chat-thinking-dots lives in a kit sheet not bundled
7907
8491
  into this DS distribution, so the agentchat tail draws its own). */
7908
- .ds-247420 .agentchat-working .chat-thinking-dots { display: inline-flex; gap: 3px; }
8492
+ .ds-247420 .agentchat-working .chat-thinking-dots { display: inline-flex; gap: var(--space-half); }
7909
8493
  .ds-247420 .agentchat-working .chat-thinking-dots span {
7910
8494
  width: 5px; height: 5px; border-radius: 50%;
7911
8495
  background: var(--fg); opacity: .4;
@@ -7926,7 +8510,7 @@
7926
8510
  no muted tone. Reuse the agentchat-dot-bounce keyframe. */
7927
8511
  .ds-247420 .chat-thinking { display: flex; align-items: center; gap: .5em; color: var(--fg-3); font-size: var(--fs-tiny); background: none; padding: .3em .2em; }
7928
8512
  .ds-247420 .chat-thinking-text { color: var(--fg-3); }
7929
- .ds-247420 .chat-thinking-dots { display: inline-flex; gap: 3px; }
8513
+ .ds-247420 .chat-thinking-dots { display: inline-flex; gap: var(--space-half); }
7930
8514
  .ds-247420 .chat-thinking-dots span {
7931
8515
  width: 5px; height: 5px; border-radius: 50%;
7932
8516
  background: var(--fg); opacity: .4;
@@ -8026,7 +8610,7 @@
8026
8610
  .ds-247420 .ds-session-new:hover { background: var(--bg-2); color: var(--fg); }
8027
8611
  /* Rail filter uses the shared .ds-search-input primitive (provides bg/border/
8028
8612
  radius/focus-ring); only the rail layout + touch floor live here. */
8029
- .ds-247420 .ds-session-head .ds-search-input { order: 1; flex: 1 1 auto; min-width: 0; min-height: 36px; padding: 0 10px; }
8613
+ .ds-247420 .ds-session-head .ds-search-input { order: 1; flex: 1 1 auto; min-width: 0; min-height: 36px; padding: 0 var(--space-2-5); }
8030
8614
  .ds-247420 .ds-session-new:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
8031
8615
  /* Touch floor (must FOLLOW the base rules - same specificity, order decides). */
8032
8616
  @media (pointer: coarse) {
@@ -8035,7 +8619,7 @@
8035
8619
  }
8036
8620
  .ds-247420 .ds-session-list, .ds-247420 .ds-session-groups { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-2); }
8037
8621
  .ds-247420 .ds-session-loadmore {
8038
- width: 100%; margin-top: var(--space-1); padding: 8px 12px;
8622
+ width: 100%; margin-top: var(--space-1); padding: var(--space-2) var(--space-2-75);
8039
8623
  font-size: var(--fs-sm); font-family: inherit; color: var(--fg-3);
8040
8624
  background: none; border: var(--bw-hair) dashed var(--rule); border-radius: var(--r-1);
8041
8625
  cursor: pointer; text-align: center;
@@ -8046,11 +8630,11 @@
8046
8630
  /* Grouped rows (Today/Yesterday/...) lay out like the flat list; the section
8047
8631
  label sticks to the top of the scroll area for Claude-Desktop-style headers. */
8048
8632
  .ds-247420 .ds-session-group { display: flex; flex-direction: column; }
8049
- .ds-247420 .ds-session-group-rows { display: flex; flex-direction: column; gap: 2px; }
8050
- .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-label); padding: var(--space-2) var(--space-2) var(--space-1); }
8633
+ .ds-247420 .ds-session-group-rows { display: flex; flex-direction: column; gap: var(--space-hair); }
8634
+ .ds-247420 .ds-session-group-label { position: sticky; top: 0; z-index: var(--z-sticky); 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-label); padding: var(--space-2) var(--space-2) var(--space-1); }
8051
8635
  .ds-247420 .ds-session-row {
8052
8636
  position: relative; display: flex; align-items: center; gap: var(--space-2);
8053
- width: 100%; padding: var(--space-2); min-height: 52px; margin-bottom: 2px;
8637
+ width: 100%; padding: var(--space-2); min-height: 52px; margin-bottom: var(--space-hair);
8054
8638
  background: transparent; border: none; border-radius: var(--r-1);
8055
8639
  cursor: pointer; text-align: left; color: var(--fg);
8056
8640
  }
@@ -8065,7 +8649,7 @@
8065
8649
  .ds-247420 .ds-session-row.rail-green::before { background: var(--accent-ink); }
8066
8650
  .ds-247420 .ds-session-row.rail-purple::before { background: var(--purple-2); }
8067
8651
  .ds-247420 .ds-session-row.rail-flame::before { background: var(--flame); }
8068
- .ds-247420 .ds-session-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
8652
+ .ds-247420 .ds-session-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-hair); }
8069
8653
  .ds-247420 .ds-session-title { font-size: var(--fs-sm); color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
8070
8654
  .ds-247420 .ds-session-sub { font-size: var(--fs-tiny); color: var(--fg-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
8071
8655
  .ds-247420 .ds-session-meta { display: flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; }
@@ -8135,7 +8719,7 @@
8135
8719
  it only goes loud while ARMED (the one-shot press-again confirm). */
8136
8720
  .ds-247420 .ds-dash-header .btn, .ds-247420 .ds-dash-header .btn-primary {
8137
8721
  margin-left: 0;
8138
- padding: 5px 12px; min-height: 32px; border-radius: var(--r-1); font-weight: 500;
8722
+ padding: var(--space-1-5) var(--space-2-75); min-height: 32px; border-radius: var(--r-1); font-weight: 500;
8139
8723
  }
8140
8724
  .ds-247420 .ds-dash-header .btn-primary.danger {
8141
8725
  background: transparent; color: var(--warn);
@@ -8156,7 +8740,7 @@
8156
8740
  .ds-247420 .ds-dash-status.is-error { color: var(--flame); }
8157
8741
  .ds-247420 .ds-dash-agent { font-size: var(--fs-body); font-weight: 600; color: var(--fg); }
8158
8742
  .ds-247420 .ds-dash-model { font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3); margin-left: auto; }
8159
- .ds-247420 .ds-dash-meta { display: flex; flex-direction: column; gap: 2px; }
8743
+ .ds-247420 .ds-dash-meta { display: flex; flex-direction: column; gap: var(--space-hair); }
8160
8744
  .ds-247420 .ds-dash-cwd { font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
8161
8745
  .ds-247420 .ds-dash-stat { font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-2); }
8162
8746
  .ds-247420 .ds-dash-stat-cost { color: var(--fg); font-weight: 600; }
@@ -8187,7 +8771,7 @@
8187
8771
  letter-spacing: var(--tr-caps); text-transform: uppercase;
8188
8772
  padding: 0 0 var(--space-2);
8189
8773
  }
8190
- .ds-247420 .ds-context-group .row + .row { margin-top: 2px; }
8774
+ .ds-247420 .ds-context-group .row + .row { margin-top: var(--space-hair); }
8191
8775
 
8192
8776
  /* ============================================================================
8193
8777
  Cohesion sweep (gui-cohesion.js): one-product polish across surfaces.
@@ -8201,7 +8785,7 @@
8201
8785
  .ds-247420 .chat-code-copy {
8202
8786
  position: absolute; top: 6px; right: 6px;
8203
8787
  display: inline-flex; align-items: center; justify-content: center;
8204
- min-width: 48px; min-height: 24px; padding: 2px 8px;
8788
+ min-width: 48px; min-height: 24px; padding: var(--space-hair) var(--space-2);
8205
8789
  border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-1, 4px);
8206
8790
  background: var(--bg-2); color: var(--fg-2); cursor: pointer;
8207
8791
  font-family: var(--ff-body); font-size: var(--fs-tiny);
@@ -8244,7 +8828,7 @@
8244
8828
 
8245
8829
  /* --- A5: composer context line (agent / model / cwd at point of typing). --- */
8246
8830
  .ds-247420 .chat-composer-context {
8247
- display: block; width: 100%; text-align: left; padding: 4px var(--space-3) 0;
8831
+ display: block; width: 100%; text-align: left; padding: var(--space-1) var(--space-3) 0;
8248
8832
  background: none; border: none; cursor: default; color: var(--fg-3);
8249
8833
  font-family: var(--ff-mono); font-size: var(--fs-tiny);
8250
8834
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
@@ -8286,11 +8870,11 @@
8286
8870
  height, never a stacked full-width form column. */
8287
8871
  .ds-247420 .ds-dash-toolbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
8288
8872
  .ds-247420 .ds-dash-toolbar .ds-search-input {
8289
- width: 200px; min-height: 32px; padding: 5px 10px;
8873
+ width: 200px; min-height: 32px; padding: var(--space-1-5) var(--space-2-5);
8290
8874
  font-size: var(--fs-sm); border-radius: var(--r-1);
8291
8875
  }
8292
8876
  .ds-247420 .ds-dash-toolbar .ds-select, .ds-247420 .ds-dash-toolbar select {
8293
- min-height: 32px; padding: 4px 10px; font-size: var(--fs-sm);
8877
+ min-height: 32px; padding: var(--space-1) var(--space-2-5); font-size: var(--fs-sm);
8294
8878
  width: auto; border-radius: var(--r-1);
8295
8879
  }
8296
8880
  .ds-247420 .ds-dash-stream { font-size: var(--fs-tiny); color: var(--fg-3); }
@@ -8299,7 +8883,7 @@
8299
8883
  .ds-247420 .ds-dash-stream.is-connecting { color: var(--amber); }
8300
8884
  .ds-247420 .ds-dash-header .spread { flex: 1; }
8301
8885
  .ds-247420 .ds-dash-errors-toggle {
8302
- padding: 4px 10px; min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
8886
+ padding: var(--space-1) var(--space-2-5); min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
8303
8887
  border-radius: var(--r-1); background: var(--bg-2); color: var(--fg-2);
8304
8888
  cursor: pointer; font-family: var(--ff-body); font-size: var(--fs-tiny);
8305
8889
  }
@@ -8342,14 +8926,14 @@
8342
8926
  .ds-247420 .ds-preview-code-wrap { display: flex; flex-direction: column; min-height: 0; }
8343
8927
  .ds-247420 .ds-preview-code-head { flex: 0 0 auto; }
8344
8928
  /* --- E2: prev/next stepper in preview head. --- */
8345
- .ds-247420 .ds-preview-step { display: inline-flex; gap: 2px; }
8346
- .ds-247420 .ds-preview-step .ds-file-act { min-width: 40px; padding: 0 6px; font-family: var(--ff-body); font-size: var(--fs-tiny); }
8929
+ .ds-247420 .ds-preview-step { display: inline-flex; gap: var(--space-hair); }
8930
+ .ds-247420 .ds-preview-step .ds-file-act { min-width: 40px; padding: 0 var(--space-1-75); font-family: var(--ff-body); font-size: var(--fs-tiny); }
8347
8931
 
8348
8932
  /* --- D1: file grid "show more" row. --- */
8349
8933
  .ds-247420 .ds-file-more { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); justify-content: center; }
8350
8934
  .ds-247420 .ds-file-more-count { font-size: var(--fs-tiny); color: var(--fg-3); }
8351
8935
  .ds-247420 .ds-file-more-btn {
8352
- padding: 4px 12px; min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
8936
+ padding: var(--space-1) var(--space-2-75); min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
8353
8937
  border-radius: var(--r-1); background: var(--bg-2); color: var(--fg-2); cursor: pointer;
8354
8938
  font-family: var(--ff-body); font-size: var(--fs-tiny);
8355
8939
  }
@@ -8358,9 +8942,9 @@
8358
8942
  .ds-247420 .ds-file-row.is-locked { opacity: .6; }
8359
8943
 
8360
8944
  /* --- D4: roots picker segmented control. --- */
8361
- .ds-247420 .ds-roots-picker { display: inline-flex; gap: 2px; padding: 2px; background: var(--bg-2); border-radius: var(--r-1); }
8945
+ .ds-247420 .ds-roots-picker { display: inline-flex; gap: var(--space-hair); padding: var(--space-hair); background: var(--bg-2); border-radius: var(--r-1); }
8362
8946
  .ds-247420 .ds-roots-tab {
8363
- padding: 4px 10px; min-height: 32px; border: none; border-radius: var(--r-1);
8947
+ padding: var(--space-1) var(--space-2-5); min-height: 32px; border: none; border-radius: var(--r-1);
8364
8948
  background: none; color: var(--fg-3); cursor: pointer;
8365
8949
  font-family: var(--ff-body); font-size: var(--fs-tiny);
8366
8950
  }
@@ -8394,7 +8978,7 @@
8394
8978
  .ds-247420 .ds-session-meta-label { color: var(--fg-3); }
8395
8979
  .ds-247420 .ds-session-meta-value { font-family: var(--ff-mono); color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
8396
8980
  .ds-247420 .ds-session-meta-copy, .ds-247420 .ds-session-meta-action {
8397
- padding: 2px 8px; min-height: 24px; cursor: pointer;
8981
+ padding: var(--space-hair) var(--space-2); min-height: 24px; cursor: pointer;
8398
8982
  background: var(--bg-2); border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-1);
8399
8983
  color: var(--fg-3); font-family: var(--ff-body); font-size: var(--fs-micro);
8400
8984
  }
@@ -8413,7 +8997,7 @@
8413
8997
  can discover Enter-vs-Shift+Enter without having to focus it first;
8414
8998
  hidden under 420px to save rows. */
8415
8999
  .ds-247420 .chat-composer-hint {
8416
- display: block; width: 100%; order: 5; padding: 2px var(--space-1) 0;
9000
+ display: block; width: 100%; order: 5; padding: var(--space-hair) var(--space-1) 0;
8417
9001
  font-size: var(--fs-micro); color: var(--fg-3);
8418
9002
  }
8419
9003
  @media (max-width: 420px) {
@@ -8422,13 +9006,13 @@
8422
9006
 
8423
9007
  /* Transient composer note (paste/drop not supported), aria-live polite. */
8424
9008
  .ds-247420 .chat-composer-note {
8425
- padding: 4px var(--space-3); font-size: var(--fs-tiny); color: var(--fg-2);
9009
+ padding: var(--space-1) var(--space-3); font-size: var(--fs-tiny); color: var(--fg-2);
8426
9010
  }
8427
9011
 
8428
9012
  /* Streaming elapsed-time counter: ticks m:ss while a turn is in flight.
8429
9013
  Tabular-nums so the digits don't jitter the layout every second. */
8430
9014
  .ds-247420 .chat-composer-elapsed {
8431
- order: 5; padding: 2px var(--space-1) 0;
9015
+ order: 5; padding: var(--space-hair) var(--space-1) 0;
8432
9016
  font-size: var(--fs-micro); color: var(--fg-3);
8433
9017
  font-variant-numeric: tabular-nums; font-feature-settings: 'tnum';
8434
9018
  }
@@ -8438,7 +9022,7 @@
8438
9022
  new chrome. */
8439
9023
  .ds-247420 .chat-composer-detected-badge {
8440
9024
  display: flex; align-items: center; gap: var(--space-2, 8px);
8441
- padding: 4px var(--space-3); font-size: var(--fs-tiny); color: var(--fg-2);
9025
+ padding: var(--space-1) var(--space-3); font-size: var(--fs-tiny); color: var(--fg-2);
8442
9026
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule);
8443
9027
  border-radius: var(--r-1); width: 100%; order: -1;
8444
9028
  }
@@ -8446,7 +9030,7 @@
8446
9030
  .ds-247420 .chat-composer-detected-dismiss {
8447
9031
  flex: 0 0 auto; background: none; border: none; cursor: pointer;
8448
9032
  color: var(--fg-3); font: inherit; font-size: var(--fs-tiny);
8449
- padding: 2px 6px; border-radius: var(--r-1);
9033
+ padding: var(--space-hair) var(--space-1-75); border-radius: var(--r-1);
8450
9034
  }
8451
9035
  .ds-247420 .chat-composer-detected-dismiss:hover { color: var(--fg); }
8452
9036
  .ds-247420 .chat-composer-detected-dismiss:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
@@ -8499,7 +9083,7 @@
8499
9083
  /* Out-of-band turn notices: neutral tone (NOT error red) — a stopped or
8500
9084
  incomplete turn must not read as a finished answer. */
8501
9085
  .ds-247420 .chat-msg-notice {
8502
- margin-top: var(--space-1); padding: 6px 10px;
9086
+ margin-top: var(--space-1); padding: var(--space-1-75) var(--space-2-5);
8503
9087
  border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
8504
9088
  background: var(--bg-2); color: var(--fg-2); font-size: var(--fs-tiny);
8505
9089
  }
@@ -8514,14 +9098,14 @@
8514
9098
  .ds-247420 .chat-msg-retry-btn {
8515
9099
  border: var(--bw-hair) solid var(--danger); border-radius: var(--r-1);
8516
9100
  background: transparent; color: var(--danger-ink, var(--danger));
8517
- font: inherit; font-size: var(--fs-tiny); padding: 2px 10px; cursor: pointer;
9101
+ font: inherit; font-size: var(--fs-tiny); padding: var(--space-hair) var(--space-2-5); cursor: pointer;
8518
9102
  }
8519
9103
  .ds-247420 .chat-msg-retry-btn:hover { background: var(--danger); color: var(--bg); }
8520
9104
  .ds-247420 .chat-msg-retry-btn:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
8521
9105
 
8522
9106
  /* Tail-window streaming head ('streaming · N KB so far'). */
8523
9107
  .ds-247420 .chat-stream-head {
8524
- padding: 2px 0 6px; font-family: var(--ff-mono);
9108
+ padding: var(--space-hair) 0 var(--space-1-75); font-family: var(--ff-mono);
8525
9109
  font-size: var(--fs-micro); color: var(--fg-3);
8526
9110
  }
8527
9111
 
@@ -8532,7 +9116,7 @@
8532
9116
  }
8533
9117
  .ds-247420 .agentchat-earlier-count { font-size: var(--fs-tiny); color: var(--fg-3); }
8534
9118
  .ds-247420 .agentchat-earlier-btn {
8535
- padding: 4px 12px; min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
9119
+ padding: var(--space-1) var(--space-2-75); min-height: 32px; border: var(--bw-hair) solid var(--bg-3);
8536
9120
  border-radius: var(--r-1); background: var(--bg-2); color: var(--fg-2); cursor: pointer;
8537
9121
  font-family: var(--ff-body); font-size: var(--fs-tiny);
8538
9122
  }
@@ -8558,7 +9142,10 @@
8558
9142
 
8559
9143
  /* External (observed, not owned) session card: no stop control exists. */
8560
9144
  .ds-247420 .ds-dash-external {
8561
- padding: 1px 6px; border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-pill);
9145
+ /* 1px vertical is OFF-SCALE ON PURPOSE — a --fs-micro uppercase pill whose
9146
+ height must stay inside the card's meta row. --space-hair (2px) tips it
9147
+ past the row and pushes the card taller. Horizontal snaps normally. */
9148
+ padding: 1px var(--space-1-75); border: var(--bw-hair) solid var(--bg-3); border-radius: var(--r-pill);
8562
9149
  font-size: var(--fs-micro); color: var(--fg-3); text-transform: uppercase; letter-spacing: var(--tr-caps);
8563
9150
  }
8564
9151
  .ds-247420 .ds-dash-card.is-external { border-style: dashed; }
@@ -8597,11 +9184,18 @@
8597
9184
  .ds-247420 .chat-msg-flat .chat-role { margin-bottom: var(--space-2); }
8598
9185
  .ds-247420 .chat-msg-flat .chat-md { line-height: var(--lh-long); }
8599
9186
  .ds-247420 .chat-msg-flat .chat-md p { margin: var(--space-2) 0; }
9187
+ /* The `+ 2px` is an OFF-SCALE optical correction, not a rhythm step: the tinted
9188
+ assistant row needs marginally more inset than the untinted .you row so the
9189
+ fill does not appear to crowd the text. Expressing it as a --space-* rung
9190
+ would make it a visible step rather than the sub-perceptual nudge intended. */
8600
9191
  .ds-247420 .chat-msg-flat.them { padding-block: calc(var(--space-3) * var(--density, 1) + 2px); }
8601
9192
  /* Inline backtick code (renderInline tags <code class=chat-tick>) - was a dead
8602
9193
  class relying on the generic .chat-bubble code rule, so notices / non-bubble
8603
9194
  surfaces got unstyled monospace. Self-style it regardless of container. */
8604
- .ds-247420 .chat-tick { font-family: var(--ff-mono); font-size: .92em; background: color-mix(in oklab, var(--fg) 10%, transparent); padding: 1px 6px; border-radius: var(--r-1); }
9195
+ /* 1px vertical is OFF-SCALE ON PURPOSE inline code sits INSIDE a line of running
9196
+ prose; any larger vertical pad makes the tinted box overlap the lines above and
9197
+ below. Horizontal is on the scale. */
9198
+ .ds-247420 .chat-tick { font-family: var(--ff-mono); font-size: .92em; background: color-mix(in oklab, var(--fg) 10%, transparent); padding: 1px var(--space-1-75); border-radius: var(--r-1); }
8605
9199
  /* Structured tool/code output earns more width than running prose (claude.ai/code
8606
9200
  lets diffs/tables break out wider than the reading measure). A flat turn that
8607
9201
  contains a tool card or code block widens itself AND its stack past --measure;
@@ -8653,7 +9247,7 @@
8653
9247
  margin-left: auto; flex: 0 0 auto;
8654
9248
  font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: var(--tr-caps);
8655
9249
  color: var(--fg-3);
8656
- padding: 2px var(--space-2); border-radius: var(--r-pill);
9250
+ padding: var(--space-hair) var(--space-2); border-radius: var(--r-pill);
8657
9251
  background: color-mix(in oklab, var(--fg) 6%, transparent);
8658
9252
  }
8659
9253
  .ds-247420 .chat-msg .chat-tool.tool-running .chat-tool-status { color: var(--accent-ink); background: color-mix(in oklab, var(--accent) 12%, transparent); }
@@ -8681,8 +9275,8 @@
8681
9275
  structured CodeNode). injectCodeCopy reads the language- class. */
8682
9276
  .ds-247420 .chat-code-block { position: relative; }
8683
9277
  .ds-247420 .chat-code-lang {
8684
- position: absolute; top: 0; left: 0; z-index: 2;
8685
- padding: 2px var(--space-2); border-bottom-right-radius: var(--r-1);
9278
+ position: absolute; top: 0; left: 0; z-index: var(--z-raised);
9279
+ padding: var(--space-hair) var(--space-2); border-bottom-right-radius: var(--r-1);
8686
9280
  font-family: var(--ff-mono); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--tr-caps);
8687
9281
  color: var(--fg-3); background: color-mix(in oklab, var(--fg) 6%, transparent);
8688
9282
  pointer-events: none;
@@ -8742,7 +9336,7 @@
8742
9336
  .ds-247420 .ds-dash-clear:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 1px; border-radius: var(--r-1); }
8743
9337
 
8744
9338
  /* Conversation-rail loading skeleton (cold ccsniff walk). */
8745
- .ds-247420 .ds-session-row-skeleton { display: flex; flex-direction: column; gap: 6px; padding: var(--space-2) var(--space-3); }
9339
+ .ds-247420 .ds-session-row-skeleton { display: flex; flex-direction: column; gap: var(--space-1-75); padding: var(--space-2) var(--space-3); }
8746
9340
  .ds-247420 .ds-session-row-skeleton .ds-skel { background: var(--bg-3); border-radius: var(--r-1); }
8747
9341
  .ds-247420 .ds-session-row-skeleton .ds-skel-title { height: 12px; width: 70%; }
8748
9342
  .ds-247420 .ds-session-row-skeleton .ds-skel-meta { height: 9px; width: 45%; }
@@ -8793,7 +9387,7 @@
8793
9387
  Hover/focus/active-state rules on the originals still apply.
8794
9388
  ---------------------------------------------------------------------------- */
8795
9389
  .ds-247420 .row-act, .ds-247420 .ds-dash-errors-toggle, .ds-247420 .agentchat-export-act, .ds-247420 .ds-file-more-btn {
8796
- min-height: 32px; padding: 5px 12px; border-radius: var(--r-1);
9390
+ min-height: 32px; padding: var(--space-1-5) var(--space-2-75); border-radius: var(--r-1);
8797
9391
  font-family: var(--ff-body); font-size: var(--fs-tiny); font-weight: 500;
8798
9392
  background: transparent; border: var(--bw-hair) solid var(--rule); color: var(--fg-2);
8799
9393
  cursor: pointer;
@@ -8802,7 +9396,7 @@
8802
9396
  background: var(--bg-2); color: var(--fg);
8803
9397
  }
8804
9398
  .ds-247420 .agentchat-install-copy, .ds-247420 .ds-upload-act, .ds-247420 .ds-session-meta-copy {
8805
- min-height: 24px; padding: 2px 8px; border-radius: var(--r-1);
9399
+ min-height: 24px; padding: var(--space-hair) var(--space-2); border-radius: var(--r-1);
8806
9400
  font-family: var(--ff-body); font-size: var(--fs-tiny);
8807
9401
  background: transparent; border: var(--bw-hair) solid var(--rule); color: var(--fg-3);
8808
9402
  cursor: pointer;
@@ -8856,7 +9450,10 @@
8856
9450
  border-top: var(--bw-hair) solid var(--rule);
8857
9451
  border-bottom: var(--bw-hair) solid var(--rule);
8858
9452
  pointer-events: none;
8859
- z-index: 1;
9453
+ /* Minimap internal order: centerline < viewport < dot < tooltip. All four
9454
+ live inside the one raised widget, so they share its rung and differ
9455
+ only by a local offset. */
9456
+ z-index: calc(var(--z-raised) + 1);
8860
9457
  }
8861
9458
  .ds-247420 .chat-minimap-centerline {
8862
9459
  position: absolute;
@@ -8866,7 +9463,7 @@
8866
9463
  width: 1px;
8867
9464
  background: var(--rule);
8868
9465
  transform: translateX(-50%);
8869
- z-index: 0;
9466
+ z-index: var(--z-raised);
8870
9467
  }
8871
9468
  .ds-247420 .chat-minimap-dot {
8872
9469
  position: absolute;
@@ -8876,7 +9473,7 @@
8876
9473
  border-radius: var(--r-pill, 999px);
8877
9474
  transform: translate(-50%, -50%) scale(1);
8878
9475
  transition: transform 0.1s;
8879
- z-index: 2;
9476
+ z-index: calc(var(--z-raised) + 2);
8880
9477
  }
8881
9478
  .ds-247420 .chat-minimap-dot.is-user {
8882
9479
  background: color-mix(in oklab, var(--accent) 18%, transparent);
@@ -8898,7 +9495,10 @@
8898
9495
  border-left: 2px solid var(--fg-3);
8899
9496
  border-radius: var(--r-1);
8900
9497
  padding: calc(var(--space-1) / 2) var(--space-2);
8901
- z-index: 100;
9498
+ /* Top of the minimap's internal order. Deliberately NOT --z-tooltip: it is
9499
+ clipped to the minimap rail rather than floating over the app, so it must
9500
+ not outrank real overlays that may cover the rail. */
9501
+ z-index: calc(var(--z-raised) + 3);
8902
9502
  pointer-events: none;
8903
9503
  opacity: 0.45;
8904
9504
  font-size: var(--fs-tiny);
@@ -8936,8 +9536,8 @@
8936
9536
  }
8937
9537
  .ds-247420 .ds-ep-panel-head {
8938
9538
  flex-shrink: 0;
8939
- display: flex; align-items: center; justify-content: space-between; gap: 8px;
8940
- padding: 6px 10px;
9539
+ display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
9540
+ padding: var(--space-1-75) var(--space-2-5);
8941
9541
  border-bottom: 1px solid var(--rule);
8942
9542
  font-size: var(--fs-micro, 11px); font-weight: 600;
8943
9543
  text-transform: uppercase; letter-spacing: 0.1em;
@@ -8951,7 +9551,7 @@
8951
9551
  }
8952
9552
  .ds-247420 .ds-ep-panel-body {
8953
9553
  flex: 1; min-height: 0; overflow: auto;
8954
- padding: 6px 8px;
9554
+ padding: var(--space-1-75) var(--space-2);
8955
9555
  }
8956
9556
  .ds-247420 .ds-ep-panel-body.flush { padding: 0; }
8957
9557
  /* A sub-section divider inside a docked panel (e.g. app-prop mount). Only
@@ -8967,36 +9567,36 @@
8967
9567
  /* Dense status strip for editor chrome — thin, flush, bordered top. */
8968
9568
  .ds-247420 .ds-ep-statusbar {
8969
9569
  flex-shrink: 0;
8970
- display: flex; align-items: center; justify-content: space-between; gap: 8px;
9570
+ display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
8971
9571
  min-height: 0; height: 26px;
8972
- padding: 0 10px;
9572
+ padding: 0 var(--space-2-5);
8973
9573
  border-top: 1px solid var(--rule);
8974
9574
  background: var(--panel-1);
8975
9575
  color: var(--panel-text-2);
8976
9576
  font: var(--fs-micro, 11px)/1 var(--ff-mono, monospace);
8977
9577
  }
8978
- .ds-247420 .ds-ep-statusbar-left, .ds-247420 .ds-ep-statusbar-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
9578
+ .ds-247420 .ds-ep-statusbar-left, .ds-247420 .ds-ep-statusbar-right { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
8979
9579
  .ds-247420 .ds-ep-statusbar-left { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
8980
9580
  /* Buttons inside the dense strip shrink to fit the 26px band. */
8981
9581
  .ds-247420 .ds-ep-statusbar button {
8982
- min-height: 0; height: 20px; padding: 0 8px;
9582
+ min-height: 0; height: 20px; padding: 0 var(--space-2);
8983
9583
  border-radius: var(--r-1, 4px);
8984
9584
  font: var(--fs-micro, 11px)/1 var(--ff-mono, monospace);
8985
9585
  }
8986
9586
 
8987
9587
  /* Toolbar */
8988
9588
  .ds-247420 .ds-ep-toolbar {
8989
- display: flex; align-items: center; gap: 6px;
8990
- padding: 8px 10px;
9589
+ display: flex; align-items: center; gap: var(--space-1-75);
9590
+ padding: var(--space-2) var(--space-2-5);
8991
9591
  background: var(--panel-1);
8992
9592
  color: var(--panel-text);
8993
9593
  border-bottom: 1px solid var(--rule);
8994
9594
  font: var(--fs-tiny, 12px)/var(--lh-base, 1.55) var(--ff-mono, monospace);
8995
9595
  }
8996
- .ds-247420 .ds-ep-toolbar.dense { padding: 2px 4px; gap: 2px; }
9596
+ .ds-247420 .ds-ep-toolbar.dense { padding: var(--space-hair) var(--space-1); gap: var(--space-hair); }
8997
9597
  .ds-247420 .ds-ep-toolbar-leading,
8998
9598
  .ds-247420 .ds-ep-toolbar-center,
8999
- .ds-247420 .ds-ep-toolbar-trailing { display: flex; align-items: center; gap: 4px; }
9599
+ .ds-247420 .ds-ep-toolbar-trailing { display: flex; align-items: center; gap: var(--space-1); }
9000
9600
  .ds-247420 .ds-ep-toolbar-trailing { margin-left: auto; }
9001
9601
  .ds-247420 .ds-ep-toolbar-center { flex: 1; min-width: 0; }
9002
9602
 
@@ -9066,7 +9666,7 @@
9066
9666
  flex: 1; min-width: 0; appearance: none; background: transparent; border: 0;
9067
9667
  border-bottom: 2px solid transparent;
9068
9668
  color: var(--panel-text-3);
9069
- padding: 8px 10px;
9669
+ padding: var(--space-2) var(--space-2-5);
9070
9670
  font: inherit; cursor: pointer;
9071
9671
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
9072
9672
  transition: color var(--dur-snap, 80ms) var(--ease, ease), border-color var(--dur-snap, 80ms) var(--ease, ease);
@@ -9105,8 +9705,8 @@
9105
9705
  color: var(--panel-text);
9106
9706
  }
9107
9707
  .ds-247420 .ds-ep-eventrow {
9108
- display: flex; align-items: baseline; gap: 8px;
9109
- padding: 3px 8px;
9708
+ display: flex; align-items: baseline; gap: var(--space-2);
9709
+ padding: var(--space-half) var(--space-2);
9110
9710
  border-bottom: 1px solid color-mix(in oklab, var(--rule) 50%, transparent);
9111
9711
  }
9112
9712
  .ds-247420 .ds-ep-eventrow:hover { background: color-mix(in oklab, var(--accent) 6%, transparent); }
@@ -9123,8 +9723,8 @@
9123
9723
  .ds-247420 .ds-ep-tree-item { display: flex; flex-direction: column; }
9124
9724
  .ds-247420 .ds-ep-tree-item:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
9125
9725
  .ds-247420 .ds-ep-tree-row {
9126
- display: flex; align-items: center; gap: 6px;
9127
- padding: 4px 8px 4px 0;
9726
+ display: flex; align-items: center; gap: var(--space-1-75);
9727
+ padding: var(--space-1) var(--space-2) var(--space-1) 0;
9128
9728
  border-radius: var(--r-1, 10px);
9129
9729
  cursor: pointer;
9130
9730
  color: var(--panel-text-2);
@@ -9147,25 +9747,25 @@
9147
9747
  .ds-247420 .ds-ep-tree-glyph { flex-shrink: 0; color: var(--panel-text-3); }
9148
9748
  .ds-247420 .ds-ep-tree-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
9149
9749
  .ds-247420 .ds-ep-tree-tag {
9150
- flex-shrink: 0; padding-left: 6px;
9750
+ flex-shrink: 0; padding-left: var(--space-1-75);
9151
9751
  font-size: 0.85em; color: var(--panel-text-3);
9152
9752
  }
9153
9753
  .ds-247420 .ds-ep-tree-children { display: flex; flex-direction: column; }
9154
9754
 
9155
9755
  /* PropertyGrid / PropertyField */
9156
9756
  .ds-247420 .ds-ep-propgrid {
9157
- display: flex; flex-direction: column; gap: 6px;
9158
- padding: 8px;
9757
+ display: flex; flex-direction: column; gap: var(--space-1-75);
9758
+ padding: var(--space-2);
9159
9759
  color: var(--panel-text);
9160
9760
  font: var(--fs-tiny, 12px)/var(--lh-base, 1.55) var(--ff-mono, monospace);
9161
9761
  }
9162
9762
  .ds-247420 .ds-ep-propfield {
9163
9763
  display: grid;
9164
9764
  grid-template-columns: minmax(80px, 120px) 1fr;
9165
- gap: 4px 10px;
9765
+ gap: var(--space-1) var(--space-2-5);
9166
9766
  align-items: center;
9167
9767
  }
9168
- .ds-247420 .ds-ep-propfield.inline { display: flex; gap: 8px; }
9768
+ .ds-247420 .ds-ep-propfield.inline { display: flex; gap: var(--space-2); }
9169
9769
  .ds-247420 .ds-ep-propfield-label {
9170
9770
  color: var(--panel-text-3);
9171
9771
  font-size: 0.85em;
@@ -9174,7 +9774,7 @@
9174
9774
  }
9175
9775
  .ds-247420 .ds-ep-propfield-value {
9176
9776
  color: var(--panel-text);
9177
- display: flex; align-items: center; gap: 4px; min-width: 0;
9777
+ display: flex; align-items: center; gap: var(--space-1); min-width: 0;
9178
9778
  }
9179
9779
  .ds-247420 .ds-ep-propfield-value input,
9180
9780
  .ds-247420 .ds-ep-propfield-value select,
@@ -9184,7 +9784,7 @@
9184
9784
  color: var(--panel-text);
9185
9785
  border: 1px solid var(--rule);
9186
9786
  border-radius: var(--r-1, 10px);
9187
- padding: 4px 8px;
9787
+ padding: var(--space-1) var(--space-2);
9188
9788
  font: inherit;
9189
9789
  min-width: 0; width: 100%;
9190
9790
  }
@@ -9202,7 +9802,7 @@
9202
9802
  }
9203
9803
  /* x/y/z packed on one row, each field equal width, no horizontal overflow. */
9204
9804
  .ds-247420 .ds-ep-vec3 {
9205
- display: flex; gap: 4px; width: 100%; min-width: 0;
9805
+ display: flex; gap: var(--space-1); width: 100%; min-width: 0;
9206
9806
  }
9207
9807
  .ds-247420 .ds-ep-vec3 > * { flex: 1 1 0; min-width: 0; }
9208
9808
  /* Each axis cell (axis letter + scrub input) must show its full 3-decimal value
@@ -9210,7 +9810,7 @@
9210
9810
  fill the rest with tight padding and centered text so 0.000 / -0.0 / 1.000 are
9211
9811
  always legible even in the narrow 3-up layout. */
9212
9812
  .ds-247420 .ds-ep-vec3 > * {
9213
- display: flex; align-items: center; gap: 2px;
9813
+ display: flex; align-items: center; gap: var(--space-hair);
9214
9814
  }
9215
9815
  .ds-247420 .ds-ep-vec3 .ds-ep-propfield-hint {
9216
9816
  flex: 0 0 auto; width: 9px; text-align: center;
@@ -9218,12 +9818,12 @@
9218
9818
  }
9219
9819
  .ds-247420 .ds-ep-vec3 .ds-input-bare {
9220
9820
  flex: 1 1 auto; min-width: 0; width: auto;
9221
- padding: 2px 4px; text-align: center; text-overflow: clip;
9821
+ padding: var(--space-hair) var(--space-1); text-align: center; text-overflow: clip;
9222
9822
  }
9223
9823
  /* Dense numeric inputs in the inspector — compact, tight radius, mono. */
9224
9824
  .ds-247420 .ds-ep-propfield-value input,
9225
9825
  .ds-247420 .ds-ep-propfield-value .ds-input-bare {
9226
- padding: 2px 6px;
9826
+ padding: var(--space-hair) var(--space-1-75);
9227
9827
  border-radius: var(--r-1, 4px);
9228
9828
  font: var(--fs-tiny, 12px)/1.3 var(--ff-mono, monospace);
9229
9829
  }
@@ -9233,7 +9833,7 @@
9233
9833
  color: var(--panel-text);
9234
9834
  border: 1px solid var(--rule);
9235
9835
  border-radius: var(--r-1, 4px);
9236
- padding: 2px 6px;
9836
+ padding: var(--space-hair) var(--space-1-75);
9237
9837
  font: var(--fs-tiny, 12px)/1.3 var(--ff-mono, monospace);
9238
9838
  min-width: 0;
9239
9839
  }
@@ -9242,7 +9842,7 @@
9242
9842
  control below) — used for wide segmented controls that would clip in the
9243
9843
  narrow value column. */
9244
9844
  .ds-247420 .ds-ep-propfield.block {
9245
- display: flex; flex-direction: column; align-items: stretch; gap: 4px;
9845
+ display: flex; flex-direction: column; align-items: stretch; gap: var(--space-1);
9246
9846
  }
9247
9847
  .ds-247420 .ds-ep-propfield.block > .ds-ep-propfield-value { width: 100%; }
9248
9848
  .ds-247420 .ds-ep-propfield.block .ds-ep-btngrp { width: 100%; }
@@ -9291,8 +9891,8 @@
9291
9891
  Compact buttons, square-ish, bordered top — not big floating pills. */
9292
9892
  .ds-247420 .ds-ep-actionbar {
9293
9893
  flex-shrink: 0;
9294
- display: flex; align-items: center; gap: 6px;
9295
- padding: 6px 8px;
9894
+ display: flex; align-items: center; gap: var(--space-1-75);
9895
+ padding: var(--space-1-75) var(--space-2);
9296
9896
  border-top: 1px solid var(--rule);
9297
9897
  background: var(--panel-1);
9298
9898
  }
@@ -9310,7 +9910,7 @@
9310
9910
  IconButtonGroup which manages its own sizing. */
9311
9911
  .ds-247420 .ds-ep-tree-row button:not(.ds-ep-btngrp-btn),
9312
9912
  .ds-247420 .ds-ep-toolbar button:not(.ds-ep-btngrp-btn) {
9313
- min-height: 24px; height: 24px; padding: 0 8px;
9913
+ min-height: 24px; height: 24px; padding: 0 var(--space-2);
9314
9914
  border-radius: var(--r-1, 4px);
9315
9915
  font: var(--fs-tiny, 12px)/1 var(--ff-mono, monospace);
9316
9916
  }
@@ -9346,7 +9946,7 @@
9346
9946
  border: 1px solid var(--rule);
9347
9947
  color: var(--panel-text, var(--fg));
9348
9948
  min-width: 1.75em;
9349
- padding: var(--space-half, 3px) var(--space-1, 5px);
9949
+ padding: var(--space-half, 3px) var(--space-1, 4px);
9350
9950
  border-radius: var(--r-1, 4px);
9351
9951
  font: inherit;
9352
9952
  text-align: center;
@@ -9358,6 +9958,15 @@
9358
9958
  border-color: var(--accent);
9359
9959
  }
9360
9960
  .ds-247420 .ds-ep-pager-ellipsis { padding: 0 var(--space-hair, 2px); opacity: 0.6; }
9961
+ /* Touch floor. Pager controls render ~21px tall, so on a coarse pointer they
9962
+ were the smallest interactive targets in the kit — every other control family
9963
+ here (.ds-sub-btn, .ds-session-row, .ds-file-act, .btn) already floors at
9964
+ 44px, and paging is a repeated, mis-tap-prone action. The visible mark stays
9965
+ compact; only the hit area grows. */
9966
+ @media (pointer: coarse) {
9967
+ .ds-247420 .ds-ep-pager-btn, .ds-247420 .ds-ep-pager-num { min-height: 44px; min-width: 44px; }
9968
+ .ds-247420 .ds-ep-pager { gap: var(--space-2); }
9969
+ }
9361
9970
  .ds-247420 .ds-ep-pager-total { white-space: nowrap; margin-left: auto; }
9362
9971
 
9363
9972
  /* Grid / GridItem — 24-column responsive layout. GridItem's flex-basis is
@@ -9438,7 +10047,7 @@
9438
10047
  /* Collapsible tree mode — native details/summary, indent guides on children. */
9439
10048
  .ds-247420 .ds-ep-json-tree { white-space: normal; }
9440
10049
  .ds-247420 .ds-ep-json-kids {
9441
- padding-left: var(--space-3-5, 14px);
10050
+ padding-left: var(--space-3-5, 20px);
9442
10051
  margin-left: var(--space-1, 4px);
9443
10052
  border-left: 1px solid var(--rule);
9444
10053
  }
@@ -9450,7 +10059,7 @@
9450
10059
  .ds-247420 .ds-ep-json-sum::-webkit-details-marker { display: none; }
9451
10060
  .ds-247420 .ds-ep-json-sum::before {
9452
10061
  content: '+';
9453
- display: inline-block; width: var(--space-3, 12px);
10062
+ display: inline-block; width: var(--space-3, 16px);
9454
10063
  color: var(--panel-text-3, var(--fg-3));
9455
10064
  }
9456
10065
  .ds-247420 .ds-ep-json-node[open] > .ds-ep-json-sum::before { content: '-'; }
@@ -9464,11 +10073,11 @@
9464
10073
  font-size: var(--fs-micro, 11px);
9465
10074
  color: var(--panel-text-3, var(--fg-3));
9466
10075
  }
9467
- .ds-247420 .ds-ep-json-leaf { padding-left: var(--space-3, 12px); word-break: break-all; }
10076
+ .ds-247420 .ds-ep-json-leaf { padding-left: var(--space-3, 16px); word-break: break-all; }
9468
10077
  /* Copy affordance (copyable:true) — floats over the viewer's top-right. */
9469
10078
  .ds-247420 .ds-ep-json-wrap { position: relative; }
9470
10079
  .ds-247420 .ds-ep-json-copy {
9471
- position: absolute; top: var(--space-1-75, 6px); right: var(--space-1-75, 6px); z-index: 1;
10080
+ position: absolute; top: var(--space-1-75, 6px); right: var(--space-1-75, 6px); z-index: var(--z-raised);
9472
10081
  appearance: none; cursor: pointer;
9473
10082
  background: var(--panel-1, var(--bg-1));
9474
10083
  border: 1px solid var(--rule);
@@ -9526,12 +10135,12 @@
9526
10135
  overflow: hidden;
9527
10136
  background: var(--panel-2);
9528
10137
  }
9529
- .ds-247420 .ds-ep-btngrp.dense .ds-ep-btngrp-btn { padding: 2px 6px; min-width: 22px; }
10138
+ .ds-247420 .ds-ep-btngrp.dense .ds-ep-btngrp-btn { padding: var(--space-hair) var(--space-1-75); min-width: 22px; }
9530
10139
  .ds-247420 .ds-ep-btngrp-btn {
9531
10140
  appearance: none; border: 0;
9532
10141
  background: transparent;
9533
10142
  color: var(--panel-text-2);
9534
- padding: 4px 10px;
10143
+ padding: var(--space-1) var(--space-2-5);
9535
10144
  font: inherit; cursor: pointer;
9536
10145
  border-right: 1px solid var(--rule);
9537
10146
  transition: background var(--dur-snap, 80ms) var(--ease, ease), color var(--dur-snap, 80ms) var(--ease, ease);
@@ -9585,7 +10194,7 @@
9585
10194
  ContextMenu
9586
10195
  --------------------------------------------------------------- */
9587
10196
  .ds-247420 .ds-ep-ctxmenu-backdrop {
9588
- position: fixed; inset: 0; z-index: 9000;
10197
+ position: fixed; inset: 0; z-index: var(--z-dropdown);
9589
10198
  }
9590
10199
  .ds-247420 .ds-ep-ctxmenu {
9591
10200
  position: absolute;
@@ -9600,13 +10209,13 @@
9600
10209
  border: 1px solid var(--rule);
9601
10210
  border-radius: var(--r-2, 8px);
9602
10211
  box-shadow: var(--shadow-2);
9603
- padding: 4px;
10212
+ padding: var(--space-1);
9604
10213
  display: flex; flex-direction: column;
9605
10214
  outline: none;
9606
10215
  }
9607
10216
  .ds-247420 .ds-ep-ctxmenu-item {
9608
- display: flex; align-items: center; gap: 8px;
9609
- padding: 8px 10px;
10217
+ display: flex; align-items: center; gap: var(--space-2);
10218
+ padding: var(--space-2) var(--space-2-5);
9610
10219
  background: transparent; border: 0;
9611
10220
  color: inherit; font: inherit; text-align: left;
9612
10221
  border-radius: var(--r-1, 4px);
@@ -9619,13 +10228,13 @@
9619
10228
  .ds-247420 .ds-ep-ctxmenu-item.danger { color: var(--danger); }
9620
10229
  .ds-247420 .ds-ep-ctxmenu-item.disabled { opacity: 0.45; cursor: not-allowed; }
9621
10230
  .ds-247420 .ds-ep-ctxmenu-icon { width: 16px; display: inline-flex; justify-content: center; }
9622
- .ds-247420 .ds-ep-ctxmenu-sep { height: 1px; background: var(--rule); margin: 4px 6px; }
10231
+ .ds-247420 .ds-ep-ctxmenu-sep { height: 1px; background: var(--rule); margin: var(--space-1) var(--space-1-75); }
9623
10232
 
9624
10233
  /* ---------------------------------------------------------------
9625
10234
  Drawer
9626
10235
  --------------------------------------------------------------- */
9627
10236
  .ds-247420 .ds-ep-drawer-backdrop {
9628
- position: fixed; inset: 0; z-index: 8500;
10237
+ position: fixed; inset: 0; z-index: var(--z-drawer);
9629
10238
  background: var(--scrim);
9630
10239
  }
9631
10240
  .ds-247420 .ds-ep-drawer {
@@ -9635,11 +10244,11 @@
9635
10244
  box-shadow: var(--shadow-overlay);
9636
10245
  outline: none;
9637
10246
  transition: transform 180ms ease;
9638
- padding: 12px;
9639
- padding-top: max(12px, env(safe-area-inset-top));
9640
- padding-bottom: max(12px, env(safe-area-inset-bottom));
9641
- padding-left: max(12px, env(safe-area-inset-left));
9642
- padding-right: max(12px, env(safe-area-inset-right));
10247
+ padding: var(--space-2-75);
10248
+ padding-top: max(var(--space-2-75), env(safe-area-inset-top));
10249
+ padding-bottom: max(var(--space-2-75), env(safe-area-inset-bottom));
10250
+ padding-left: max(var(--space-2-75), env(safe-area-inset-left));
10251
+ padding-right: max(var(--space-2-75), env(safe-area-inset-right));
9643
10252
  }
9644
10253
  .ds-247420 .ds-ep-drawer.side-left { left: 0; top: 0; bottom: 0; width: 86vw; max-width: 320px; }
9645
10254
  .ds-247420 .ds-ep-drawer.side-right { right: 0; top: 0; bottom: 0; width: 86vw; max-width: 320px; }
@@ -9652,10 +10261,10 @@
9652
10261
  Dialog
9653
10262
  --------------------------------------------------------------- */
9654
10263
  .ds-247420 .ds-ep-dialog-backdrop {
9655
- position: fixed; inset: 0; z-index: 9500;
10264
+ position: fixed; inset: 0; z-index: var(--z-modal);
9656
10265
  background: var(--scrim-strong);
9657
10266
  display: flex; align-items: center; justify-content: center;
9658
- padding: max(16px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) max(16px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
10267
+ padding: max(var(--space-3), env(safe-area-inset-top)) max(var(--space-3), env(safe-area-inset-right)) max(var(--space-3), env(safe-area-inset-bottom)) max(var(--space-3), env(safe-area-inset-left));
9659
10268
  }
9660
10269
  .ds-247420 .ds-ep-dialog {
9661
10270
  background: var(--panel-1, var(--panel-bg));
@@ -9705,8 +10314,8 @@
9705
10314
  position: fixed;
9706
10315
  top: max(16px, env(safe-area-inset-top));
9707
10316
  right: max(16px, env(safe-area-inset-right));
9708
- z-index: 9800;
9709
- display: flex; flex-direction: column; gap: 8px;
10317
+ z-index: var(--z-toast);
10318
+ display: flex; flex-direction: column; gap: var(--space-2);
9710
10319
  pointer-events: none;
9711
10320
  }
9712
10321
  .ds-247420 .ds-ep-toast {
@@ -9714,7 +10323,13 @@
9714
10323
  background: var(--panel-1, var(--panel-bg));
9715
10324
  color: var(--panel-text, var(--fg-text));
9716
10325
  border: 1px solid var(--rule);
9717
- border-left: 3px solid var(--accent);
10326
+ /* DELIBERATE accent spine (same intent as .panel-spine, expressed as a
10327
+ border because a toast has no free ::before — the host stacks them and
10328
+ .has-action reflows the box). Load-bearing, not decoration: this edge is
10329
+ the ONLY channel carrying toast severity — .kind-success/.kind-warn/
10330
+ .kind-error below recolour border-left-color and nothing else. Do not
10331
+ demote to a hairline; that would erase the status signal. */
10332
+ border-left: var(--bw-chunk) solid var(--accent);
9718
10333
  border-radius: var(--r-1, 6px);
9719
10334
  padding: var(--space-2) var(--space-2-75);
9720
10335
  box-shadow: var(--shadow-3);
@@ -9773,8 +10388,8 @@
9773
10388
  .ds-247420 .ds-ep-tree-row,
9774
10389
  .ds-247420 .ds-ep-pager-btn {
9775
10390
  min-height: 44px;
9776
- padding-top: 10px;
9777
- padding-bottom: 10px;
10391
+ padding-top: var(--space-2-5);
10392
+ padding-bottom: var(--space-2-5);
9778
10393
  }
9779
10394
  .ds-247420 .ds-ep-resize.axis-h { width: 14px; }
9780
10395
  .ds-247420 .ds-ep-resize.axis-v { height: 14px; }
@@ -9919,6 +10534,10 @@
9919
10534
 
9920
10535
  .ds-247420 .sr-only {
9921
10536
  position: absolute; width: 1px; height: 1px;
10537
+ /* margin:-1px is OFF-SCALE ON PURPOSE — it is not rhythm, it is the
10538
+ canonical visually-hidden idiom: the negative margin cancels the 1px
10539
+ box so the clipped element contributes zero layout. Snapping it to a
10540
+ --space-* rung would reintroduce a measurable gap. */
9922
10541
  padding: 0; margin: -1px; overflow: hidden;
9923
10542
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
9924
10543
  }
@@ -9933,7 +10552,7 @@
9933
10552
  .ds-247420 .ds-tooltip {
9934
10553
  position: fixed;
9935
10554
  left: 0; top: 0;
9936
- z-index: 9700;
10555
+ z-index: var(--z-tooltip);
9937
10556
  background: var(--panel-1, var(--panel-bg));
9938
10557
  color: var(--panel-text, var(--fg-text));
9939
10558
  border: 1px solid var(--rule);
@@ -9956,7 +10575,7 @@
9956
10575
  .ds-247420 .ds-popover {
9957
10576
  position: fixed;
9958
10577
  left: 0; top: 0;
9959
- z-index: 9600;
10578
+ z-index: var(--z-dropdown);
9960
10579
  background: var(--panel-1, var(--panel-bg));
9961
10580
  color: var(--panel-text, var(--fg-text));
9962
10581
  border: 1px solid var(--rule);
@@ -9978,10 +10597,10 @@
9978
10597
  /* ---------------------------------------------------------------
9979
10598
  Dropdown
9980
10599
  --------------------------------------------------------------- */
9981
- .ds-247420 .ds-dropdown-menu { padding: 4px; }
10600
+ .ds-247420 .ds-dropdown-menu { padding: var(--space-1); }
9982
10601
  .ds-247420 .ds-dropdown-list { display: flex; flex-direction: column; }
9983
10602
  .ds-247420 .ds-dropdown-item {
9984
- display: flex; align-items: center; gap: 8px;
10603
+ display: flex; align-items: center; gap: var(--space-2);
9985
10604
  /* Dense desktop row (was an unconditional 44px touch target — a menu of
9986
10605
  these was very tall on desktop). ~30px here; the 44px tap target is
9987
10606
  restored under @media(pointer:coarse) below, matching the .ds-check-row
@@ -10013,7 +10632,7 @@
10013
10632
  .ds-247420 .ds-dropdown-item.is-danger { color: var(--danger); }
10014
10633
  .ds-247420 .ds-dropdown-glyph { width: 16px; display: inline-flex; justify-content: center; flex-shrink: 0; }
10015
10634
  .ds-247420 .ds-dropdown-label { flex: 1; min-width: 0; }
10016
- .ds-247420 .ds-dropdown-separator { height: 1px; background: var(--rule); margin: 4px 6px; }
10635
+ .ds-247420 .ds-dropdown-separator { height: 1px; background: var(--rule); margin: var(--space-1) var(--space-1-75); }
10017
10636
  .ds-247420 .ds-dropdown-trigger {
10018
10637
  appearance: none;
10019
10638
  background: var(--panel-2, transparent);
@@ -10153,7 +10772,7 @@
10153
10772
  border-radius: var(--r-1, 10px);
10154
10773
  background: var(--panel-2, var(--panel-1)); color: var(--panel-text);
10155
10774
  }
10156
- .ds-247420 .ds-kbd-group { margin: var(--space-3, 12px) 0; }
10775
+ .ds-247420 .ds-kbd-group { margin: var(--space-3, 16px) 0; }
10157
10776
  .ds-247420 .ds-kbd-group h3 { font-size: 0.9em; opacity: 0.7; margin: 0 0 var(--space-1, 4px); text-transform: capitalize; }
10158
10777
  /* One shortcut per row: the key chip on the left, its description on the right,
10159
10778
  so the dialog reads as "G Translate gizmo" rather than a wall of bare keys. */
@@ -10167,7 +10786,7 @@
10167
10786
  --------------------------------------------------------------- */
10168
10787
  .ds-247420 .ov-cmd-backdrop {
10169
10788
  position: fixed; inset: 0;
10170
- z-index: var(--z-overlay, 1000);
10789
+ z-index: var(--z-modal);
10171
10790
  background: color-mix(in oklab, var(--fg) 32%, transparent);
10172
10791
  display: flex; align-items: flex-start; justify-content: center;
10173
10792
  padding: 12vh var(--space-3, 16px) var(--space-3, 16px);
@@ -10222,7 +10841,8 @@
10222
10841
  --------------------------------------------------------------- */
10223
10842
  .ds-247420 .ov-emoji-root {
10224
10843
  position: fixed; left: 0; top: 0;
10225
- z-index: var(--z-overlay, 1000);
10844
+ /* Anchored to a trigger, not a blocking surface — dropdown rung. */
10845
+ z-index: var(--z-dropdown);
10226
10846
  width: 280px;
10227
10847
  display: flex; flex-direction: column;
10228
10848
  background: var(--bg-2); color: var(--fg);
@@ -10260,7 +10880,7 @@
10260
10880
  --------------------------------------------------------------- */
10261
10881
  .ds-247420 .ov-boot {
10262
10882
  position: fixed; inset: 0;
10263
- z-index: calc(var(--z-overlay, 1000) + 100);
10883
+ z-index: var(--z-top);
10264
10884
  background: var(--bg);
10265
10885
  display: flex; align-items: center; justify-content: center;
10266
10886
  color: var(--fg);
@@ -10303,7 +10923,8 @@
10303
10923
  --------------------------------------------------------------- */
10304
10924
  .ds-247420 .ov-set-root {
10305
10925
  position: fixed; left: 0; top: 0;
10306
- z-index: var(--z-overlay, 1000);
10926
+ /* Anchored to a trigger, not a blocking surface — dropdown rung. */
10927
+ z-index: var(--z-dropdown);
10307
10928
  width: 300px; max-height: 70vh;
10308
10929
  display: flex; flex-direction: column;
10309
10930
  background: var(--bg-2); color: var(--fg);
@@ -10352,7 +10973,7 @@
10352
10973
 
10353
10974
  /* AuthModal — ov-auth-* */
10354
10975
  .ds-247420 .ov-auth-backdrop {
10355
- position: fixed; inset: 0; z-index: var(--z-overlay, 1000);
10976
+ position: fixed; inset: 0; z-index: var(--z-modal);
10356
10977
  display: flex; align-items: center; justify-content: center;
10357
10978
  background: var(--scrim-strong);
10358
10979
  }
@@ -10381,7 +11002,7 @@
10381
11002
 
10382
11003
  /* VideoLightbox — ov-lightbox-* */
10383
11004
  .ds-247420 .ov-lightbox-backdrop {
10384
- position: fixed; inset: 0; z-index: var(--z-overlay-top, 1100);
11005
+ position: fixed; inset: 0; z-index: var(--z-modal);
10385
11006
  display: flex; align-items: center; justify-content: center;
10386
11007
  background: var(--scrim-media);
10387
11008
  }
@@ -10435,7 +11056,7 @@
10435
11056
  border: 1px solid var(--rule); border-radius: var(--r-1, 4px);
10436
11057
  background: var(--panel-2); cursor: pointer; flex-shrink: 0;
10437
11058
  }
10438
- .ds-247420 .ds-input-color::-webkit-color-swatch-wrapper { padding: 2px; }
11059
+ .ds-247420 .ds-input-color::-webkit-color-swatch-wrapper { padding: var(--space-hair); }
10439
11060
  .ds-247420 .ds-input-color::-webkit-color-swatch { border: none; border-radius: var(--r-hair); }
10440
11061
  .ds-247420 .ds-input-color:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
10441
11062
  .ds-247420 .ds-input-check {
@@ -10498,8 +11119,8 @@
10498
11119
  /* Collapsed: shrink to just the header strip, freeing the viewport. */
10499
11120
  .ds-247420 .ds-ep-dock.collapsed { bottom: auto; height: auto; }
10500
11121
  .ds-247420 .ds-ep-dock-head {
10501
- display: flex; align-items: center; gap: 6px;
10502
- flex: 0 0 auto; padding: 4px 6px 4px 10px;
11122
+ display: flex; align-items: center; gap: var(--space-1-75);
11123
+ flex: 0 0 auto; padding: var(--space-1) var(--space-1-75) var(--space-1) var(--space-2-5);
10503
11124
  border-bottom: 1px solid var(--rule);
10504
11125
  background: color-mix(in oklab, var(--panel-1) 60%, transparent);
10505
11126
  }
@@ -10530,7 +11151,7 @@
10530
11151
  border-radius: var(--r-1, 4px);
10531
11152
  background: var(--panel-2, var(--bg-2));
10532
11153
  }
10533
- .ds-247420 .ds-ep-collapse + .ds-ep-collapse { margin-top: var(--space-1, 5px); }
11154
+ .ds-247420 .ds-ep-collapse + .ds-ep-collapse { margin-top: var(--space-1, 4px); }
10534
11155
  .ds-247420 .ds-ep-collapse-head {
10535
11156
  appearance: none; cursor: pointer; width: 100%;
10536
11157
  display: flex; align-items: center; gap: var(--space-1-5, 5px);
@@ -10597,7 +11218,7 @@
10597
11218
  .ds-247420 .ov-perm-action {
10598
11219
  flex: 1; appearance: none; border: 1px solid var(--rule); background: transparent;
10599
11220
  color: var(--fg-2); font: inherit; font-size: var(--fs-tiny, 12px);
10600
- padding: 4px 8px; border-radius: var(--r-1, 10px); cursor: pointer;
11221
+ padding: var(--space-1) var(--space-2); border-radius: var(--r-1, 10px); cursor: pointer;
10601
11222
  }
10602
11223
  .ds-247420 .ov-perm-action:hover { background: var(--panel-2, var(--rule)); }
10603
11224
 
@@ -10828,7 +11449,7 @@
10828
11449
  @media (max-width: 900px) {
10829
11450
  .ds-247420.ds-247420 .ca-rail {
10830
11451
  position: absolute;
10831
- z-index: 20;
11452
+ z-index: calc(var(--z-drawer) + 1);
10832
11453
  top: 0; left: 0; bottom: 0;
10833
11454
  width: 240px; min-width: 240px;
10834
11455
  transform: translateX(-110%);
@@ -10843,7 +11464,7 @@
10843
11464
  content: '';
10844
11465
  position: absolute;
10845
11466
  inset: 0;
10846
- z-index: 15;
11467
+ z-index: var(--z-drawer);
10847
11468
  background: color-mix(in oklab, var(--ink, #000) 40%, transparent);
10848
11469
  pointer-events: none;
10849
11470
  }
@@ -11078,7 +11699,15 @@
11078
11699
 
11079
11700
  /* Event-list row hover + search-result flash. */
11080
11701
  .ds-247420 .ds-event-list .row[role="button"]:hover { background: color-mix(in srgb, var(--fg) 5%, transparent); }
11081
- .ds-247420 .ds-event-list .row.event-flash { animation: agentgui-event-flash 2s ease-out; }
11702
+ /* Opt-in like every other animation in the kit: the flash is declared only
11703
+ under no-preference, so a reduced-motion user gets the row without a 2s
11704
+ pulsing highlight. It animates background rather than transform, so the
11705
+ vestibular risk is low, but a repeating attention pull is still exactly the
11706
+ kind of thing the preference exists to suppress. The row is located by the
11707
+ scroll-into-view that accompanies it, so nothing is lost when it is absent. */
11708
+ @media (prefers-reduced-motion: no-preference) {
11709
+ .ds-247420 .ds-event-list .row.event-flash { animation: agentgui-event-flash 2s ease-out; }
11710
+ }
11082
11711
 
11083
11712
 
11084
11713
  /* Generic interactive focus ring for app-emitted controls. */
@@ -11167,6 +11796,11 @@
11167
11796
  .ds-247420 #ds-article-host.has-toc {
11168
11797
  display: flex;
11169
11798
  align-items: flex-start;
11799
+ /* 44px is OFF-SCALE ON PURPOSE — it is not a rhythm step but one term of the
11800
+ three-term width equation on the next line (256px rail + 44px gutter +
11801
+ measure). It sits between --space-6 (48) and --space-5 (32); snapping it
11802
+ would silently change the host's computed max-width unless the calc were
11803
+ re-derived, so the literal and the calc stay coupled and explicit. */
11170
11804
  column-gap: 44px;
11171
11805
  gap: 44px;
11172
11806
  max-width: calc(256px + 44px + var(--measure-narrow));
@@ -11190,7 +11824,7 @@
11190
11824
  overscroll-behavior: contain;
11191
11825
  margin: 0;
11192
11826
  max-width: 100%;
11193
- padding: 18px 18px 18px 20px;
11827
+ padding: var(--space-3-5);
11194
11828
  background: var(--panel-1);
11195
11829
  border-radius: var(--r-1);
11196
11830
  box-shadow: var(--panel-shadow);
@@ -11209,15 +11843,28 @@
11209
11843
  background: var(--panel-text-3);
11210
11844
  background-clip: padding-box;
11211
11845
  }
11212
- .ds-247420 #ds-article-host .toc .toc-title {
11846
+ /* Small-label voice — the local composition of the house `.t-label` recipe
11847
+ (src/css/app-shell/base.css). This sheet is a standalone published export
11848
+ with its own <link>, so it cannot join the `.t-label` selector list; it
11849
+ composes by referencing the identical token set. Both members are gm-
11850
+ generated markup (injected into #ds-article-host), so the class list is not
11851
+ reachable from src/ — the rule, not the markup, does the composing.
11852
+ Deliberate override for both: --panel-text-2, because prose surfaces use the
11853
+ panel text ramp rather than the app --fg ramp. Sized at --fs-nano: these
11854
+ labels ride above dense article chrome, not UI text. */
11855
+ .ds-247420 #ds-article-host .toc .toc-title,
11856
+ .ds-247420 .ds-prose .gm-callout .who {
11213
11857
  font-family: var(--ff-mono);
11214
- font-size: 11px;
11858
+ font-size: var(--fs-nano);
11215
11859
  text-transform: uppercase;
11216
- letter-spacing: .09em;
11860
+ letter-spacing: var(--tr-label);
11217
11861
  color: var(--panel-text-2);
11218
- margin: 0 0 14px 0;
11219
11862
  }
11220
- .ds-247420 #ds-article-host .toc ol { margin: 0; padding-left: 18px; }
11863
+
11864
+ .ds-247420 #ds-article-host .toc .toc-title {
11865
+ margin: 0 0 var(--space-3) 0;
11866
+ }
11867
+ .ds-247420 #ds-article-host .toc ol { margin: 0; padding-left: var(--space-3-5); }
11221
11868
  .ds-247420 #ds-article-host .toc li { font-size: 13px; line-height: 1.85; color: var(--panel-text); }
11222
11869
  .ds-247420 #ds-article-host .toc li::marker { color: var(--panel-text-3); font-variant-numeric: tabular-nums; }
11223
11870
  .ds-247420 #ds-article-host .toc a { color: var(--panel-text-2); text-decoration: none; transition: color .12s ease; }
@@ -11230,7 +11877,7 @@
11230
11877
  position: static;
11231
11878
  max-height: none;
11232
11879
  overflow: visible;
11233
- margin: 0 0 28px 0;
11880
+ margin: 0 0 var(--space-5) 0;
11234
11881
  }
11235
11882
  }
11236
11883
 
@@ -11246,8 +11893,8 @@
11246
11893
  display: block;
11247
11894
  background: var(--panel-1);
11248
11895
  border-radius: var(--r-0);
11249
- padding: 16px 20px;
11250
- margin: 16px 0 28px 0;
11896
+ padding: var(--space-3) var(--space-3-5);
11897
+ margin: var(--space-3) 0 var(--space-5) 0;
11251
11898
  font-family: var(--ff-mono);
11252
11899
  font-size: 12.5px;
11253
11900
  line-height: 1.6;
@@ -11262,14 +11909,14 @@
11262
11909
  white-space: pre-wrap;
11263
11910
  word-break: break-word;
11264
11911
  min-height: 1.4em;
11265
- padding: 3px 0;
11912
+ padding: var(--space-half) 0;
11266
11913
  line-height: 1.6;
11267
11914
  }
11268
11915
  .ds-247420 .ds-cli-block .ds-cli-comment:empty::before { content: '\00a0'; }
11269
11916
  .ds-247420 .ds-cli-block .ds-cli-row {
11270
11917
  display: flex;
11271
- gap: 10px;
11272
- padding: 3px 0;
11918
+ gap: var(--space-2-5);
11919
+ padding: var(--space-half) 0;
11273
11920
  white-space: pre-wrap;
11274
11921
  word-break: break-word;
11275
11922
  }
@@ -11285,14 +11932,14 @@
11285
11932
  word-break: break-word;
11286
11933
  }
11287
11934
 
11288
- .ds-247420 .panel .row { align-items: flex-start; padding: 16px 20px; gap: 16px; }
11935
+ .ds-247420 .panel .row { align-items: flex-start; padding: var(--space-3) var(--space-3-5); gap: var(--space-3); }
11289
11936
  .ds-247420 .panel .row + .row { box-shadow: inset 0 1px 0 var(--rule); }
11290
- .ds-247420 .panel .row .code { padding-top: 2px; min-width: 28px; }
11291
- .ds-247420 .panel .row .meta { padding-top: 2px; opacity: 0.4; }
11937
+ .ds-247420 .panel .row .code { padding-top: var(--space-hair); min-width: 28px; }
11938
+ .ds-247420 .panel .row .meta { padding-top: var(--space-hair); opacity: 0.4; }
11292
11939
  .ds-247420 .panel .row .title { display: block; line-height: 1.4; }
11293
11940
  .ds-247420 .panel .row .title .sub {
11294
11941
  display: block;
11295
- margin-top: 6px;
11942
+ margin-top: var(--space-1-75);
11296
11943
  font-weight: 400;
11297
11944
  color: var(--panel-text-2);
11298
11945
  font-size: 13px;
@@ -11302,9 +11949,9 @@
11302
11949
  .ds-247420 .ds-prose .card {
11303
11950
  display: flex;
11304
11951
  flex-direction: column;
11305
- gap: 8px;
11306
- padding: 14px 18px;
11307
- margin: 8px 0;
11952
+ gap: var(--space-2);
11953
+ padding: var(--space-2-75) var(--space-3-5);
11954
+ margin: var(--space-2) 0;
11308
11955
  background: var(--panel-1);
11309
11956
  border-radius: var(--r-0);
11310
11957
  font-size: 13px;
@@ -11312,35 +11959,46 @@
11312
11959
  text-decoration: none;
11313
11960
  }
11314
11961
  .ds-247420 .ds-prose .card:hover { background: var(--panel-hover); }
11315
- .ds-247420 .ds-prose .card .card-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
11962
+ .ds-247420 .ds-prose .card .card-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2-75); }
11316
11963
  .ds-247420 .ds-prose .card .repo-name { font-weight: 600; color: var(--panel-text); }
11317
11964
  .ds-247420 .ds-prose .card .stars { color: var(--panel-text-3); font-family: var(--ff-mono); font-size: 12px; flex: 0 0 auto; }
11318
11965
  .ds-247420 .ds-prose .card .desc { color: var(--panel-text-2); font-size: 12px; line-height: 1.5; margin: 0; }
11319
- .ds-247420 .ds-prose .tags { display: flex; gap: 6px; flex-wrap: wrap; }
11966
+ .ds-247420 .ds-prose .tags { display: flex; gap: var(--space-1-75); flex-wrap: wrap; }
11320
11967
  .ds-247420 .ds-prose .tag {
11321
11968
  background: var(--panel-2);
11322
11969
  color: var(--panel-text-2);
11323
11970
  border: 1px solid var(--panel-3);
11324
11971
  font-size: 0.7rem;
11972
+ /* rem, not --space-*: the chip's inset is deliberately tied to the root type
11973
+ scale alongside its own 0.7rem size, so the capsule keeps its proportions
11974
+ when a doc site scales root font-size. A px rung would decouple them. */
11325
11975
  padding: 0.15rem 0.5rem;
11326
11976
  border-radius: var(--r-hair);
11327
11977
  font-family: var(--ff-mono);
11328
11978
  }
11979
+ /* Attributed callout — an editorial pull-quote (it carries a .who byline), so
11980
+ the left accent is DELIBERATE, not the generic alert stripe. Expressed via
11981
+ the house .panel-spine idiom (absolute ::before rail at --bw-chunk, squared
11982
+ leading corners) instead of a raw 3px border-left, so it stays on the border
11983
+ scale and matches the spine primitive in panel-row.css. */
11329
11984
  .ds-247420 .ds-prose .gm-callout {
11330
- margin: 18px 0;
11331
- padding: 14px 18px;
11985
+ position: relative;
11986
+ margin: var(--space-3-5) 0;
11987
+ padding: var(--space-2-75) var(--space-3-5);
11988
+ padding-left: calc(var(--space-3-5) + var(--bw-chunk));
11332
11989
  background: var(--panel-1);
11333
- border-left: 3px solid var(--panel-accent);
11990
+ border-radius: 0 var(--r-1) var(--r-1) 0;
11334
11991
  color: var(--panel-text);
11335
11992
  }
11993
+ .ds-247420 .ds-prose .gm-callout::before {
11994
+ content: ''; position: absolute; left: 0; top: 0; bottom: 0;
11995
+ width: var(--bw-chunk); background: var(--panel-accent);
11996
+ border-radius: var(--bw-chunk) 0 0 var(--bw-chunk);
11997
+ }
11998
+ /* Joins the small-label voice above; only its own box properties here. */
11336
11999
  .ds-247420 .ds-prose .gm-callout .who {
11337
12000
  display: block;
11338
- font-family: var(--ff-mono);
11339
- font-size: 11px;
11340
- text-transform: uppercase;
11341
- letter-spacing: .08em;
11342
- color: var(--panel-text-2);
11343
- margin-bottom: 4px;
12001
+ margin-bottom: var(--space-1);
11344
12002
  }
11345
12003
 
11346
12004
  /* marketing.css */
@@ -11382,7 +12040,7 @@
11382
12040
  .ds-247420 .sp-loading {
11383
12041
  position: fixed;
11384
12042
  inset: 0;
11385
- z-index: 10000;
12043
+ z-index: var(--z-top);
11386
12044
  display: flex;
11387
12045
  align-items: center;
11388
12046
  justify-content: center;
@@ -11513,7 +12171,7 @@
11513
12171
  .ds-247420 .sp-lobby {
11514
12172
  position: fixed;
11515
12173
  inset: 0;
11516
- z-index: 9500;
12174
+ z-index: var(--z-modal);
11517
12175
  display: flex;
11518
12176
  align-items: center;
11519
12177
  justify-content: center;