agentgui 1.0.1049 → 1.0.1050

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.
@@ -186,7 +186,9 @@
186
186
  --space-1-75: 6px;
187
187
  --space-2: 8px;
188
188
  --space-2-5: 10px;
189
+ --space-2-75: 12px; /* fills the 10->16 hole (row-form gap, dense cell pad) */
189
190
  --space-3: 16px;
191
+ --space-3-5: 20px; /* fills the 16->24 hole (settings body, mono block pad) */
190
192
  --space-4: 24px;
191
193
  --space-5: 32px;
192
194
  --space-6: 48px;
@@ -260,6 +262,19 @@
260
262
  --size-base: 42px;
261
263
  --size-lg: 56px;
262
264
 
265
+ /* Dense control-height ladder — the actual heights front-door controls
266
+ (buttons, fields, rows) snap to, one rung tighter than the --size-*
267
+ chrome scale so app UI reads compact instead of marketing-scale. Density
268
+ scales them so [data-density=compact/spacious] moves every control at once.
269
+ Mirrors webgeist's 30/38/46 button ladder, retuned for this system. */
270
+ --ctl-sm: calc(28px * var(--density));
271
+ --ctl-md: calc(34px * var(--density));
272
+ --ctl-lg: calc(42px * var(--density));
273
+ /* The canonical single-line input/select/searchfield height (== --ctl-md)
274
+ and the default list-row min-height, both density-aware. */
275
+ --field-height: var(--ctl-md);
276
+ --row-height: calc(40px * var(--density));
277
+
263
278
  /* Unified focus-ring tokens (single source for the design system). Outset
264
279
  rings (the default) tokenize colour+width+offset; bordered text fields use
265
280
  the inset variant. Deliberate negative offsets on edge-flush/clipping
@@ -289,25 +304,26 @@
289
304
  outline-offset: var(--focus-offset);
290
305
  }
291
306
 
292
- /* Link focus-visible */
307
+ /* Link focus-visible — all route through the single --focus-* token set so a
308
+ focus retune (colour/width/offset) happens in one place, never per selector. */
293
309
  .ds-247420 a:focus-visible,
294
310
  .ds-247420[role="link"]:focus-visible {
295
- outline: 2px solid var(--accent-ink);
296
- outline-offset: 2px;
311
+ outline: var(--focus-w) solid var(--focus-color);
312
+ outline-offset: var(--focus-offset);
297
313
  }
298
314
 
299
315
  /* Form inputs with focus-visible */
300
316
  .ds-247420 input:focus-visible,
301
317
  .ds-247420 textarea:focus-visible,
302
318
  .ds-247420 select:focus-visible {
303
- outline: 2px solid var(--accent-ink);
304
- outline-offset: 2px;
319
+ outline: var(--focus-w) solid var(--focus-color);
320
+ outline-offset: var(--focus-offset);
305
321
  }
306
322
 
307
323
  /* Interactive element focus-visible */
308
324
  .ds-247420[tabindex]:focus-visible {
309
- outline: 2px solid var(--accent-ink);
310
- outline-offset: 2px;
325
+ outline: var(--focus-w) solid var(--focus-color);
326
+ outline-offset: var(--focus-offset);
311
327
  }
312
328
 
313
329
  .ds-247420[data-theme="ink"],
@@ -777,11 +793,15 @@
777
793
  .ds-247420 .app-topbar nav a { flex: 0 0 auto; }
778
794
  .ds-247420 .app-topbar nav a {
779
795
  color: var(--fg-2);
780
- padding: 12px 14px;
781
- min-height: 44px;
796
+ /* Dense desktop chrome (was a 44px pill with 12px 14px pad — marketing-scale
797
+ touch target in the top bar). Matches the .app-side a treatment: ~34px,
798
+ --r-1 rounded rect, tighter padding. The 44px tap target is restored under
799
+ @media(pointer:coarse) (the existing .app-topbar nav a rule further down). */
800
+ padding: var(--space-2) var(--space-2-5);
801
+ min-height: 34px;
782
802
  display: flex;
783
803
  align-items: center;
784
- border-radius: var(--r-pill);
804
+ border-radius: var(--r-1);
785
805
  transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
786
806
  }
787
807
  .ds-247420 .app-topbar nav a:hover { background: var(--bg-2); color: var(--fg); }
@@ -809,8 +829,13 @@
809
829
  .ds-247420 .brand .slash { color: var(--accent-ink); font-weight: 700; margin: 0 3px; }
810
830
 
811
831
  .ds-247420 .app-search {
812
- display: inline-flex; align-items: center; gap: 10px;
813
- padding: 9px 16px; background: var(--bg-2);
832
+ display: inline-flex; align-items: center; gap: var(--space-2-5);
833
+ /* Snap to the single-line control ladder (--field-height == --ctl-md, 34px,
834
+ density-scaled) so the topbar search aligns with sibling topbar controls and
835
+ shrinks under [data-density]. Was raw 9px 16px padding off the ladder — the
836
+ one front-door input the control-height port missed. */
837
+ height: var(--field-height);
838
+ padding: 0 var(--space-3); background: var(--bg-2);
814
839
  border-radius: var(--r-pill);
815
840
  font-size: var(--fs-sm); color: var(--fg-3);
816
841
  max-width: 360px;
@@ -855,13 +880,19 @@
855
880
  }
856
881
  .ds-247420 .app-side a {
857
882
  display: grid; grid-template-columns: 18px 1fr auto;
858
- gap: 10px; align-items: center;
859
- padding: 12px 14px;
860
- min-height: 44px;
861
- border-radius: var(--r-pill);
883
+ gap: var(--space-2-5); align-items: center;
884
+ /* Dense rounded-rect nav row (was a 44px pill with 12px 14px padding — tall
885
+ and consumer-shaped). A --r-1 rounded rect at ~34px reads as compact app
886
+ chrome; the full 44px touch target is restored under pointer:coarse below. */
887
+ padding: var(--space-2) var(--space-2-5);
888
+ min-height: 34px;
889
+ border-radius: var(--r-1);
862
890
  color: var(--fg-2);
863
891
  margin-bottom: 2px;
864
892
  }
893
+ @media (pointer: coarse) {
894
+ .ds-247420 .app-side a { min-height: 44px; padding: var(--space-2-75) var(--space-3); }
895
+ }
865
896
  .ds-247420 .app-side a:hover { background: var(--bg-2); color: var(--fg); }
866
897
  .ds-247420 .app-side a:focus-visible {
867
898
  outline: var(--focus-w) solid var(--focus-color);
@@ -984,10 +1015,16 @@
984
1015
  ============================================================ */
985
1016
  .ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost {
986
1017
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
987
- padding: 8px 14px; min-height: 32px;
1018
+ /* Fixed height + horizontal-only padding: the control height is exact and
1019
+ alignable (flex centres the label vertically), the way webgeist snaps every
1020
+ control to a height ladder. Default is the --ctl-md rung; --btn-sm/--btn-lg
1021
+ retune height + h-padding + font per size. Density scales the ladder. */
1022
+ height: var(--ctl-md); min-height: var(--ctl-md);
1023
+ padding: 0 var(--space-2-75);
988
1024
  font-family: var(--ff-body);
989
1025
  font-weight: 600; font-size: var(--fs-sm);
990
1026
  text-decoration: none;
1027
+ white-space: nowrap;
991
1028
  cursor: pointer;
992
1029
  /* Rounded-rect app chrome, not a marketing-page stadium CTA.
993
1030
  Shape vocabulary: r-1/r-2 = actionable buttons, icon-buttons, and
@@ -1020,6 +1057,33 @@
1020
1057
  outline-offset: var(--focus-offset);
1021
1058
  }
1022
1059
 
1060
+ /* Button size ladder — the size prop on Btn() (sm | md | lg). md is the base
1061
+ rule above; sm/lg retune height (off the --ctl-* ladder), horizontal padding,
1062
+ and font-size so a size swap is one class, never inline padding overrides
1063
+ (the old preview faked sizes with style=). Applies to every variant. */
1064
+ .ds-247420 .btn-sm, .ds-247420 .btn-sm.btn-primary, .ds-247420 .btn-sm.btn-ghost {
1065
+ height: var(--ctl-sm); min-height: var(--ctl-sm);
1066
+ padding: 0 var(--space-2); font-size: var(--fs-tiny); gap: var(--space-1);
1067
+ }
1068
+ .ds-247420 .btn-lg, .ds-247420 .btn-lg.btn-primary, .ds-247420 .btn-lg.btn-ghost {
1069
+ height: var(--ctl-lg); min-height: var(--ctl-lg);
1070
+ padding: 0 var(--space-4); font-size: var(--fs-body); gap: var(--space-2);
1071
+ }
1072
+
1073
+ /* App-mode quiet interactions — the marketing hover-lift (translateY + shadow)
1074
+ and the .row .meta slide read as decorative float on a dense working surface.
1075
+ Under [data-typescale="app"], state changes are background/border-only: crisp,
1076
+ no motion, no elevation. Marketing surfaces (no data-typescale) keep the lift. */
1077
+ .ds-247420[data-typescale="app"] .btn:hover,
1078
+ .ds-247420[data-typescale="app"] .btn-primary:hover,
1079
+ .ds-247420[data-typescale="app"] .btn-ghost:hover { transform: none; box-shadow: none; }
1080
+ .ds-247420[data-typescale="app"] .btn:active,
1081
+ .ds-247420[data-typescale="app"] .btn-primary:active,
1082
+ .ds-247420[data-typescale="app"] .btn-ghost:active { transform: none; }
1083
+ .ds-247420[data-typescale="app"] .panel { transition: box-shadow var(--dur-snap) var(--ease), border-color var(--dur-snap) var(--ease); }
1084
+ .ds-247420[data-typescale="app"] a.row:hover .meta,
1085
+ .ds-247420[data-typescale="app"] .row[role="button"]:hover .meta { transform: none; }
1086
+
1023
1087
  /* ============================================================
1024
1088
  IconButton — square icon-only button
1025
1089
  ============================================================ */
@@ -1057,6 +1121,10 @@
1057
1121
  border-radius: var(--r-pill);
1058
1122
  background: var(--bg-3); color: var(--fg-2);
1059
1123
  }
1124
+ /* Badge size ladder — sm for dense inline counts, lg for prominent markers.
1125
+ Base (above) stays the 18px default. */
1126
+ .ds-247420 .ds-badge.ds-badge--sm { min-width: 14px; height: 14px; padding: 0 var(--space-1); font-size: 10px; }
1127
+ .ds-247420 .ds-badge.ds-badge--lg { min-width: 22px; height: 22px; padding: 0 var(--space-2); font-size: var(--fs-tiny); }
1060
1128
  /* Canonical tone names are tone-success / tone-error / tone-neutral. Every
1061
1129
  other tone name grouped into the same rule below (tone-green/tone-live,
1062
1130
  tone-flame, tone-wip, tone-sun/tone-yellow, tone-ok/tone-miss) is a
@@ -1080,7 +1148,7 @@
1080
1148
  .ds-247420 .ds-badge.tone-orange { background: color-mix(in oklab, var(--flame) 30%, var(--sun) 70%); color: var(--ink); }
1081
1149
 
1082
1150
  .ds-247420 .chip {
1083
- display: inline-flex; align-items: center; gap: 6px;
1151
+ display: inline-flex; align-items: center; gap: var(--space-1-75);
1084
1152
  padding: 3px 10px;
1085
1153
  background: var(--bg-2); color: var(--fg-2);
1086
1154
  font-family: var(--ff-body);
@@ -1088,6 +1156,17 @@
1088
1156
  letter-spacing: var(--tr-caps); text-transform: uppercase;
1089
1157
  border-radius: var(--r-pill);
1090
1158
  }
1159
+ /* Chip size ladder — sm for dense toolbars/table cells, lg for prominent
1160
+ status. tone-* colouring (below) is orthogonal to size. */
1161
+ .ds-247420 .chip.chip--sm { padding: var(--space-half) var(--space-2); font-size: var(--fs-micro); gap: var(--space-1); }
1162
+ .ds-247420 .chip.chip--lg { padding: var(--space-1-75) var(--space-2-75); font-size: var(--fs-xs); }
1163
+ /* Tag variant — a rectangular, sentence-case chip for dense data (table cells,
1164
+ inline labels) where the all-caps pill reads too shouty and space-hungry.
1165
+ Keeps the tone-* palette; drops the caps + pill for a tight --r-0 corner. */
1166
+ .ds-247420 .chip.chip--tag {
1167
+ text-transform: none; letter-spacing: 0; font-weight: 500;
1168
+ border-radius: var(--r-0); padding: var(--space-half) var(--space-2);
1169
+ }
1091
1170
  /* Same canonical/legacy-alias grouping as .ds-badge above. */
1092
1171
  .ds-247420 .chip.tone-green, .ds-247420 .chip.tone-live, .ds-247420 .chip.tone-success, .ds-247420 .chip.tone-ok {
1093
1172
  background: var(--green-tint); color: var(--green-deep);
@@ -1157,6 +1236,17 @@
1157
1236
  }
1158
1237
  .ds-247420 .panel.panel-inline { background: var(--bg-2); padding: var(--space-3) var(--space-3); }
1159
1238
  .ds-247420 .panel.panel-wide { background: transparent; box-shadow: none; border: none; }
1239
+ /* Dense panel — a compact container for app surfaces (inspector sections,
1240
+ sidebars) that want the .panel look without the roomy 16px pad + 24px stack
1241
+ gap. Tighter corner + padding + head, so it sits between .panel and the
1242
+ flush editor .ds-ep-panel. */
1243
+ .ds-247420 .panel.panel--dense {
1244
+ padding: var(--space-2); margin-bottom: var(--space-2-75);
1245
+ border-radius: var(--r-1);
1246
+ }
1247
+ .ds-247420 .panel.panel--dense .panel-head { padding: var(--space-1-5) var(--space-2); }
1248
+ .ds-247420 .panel.panel--dense .panel-body { padding: var(--space-1-5) var(--space-2) var(--space-2); }
1249
+ .ds-247420 .panel.panel--dense .panel-body > * + * { margin-top: var(--space-2); }
1160
1250
  .ds-247420 .panel-head {
1161
1251
  display: flex; align-items: baseline; justify-content: space-between;
1162
1252
  /* Shares the .panel-body 16px side padding so the caps label and the body
@@ -1186,9 +1276,13 @@
1186
1276
  grid-template-columns: minmax(80px, 12ch) minmax(0, 1fr) auto;
1187
1277
  gap: var(--space-3);
1188
1278
  align-items: baseline;
1189
- padding: var(--space-3) var(--space-4);
1279
+ /* App density is the BASE: a list row is quiet working chrome, so it defaults
1280
+ to the compact 12px/16px rhythm (density-scaled) rather than the old
1281
+ 16px/24px marketing padding. .row--lede restores the roomier marketing
1282
+ voice for editorial index pages. */
1283
+ padding: calc(var(--space-2-75) * var(--density)) var(--space-3);
1190
1284
  background: var(--bg);
1191
- border-radius: var(--r-2);
1285
+ border-radius: var(--r-1);
1192
1286
  color: var(--fg);
1193
1287
  position: relative;
1194
1288
  /* Only background + the leading rail animate; padding/size never change on
@@ -1266,8 +1360,14 @@
1266
1360
  .ds-247420 .row.row-nocode { grid-template-columns: minmax(0, 1fr) auto; }
1267
1361
 
1268
1362
  .ds-247420 .row .code { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
1269
- .ds-247420 .row .title { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-lg); line-height: var(--lh-snug); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
1363
+ /* Title defaults to the quiet app voice (fs-sm/500) the 18px/600 marketing
1364
+ voice is now opt-in via .row--lede. */
1365
+ .ds-247420 .row .title { font-family: var(--ff-body); font-weight: 500; font-size: var(--fs-sm); line-height: var(--lh-snug); display: flex; align-items: baseline; gap: var(--space-2-5); flex-wrap: wrap; min-width: 0; }
1270
1366
  .ds-247420 .row .title .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
1367
+ /* Marketing/editorial index row — restores the roomier padding + larger title
1368
+ the default carried before app-scale became the base. */
1369
+ .ds-247420 .row--lede { padding: var(--space-3) var(--space-4); }
1370
+ .ds-247420 .row--lede .title { font-size: var(--fs-lg); font-weight: 600; }
1271
1371
  /* App typescale: list rows are quiet working chrome (the 18px/600 default is a
1272
1372
  marketing-surface voice). One size for ALL app list rows - matches
1273
1373
  .ds-file-row/.ds-session-title at fs-sm/500; values mirror the kit's own
@@ -1506,16 +1606,19 @@
1506
1606
  .ds-247420 table {
1507
1607
  width: 100%; border-collapse: collapse;
1508
1608
  font-family: var(--ff-body); font-size: var(--fs-sm);
1509
- border-radius: var(--r-3); overflow: hidden;
1609
+ /* A data grid, not a card: a tight --r-0 corner (was --r-3/22px, which read
1610
+ as a rounded card). Cells drop to 8px 12px for a dense, scannable row
1611
+ (was 12/14 x 16 => ~43px rows). Density scales the vertical padding. */
1612
+ border-radius: var(--r-0); overflow: hidden;
1510
1613
  }
1511
1614
  .ds-247420 table th {
1512
1615
  text-align: left;
1513
- padding: 12px 16px;
1616
+ padding: calc(var(--space-2) * var(--density)) var(--space-2-75);
1514
1617
  font-size: var(--fs-tiny); font-weight: 600;
1515
1618
  color: var(--fg-3); text-transform: uppercase; letter-spacing: var(--tr-caps);
1516
1619
  background: var(--bg-2);
1517
1620
  }
1518
- .ds-247420 table td { padding: 14px 16px; border-top: 1px solid var(--rule); }
1621
+ .ds-247420 table td { padding: calc(var(--space-2) * var(--density)) var(--space-2-75); border-top: 1px solid var(--rule); }
1519
1622
  .ds-247420 table tr.clickable { cursor: pointer; }
1520
1623
  .ds-247420 table tr.clickable:hover td { background: var(--bg-2); }
1521
1624
  .ds-247420 table tr.clickable:focus-visible {
@@ -1583,13 +1686,16 @@
1583
1686
  gap: var(--space-2);
1584
1687
  }
1585
1688
  .ds-247420 .kpi-card {
1586
- padding: var(--space-5);
1689
+ /* Was --space-5 (32px) pad + --r-3 (22px) — four cards ate a full fold. A
1690
+ 16px pad on a --r-1 corner keeps them prominent but dense; the number drops
1691
+ from a 48px marketing display to a 32px app-scale figure. */
1692
+ padding: var(--space-3);
1587
1693
  background: var(--bg-2);
1588
- border-radius: var(--r-3);
1694
+ border-radius: var(--r-1);
1589
1695
  }
1590
1696
  .ds-247420 .kpi-card .num {
1591
1697
  font-family: var(--ff-body); font-weight: 600;
1592
- font-size: clamp(30px, 3.6cqi, 48px); line-height: 1;
1698
+ font-size: clamp(22px, 3cqi, 32px); line-height: 1;
1593
1699
  letter-spacing: var(--tr-tight);
1594
1700
  }
1595
1701
  .ds-247420 .kpi-card .lbl {
@@ -1621,7 +1727,9 @@
1621
1727
  }
1622
1728
  .ds-247420 .ds-barchart-label { font-size: var(--fs-sm); color: var(--fg-2); }
1623
1729
  .ds-247420 .ds-barchart-track {
1624
- height: var(--space-2); border-radius: var(--r-pill);
1730
+ /* 6px unifies with the system's other bar tracks (.ds-upload-bar,
1731
+ .ds-bar-bg); was --space-2 (8px), the lone thicker slab in the bar family. */
1732
+ height: var(--space-1-75); border-radius: var(--r-pill);
1625
1733
  background: var(--bg-3); overflow: hidden;
1626
1734
  }
1627
1735
  .ds-247420 .ds-barchart-fill {
@@ -1638,11 +1746,14 @@
1638
1746
  Empty state
1639
1747
  ============================================================ */
1640
1748
  .ds-247420 .empty {
1641
- padding: var(--space-8);
1749
+ /* Was --space-8 (96px) — an empty list spent 192px of vertical space on
1750
+ nothing. --space-6 (48px) still centres a message with air, without the
1751
+ empty state dominating the fold. Mobile drops it further (below). */
1752
+ padding: var(--space-6);
1642
1753
  text-align: center;
1643
1754
  color: var(--fg-3);
1644
1755
  background: var(--bg-2);
1645
- border-radius: var(--r-3);
1756
+ border-radius: var(--r-1);
1646
1757
  font-size: var(--fs-sm);
1647
1758
  }
1648
1759
 
@@ -2655,6 +2766,54 @@
2655
2766
  .ds-247420 .ds-preview-meta { display: none; }
2656
2767
  }
2657
2768
 
2769
+ /* ============================================================
2770
+ Catalog / demo shell — a shared, compact framing for the preview/*.html
2771
+ component galleries, so each preview stops hand-rolling its own \3c style>
2772
+ (body padding, section margins, demo boxes). Mirrors webgeist's dense
2773
+ catalog: a 240px sticky sidebar + capped main + a hairline-bordered,
2774
+ flex-wrapping .ds-demo cell that packs variants inline and reflows.
2775
+ ============================================================ */
2776
+ .ds-247420 .ds-catalog { display: flex; min-height: 100vh; gap: 0; }
2777
+ .ds-247420 .ds-catalog-side {
2778
+ width: 240px; flex-shrink: 0;
2779
+ border-right: var(--bw-hair) solid var(--rule);
2780
+ padding: var(--space-3);
2781
+ position: sticky; top: 0; height: 100vh; overflow-y: auto;
2782
+ }
2783
+ .ds-247420 .ds-catalog-side h1 { font-size: var(--fs-lg); margin: 0 0 var(--space-1); }
2784
+ .ds-247420 .ds-catalog-side .subtitle { font-size: var(--fs-micro); color: var(--fg-3); margin: 0 0 var(--space-4); }
2785
+ .ds-247420 .ds-catalog-side nav h4 {
2786
+ font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--tr-label);
2787
+ color: var(--fg-3); margin: var(--space-3) 0 var(--space-1);
2788
+ }
2789
+ .ds-247420 .ds-catalog-side nav a {
2790
+ display: block; padding: var(--space-half) 0; font-size: var(--fs-tiny);
2791
+ color: var(--fg-2); text-decoration: none;
2792
+ }
2793
+ .ds-247420 .ds-catalog-side nav a:hover { color: var(--accent-ink); }
2794
+ .ds-247420 .ds-catalog-main { flex: 1; padding: var(--space-5); max-width: var(--measure-wide); min-width: 0; }
2795
+ .ds-247420 .ds-catalog-section { margin-bottom: var(--space-5); padding-top: var(--space-3); border-top: var(--bw-hair) solid var(--rule); }
2796
+ .ds-247420 .ds-catalog-section > h2 { font-size: var(--fs-h3-app); margin: 0 0 var(--space-3); }
2797
+
2798
+ /* The gallery cell: a hairline-bordered, flex-wrapping bin that packs a
2799
+ component's variants inline and reflows — the signature "showcase" frame. */
2800
+ .ds-247420 .ds-demo {
2801
+ border: var(--bw-hair) solid var(--rule);
2802
+ border-radius: var(--r-1);
2803
+ padding: var(--space-3);
2804
+ display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
2805
+ background: var(--bg);
2806
+ }
2807
+ .ds-247420 .ds-demo + .ds-demo { margin-top: var(--space-2-75); }
2808
+ .ds-247420 .ds-demo-label { font-size: var(--fs-xs); font-weight: 500; margin: 0 0 var(--space-1); }
2809
+ .ds-247420 .ds-demo-desc { font-size: var(--fs-tiny); color: var(--fg-3); margin: 0 0 var(--space-2); }
2810
+
2811
+ @media (max-width: 768px) {
2812
+ .ds-247420 .ds-catalog { flex-direction: column; }
2813
+ .ds-247420 .ds-catalog-side { width: 100%; height: auto; position: static; border-right: 0; border-bottom: var(--bw-hair) solid var(--rule); }
2814
+ .ds-247420 .ds-catalog-main { padding: var(--space-3); }
2815
+ }
2816
+
2658
2817
  /* -- File browser UX affordances ---------------------------- */
2659
2818
  /* Toolbar filter input — compact search box. */
2660
2819
  .ds-247420 .ds-filter-input {
@@ -3514,19 +3673,61 @@
3514
3673
  Enhanced Form Inputs
3515
3674
  -------------------------------------------------------------- */
3516
3675
 
3517
- .ds-247420 input[type="text"],
3518
- .ds-247420 input[type="email"],
3519
- .ds-247420 input[type="password"],
3520
- .ds-247420 input[type="number"],
3521
- .ds-247420 input[type="search"],
3522
- .ds-247420 input[type="url"],
3523
- .ds-247420 input[type="tel"],
3524
- .ds-247420 textarea,
3525
- .ds-247420 select {
3676
+ /* Base chrome for any BARE native control (outside .ds-field/.row-form/.input):
3677
+ the same editorial tonal-fill + printed-baseline-rule as .ds-field, so a raw
3678
+ <input> is never a browser-default white box in dark mode. The guards are
3679
+ wrapped in :where() so they add ZERO specificity — the whole selector stays
3680
+ at (0,1,1), exactly like `.ds-field input`, so the later .ds-field / .ds-field--sm
3681
+ / .row-form descendant rules win by source order instead of being out-specified
3682
+ (a bare :not(.input) counts as a class and would beat every .ds-field rule,
3683
+ which clobbered the size variants). */
3684
+ .ds-247420 input[type="text"]:where(:not(.input):not(.ds-search-input)),
3685
+ .ds-247420 input[type="email"]:where(:not(.input):not(.ds-search-input)),
3686
+ .ds-247420 input[type="password"]:where(:not(.input):not(.ds-search-input)),
3687
+ .ds-247420 input[type="number"]:where(:not(.input):not(.ds-search-input)),
3688
+ .ds-247420 input[type="search"]:where(:not(.input):not(.ds-search-input)),
3689
+ .ds-247420 input[type="url"]:where(:not(.input):not(.ds-search-input)),
3690
+ .ds-247420 input[type="tel"]:where(:not(.input):not(.ds-search-input)),
3691
+ .ds-247420 textarea:where(:not(.input)),
3692
+ .ds-247420 select:where(:not(.ds-select)) {
3693
+ font: inherit; color: var(--fg);
3694
+ background: var(--bg-2);
3695
+ border: 0;
3696
+ box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--rule),
3697
+ inset 0 calc(-1 * var(--bw-rule)) 0 var(--rule-strong);
3698
+ border-radius: var(--r-1);
3699
+ padding: 0 var(--space-3);
3526
3700
  transition: background var(--dur-snap) var(--ease),
3527
3701
  border-color var(--dur-snap) var(--ease),
3528
3702
  box-shadow var(--dur-snap) var(--ease);
3529
3703
  }
3704
+ /* Single-line bare controls snap to the field height; textarea keeps auto
3705
+ height with symmetric padding (its content decides the box). */
3706
+ .ds-247420 input[type="text"]:where(:not(.input):not(.ds-search-input)),
3707
+ .ds-247420 input[type="email"]:where(:not(.input):not(.ds-search-input)),
3708
+ .ds-247420 input[type="password"]:where(:not(.input):not(.ds-search-input)),
3709
+ .ds-247420 input[type="number"]:where(:not(.input):not(.ds-search-input)),
3710
+ .ds-247420 input[type="search"]:where(:not(.input):not(.ds-search-input)),
3711
+ .ds-247420 input[type="url"]:where(:not(.input):not(.ds-search-input)),
3712
+ .ds-247420 input[type="tel"]:where(:not(.input):not(.ds-search-input)),
3713
+ .ds-247420 select:where(:not(.ds-select)) {
3714
+ height: var(--field-height);
3715
+ }
3716
+ .ds-247420 textarea:where(:not(.input)) { padding: var(--space-2) var(--space-3); min-height: calc(4 * 1.5em); }
3717
+ .ds-247420 input[type="text"]:where(:not(.input):not(.ds-search-input)):focus-visible,
3718
+ .ds-247420 input[type="email"]:where(:not(.input):not(.ds-search-input)):focus-visible,
3719
+ .ds-247420 input[type="password"]:where(:not(.input):not(.ds-search-input)):focus-visible,
3720
+ .ds-247420 input[type="number"]:where(:not(.input):not(.ds-search-input)):focus-visible,
3721
+ .ds-247420 input[type="search"]:where(:not(.input):not(.ds-search-input)):focus-visible,
3722
+ .ds-247420 input[type="url"]:where(:not(.input):not(.ds-search-input)):focus-visible,
3723
+ .ds-247420 input[type="tel"]:where(:not(.input):not(.ds-search-input)):focus-visible,
3724
+ .ds-247420 textarea:where(:not(.input)):focus-visible,
3725
+ .ds-247420 select:where(:not(.ds-select)):focus-visible {
3726
+ outline: none;
3727
+ background: var(--bg);
3728
+ box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--rule),
3729
+ inset 0 calc(-1 * var(--bw-chunk)) 0 var(--accent);
3730
+ }
3530
3731
 
3531
3732
  .ds-247420 input[type="text"]::placeholder,
3532
3733
  .ds-247420 input[type="email"]::placeholder,
@@ -3659,16 +3860,57 @@
3659
3860
  the electric lead on focus, instead of a uniform hairline box. */
3660
3861
  box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--rule),
3661
3862
  inset 0 calc(-1 * var(--bw-rule)) 0 var(--rule-strong);
3662
- border-radius: var(--r-2, 10px);
3663
- padding: 10px 14px;
3863
+ /* Tighter corner than the old --r-2 (14px): a dense pro control, not a soft
3864
+ consumer box. Single-line controls snap to --field-height with h-only
3865
+ padding so they align pixel-exact with buttons on the same --ctl-md rung. */
3866
+ border-radius: var(--r-1);
3867
+ height: var(--field-height);
3868
+ padding: 0 var(--space-3);
3664
3869
  transition: box-shadow var(--dur-snap) var(--ease), background var(--dur-snap) var(--ease);
3665
3870
  }
3666
- .ds-247420 .ds-field textarea { min-height: calc(4 * 1.5em); resize: vertical; }
3871
+ /* textarea is multi-line: height is auto (min-height instead), keep symmetric
3872
+ vertical padding so text doesn't sit flush to the top edge. */
3873
+ .ds-247420 .ds-field textarea { height: auto; min-height: calc(4 * 1.5em); padding: var(--space-2) var(--space-3); resize: vertical; }
3874
+
3875
+ /* Field size ladder (size prop on TextField/Select/SearchInput). md == base.
3876
+ sm/lg retune height + h-padding + font off the --ctl-* ladder, matching the
3877
+ button ladder so a form of mixed controls stays on one rhythm. */
3878
+ .ds-247420 .ds-field--sm input, .ds-247420 .ds-field--sm .ds-select, .ds-247420 .ds-field--sm .ds-search-input {
3879
+ height: var(--ctl-sm); padding: 0 var(--space-2-5); font-size: var(--fs-tiny);
3880
+ }
3881
+ .ds-247420 .ds-field--sm textarea { height: auto; padding: var(--space-1-75) var(--space-2-5); font-size: var(--fs-tiny); }
3882
+ .ds-247420 .ds-field--lg input, .ds-247420 .ds-field--lg .ds-select, .ds-247420 .ds-field--lg .ds-search-input {
3883
+ height: var(--ctl-lg); padding: 0 var(--space-4); font-size: var(--fs-body);
3884
+ }
3885
+ .ds-247420 .ds-field--lg textarea { height: auto; padding: var(--space-2-5) var(--space-4); font-size: var(--fs-body); }
3667
3886
  .ds-247420 .ds-search-input::placeholder { color: var(--fg-3); }
3668
- /* Only present when SearchInput is passed resultCount - transparent to any
3669
- flex/grid layout the bare input previously sat in directly. */
3887
+ /* Only present when SearchInput is passed resultCount or has a value (clear
3888
+ button) - transparent to any flex/grid layout the bare input previously
3889
+ sat in directly. */
3670
3890
  .ds-247420 .ds-search-input-wrap { display: contents; }
3671
3891
 
3892
+ /* Visible clear (X) button for SearchInput - mirrors .ds-alert-dismiss's
3893
+ ghost-icon treatment but sized to the kit's 44px touch-target floor
3894
+ (app-shell.css already establishes this convention for .ds-file-check /
3895
+ .ds-density-btn / .ds-upload-act etc). Positioned by the consumer's own
3896
+ flex/grid context (ds-search-input-wrap is display:contents), so it simply
3897
+ sits after the input in DOM order. */
3898
+ .ds-247420 .ds-search-clear {
3899
+ display: inline-flex;
3900
+ align-items: center; justify-content: center;
3901
+ min-width: 44px; min-height: 44px;
3902
+ flex-shrink: 0;
3903
+ cursor: pointer;
3904
+ color: var(--fg-3);
3905
+ background: transparent;
3906
+ border: 0;
3907
+ padding: 0;
3908
+ border-radius: var(--r-1);
3909
+ transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
3910
+ }
3911
+ .ds-247420 .ds-search-clear:hover { background: var(--bg-2); color: var(--fg); }
3912
+ .ds-247420 .ds-search-clear:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
3913
+
3672
3914
  .ds-247420 .ds-field input:focus-visible,
3673
3915
  .ds-247420 .ds-field textarea:focus-visible,
3674
3916
  .ds-247420 .ds-field .ds-select:focus-visible,
@@ -5361,7 +5603,7 @@
5361
5603
  background: color-mix(in oklab, var(--fg) 8%, transparent);
5362
5604
  }
5363
5605
  .ds-247420 .cm-cat-add:focus-visible {
5364
- outline: 2px solid var(--accent-ink);
5606
+ outline: var(--focus-w) solid var(--focus-color);
5365
5607
  outline-offset: 2px;
5366
5608
  }
5367
5609
 
@@ -5544,7 +5786,7 @@
5544
5786
  background: color-mix(in oklab, var(--fg) 10%, transparent);
5545
5787
  }
5546
5788
  .ds-247420 .cm-ch-action-btn:focus-visible {
5547
- outline: 2px solid var(--accent-ink);
5789
+ outline: var(--focus-w) solid var(--focus-color);
5548
5790
  outline-offset: 2px;
5549
5791
  }
5550
5792
 
@@ -6127,44 +6369,44 @@
6127
6369
  .ds-247420 .cm-server-icon:focus-visible,
6128
6370
  .ds-247420 .cm-server-back:focus-visible,
6129
6371
  .ds-247420 .cm-server-add:focus-visible {
6130
- outline: 2px solid var(--accent-ink);
6372
+ outline: var(--focus-w) solid var(--focus-color);
6131
6373
  outline-offset: 2px;
6132
6374
  border-radius: var(--r-2);
6133
6375
  }
6134
6376
 
6135
6377
  .ds-247420 .cm-channel-item:focus-visible {
6136
- outline: 2px solid var(--accent-ink);
6378
+ outline: var(--focus-w) solid var(--focus-color);
6137
6379
  outline-offset: -2px;
6138
6380
  border-radius: var(--r-1);
6139
6381
  }
6140
6382
 
6141
6383
  .ds-247420 .cm-server-header:focus-visible,
6142
6384
  .ds-247420 .cm-category-header:focus-visible {
6143
- outline: 2px solid var(--accent-ink);
6385
+ outline: var(--focus-w) solid var(--focus-color);
6144
6386
  outline-offset: -2px;
6145
6387
  }
6146
6388
 
6147
6389
  .ds-247420 .cm-member-item:focus-visible {
6148
- outline: 2px solid var(--accent-ink);
6390
+ outline: var(--focus-w) solid var(--focus-color);
6149
6391
  outline-offset: -2px;
6150
6392
  border-radius: var(--r-1);
6151
6393
  }
6152
6394
 
6153
6395
  .ds-247420 .cm-vs-btn:focus-visible,
6154
6396
  .ds-247420 .cm-user-btn:focus-visible {
6155
- outline: 2px solid var(--accent-ink);
6397
+ outline: var(--focus-w) solid var(--focus-color);
6156
6398
  outline-offset: 2px;
6157
6399
  border-radius: var(--r-1);
6158
6400
  }
6159
6401
 
6160
6402
  /* ThreadPanel / Forum / Page interactive elements */
6161
6403
  .ds-247420 .cm-tp-item:focus-visible,
6162
- .ds-247420 .cm-forum-item:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: -2px; border-radius: var(--r-1); }
6404
+ .ds-247420 .cm-forum-item:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: -2px; border-radius: var(--r-1); }
6163
6405
  .ds-247420 .cm-tp-new:focus-visible,
6164
6406
  .ds-247420 .cm-tp-close:focus-visible,
6165
6407
  .ds-247420 .cm-forum-new:focus-visible,
6166
6408
  .ds-247420 .cm-forum-sort:focus-visible,
6167
- .ds-247420 .cm-page-edit:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; border-radius: var(--r-1); }
6409
+ .ds-247420 .cm-page-edit:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 2px; border-radius: var(--r-1); }
6168
6410
  .ds-247420 .cm-forum-search:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent-ink); }
6169
6411
 
6170
6412
  /* ---------- mobile header ---------- */
@@ -6193,7 +6435,7 @@
6193
6435
  border-radius: var(--r-1);
6194
6436
  }
6195
6437
  .ds-247420 .cm-mh-btn:hover { background: var(--panel-3); }
6196
- .ds-247420 .cm-mh-btn:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
6438
+ .ds-247420 .cm-mh-btn:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 2px; }
6197
6439
  .ds-247420 .cm-mh-title {
6198
6440
  flex: 1 1 auto;
6199
6441
  min-width: 0;
@@ -6238,7 +6480,7 @@
6238
6480
  border-radius: var(--r-1);
6239
6481
  }
6240
6482
  .ds-247420 .cm-rb-cancel:hover { background: var(--panel-3); color: var(--fg); }
6241
- .ds-247420 .cm-rb-cancel:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 1px; }
6483
+ .ds-247420 .cm-rb-cancel:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 1px; }
6242
6484
 
6243
6485
  /* ---------- banner ---------- */
6244
6486
  .ds-247420 .cm-banner {
@@ -7893,12 +8135,36 @@
7893
8135
  }
7894
8136
 
7895
8137
  /* Tabs */
7896
- .ds-247420 .ds-ep-tabs { display: flex; flex-direction: column; min-height: 0; height: 100%; }
8138
+ .ds-247420 .ds-ep-tabs { display: flex; flex-direction: column; min-height: 0; height: 100%; position: relative; }
7897
8139
  .ds-247420 .ds-ep-tabs-head {
7898
8140
  display: flex; flex-shrink: 0; flex-wrap: nowrap;
7899
8141
  overflow-x: auto; scroll-behavior: smooth;
7900
8142
  background: var(--panel-1);
7901
8143
  border-bottom: 1px solid var(--rule);
8144
+ position: relative;
8145
+ }
8146
+ /* Sliding indicator — a single 2px bar under the active tab that animates its
8147
+ left/width between tabs (webgeist's "expensive" underline-slide), instead of
8148
+ each tab toggling its own static border. A REAL child element positioned by
8149
+ the Tabs ref (inline left/width/top). It lives as a child of the OUTER
8150
+ .ds-ep-tabs column (position:relative), NOT the .ds-ep-tabs-head, because an
8151
+ absolutely-positioned child of a horizontal flex container mis-sizes to 0 in
8152
+ Chromium; the outer column is a vertical flex, which sizes it correctly.
8153
+ The ref sets top to the head's height so it sits on the head's bottom edge.
8154
+ .has-slider gates the static per-tab border off (below). */
8155
+ .ds-247420 .ds-ep-tab-indicator {
8156
+ /* Sized by left+right insets (set inline by positionSlider), NOT width — an
8157
+ abspos element's `width` computes to 0 in some flex-sibling layouts in
8158
+ Chromium, whereas insets size reliably. left+right at the same value
8159
+ collapse it to 0 until positioned (no-JS: invisible). */
8160
+ position: absolute; top: 0; left: 0; right: 100%; height: 2px;
8161
+ background: var(--accent);
8162
+ transition: left var(--dur-base, 160ms) var(--ease, ease),
8163
+ right var(--dur-base, 160ms) var(--ease, ease);
8164
+ pointer-events: none;
8165
+ }
8166
+ @media (prefers-reduced-motion: reduce) {
8167
+ .ds-247420 .ds-ep-tab-indicator { transition: none; }
7902
8168
  }
7903
8169
  .ds-247420 .ds-ep-tab {
7904
8170
  flex: 1; appearance: none; background: transparent; border: 0;
@@ -7913,6 +8179,9 @@
7913
8179
  color: var(--accent);
7914
8180
  border-bottom-color: var(--accent);
7915
8181
  }
8182
+ /* When the JS slider is active, the active tab's own static border is
8183
+ redundant (the sliding bar draws it) — hide it so they don't double up. */
8184
+ .ds-247420 .ds-ep-tabs-head.has-slider .ds-ep-tab.active { border-bottom-color: transparent; }
7916
8185
  /* Flex column so a full-height docked child (e.g. an inspector panel) fills
7917
8186
  the tab body instead of collapsing under a block container. */
7918
8187
  .ds-247420 .ds-ep-tabs-body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
@@ -8118,7 +8387,8 @@
8118
8387
  .ds-247420 .ds-ep-actionbar > * { flex: 1 1 0; }
8119
8388
  .ds-247420 .ds-ep-actionbar button {
8120
8389
  width: 100%;
8121
- min-height: 28px; height: 28px; padding: 0 10px;
8390
+ /* Snapped to --ctl-sm (was a lone 28px literal that happened to match). */
8391
+ min-height: var(--ctl-sm); height: var(--ctl-sm); padding: 0 var(--space-2-5);
8122
8392
  border-radius: var(--r-1, 4px);
8123
8393
  font: var(--fs-tiny, 12px)/1 var(--ff-mono, monospace);
8124
8394
  }
@@ -8488,15 +8758,19 @@
8488
8758
  display: flex; flex-direction: column;
8489
8759
  outline: none;
8490
8760
  }
8491
- .ds-247420 .ds-ep-dialog-head { padding: 14px 16px 6px; border-bottom: 1px solid var(--rule); }
8492
- .ds-247420 .ds-ep-dialog-title { margin: 0; font-size: 16px; font-weight: 600; }
8493
- .ds-247420 .ds-ep-dialog-body { padding: 14px 16px; }
8761
+ /* Padding tokenized to the --space-* scale (was raw 14/16/10/6) and shaved to
8762
+ app density — a dialog is working chrome, not a marketing card. */
8763
+ .ds-247420 .ds-ep-dialog-head { padding: var(--space-2-75) var(--space-3) var(--space-1-5); border-bottom: 1px solid var(--rule); }
8764
+ .ds-247420 .ds-ep-dialog-title { margin: 0; font-size: var(--fs-body); font-weight: 600; }
8765
+ .ds-247420 .ds-ep-dialog-body { padding: var(--space-2-75) var(--space-3); }
8494
8766
  .ds-247420 .ds-ep-dialog-actions {
8495
- display: flex; gap: 8px; justify-content: flex-end;
8496
- padding: 10px 14px; border-top: 1px solid var(--rule);
8767
+ display: flex; gap: var(--space-2); justify-content: flex-end;
8768
+ padding: var(--space-2) var(--space-2-75); border-top: 1px solid var(--rule);
8497
8769
  }
8498
8770
  .ds-247420 .ds-ep-dialog-btn {
8499
- padding: 8px 14px;
8771
+ /* Snapped to the --ctl-sm rung + tokenized padding (was 8px 14px). */
8772
+ min-height: var(--ctl-sm); padding: 0 var(--space-3);
8773
+ display: inline-flex; align-items: center; justify-content: center;
8500
8774
  border: 1px solid var(--rule);
8501
8775
  border-radius: var(--r-1, 6px);
8502
8776
  background: var(--panel-2, transparent);
@@ -8530,7 +8804,7 @@
8530
8804
  border: 1px solid var(--rule);
8531
8805
  border-left: 3px solid var(--accent);
8532
8806
  border-radius: var(--r-1, 6px);
8533
- padding: 10px 14px;
8807
+ padding: var(--space-2) var(--space-2-75);
8534
8808
  box-shadow: var(--shadow-3);
8535
8809
  min-width: 220px; max-width: 360px;
8536
8810
  opacity: 1;
@@ -8623,7 +8897,10 @@
8623
8897
  .ds-247420 .ds-radio-row,
8624
8898
  .ds-247420 .ds-toggle-row {
8625
8899
  display: inline-flex; align-items: center; gap: var(--space-2, 8px);
8626
- min-height: 44px;
8900
+ /* Desktop density: ~30px rows, not the 44px touch target (which stacked a
8901
+ lot of dead vertical space in inspector/settings forms). The full 44px
8902
+ target is restored under pointer:coarse below. */
8903
+ min-height: 30px;
8627
8904
  padding: var(--space-1, 4px) var(--space-2, 8px);
8628
8905
  cursor: pointer;
8629
8906
  color: var(--fg);
@@ -8632,6 +8909,10 @@
8632
8909
  .ds-247420 .ds-check-row:has(input:disabled),
8633
8910
  .ds-247420 .ds-radio-row:has(input:disabled),
8634
8911
  .ds-247420 .ds-toggle-row:has(button:disabled) { opacity: 0.5; cursor: not-allowed; }
8912
+ /* Touch devices: restore the 44px minimum tap target. */
8913
+ @media (pointer: coarse) {
8914
+ .ds-247420 .ds-check-row, .ds-247420 .ds-radio-row, .ds-247420 .ds-toggle-row { min-height: 44px; }
8915
+ }
8635
8916
 
8636
8917
  .ds-247420 .ds-check, .ds-247420 .ds-radio {
8637
8918
  width: 18px; height: 18px;
@@ -8743,8 +9024,8 @@
8743
9024
  color: var(--panel-text, var(--fg-text));
8744
9025
  border: 1px solid var(--rule);
8745
9026
  border-radius: var(--r-1, 6px);
8746
- padding: 6px 10px;
8747
- font-size: 12px;
9027
+ padding: var(--space-1-75) var(--space-2-5);
9028
+ font-size: var(--fs-micro);
8748
9029
  line-height: 1.4;
8749
9030
  max-width: 280px;
8750
9031
  box-shadow: var(--shadow-3);
@@ -8787,8 +9068,12 @@
8787
9068
  .ds-247420 .ds-dropdown-list { display: flex; flex-direction: column; }
8788
9069
  .ds-247420 .ds-dropdown-item {
8789
9070
  display: flex; align-items: center; gap: 8px;
8790
- min-height: 44px;
8791
- padding: 8px 12px;
9071
+ /* Dense desktop row (was an unconditional 44px touch target — a menu of
9072
+ these was very tall on desktop). ~30px here; the 44px tap target is
9073
+ restored under @media(pointer:coarse) below, matching the .ds-check-row
9074
+ treatment. */
9075
+ min-height: 30px;
9076
+ padding: var(--space-1-5) var(--space-2-75);
8792
9077
  background: transparent; border: 0;
8793
9078
  color: inherit; font: inherit; text-align: left;
8794
9079
  border-radius: var(--r-1, 4px);
@@ -8799,6 +9084,9 @@
8799
9084
  background: var(--panel-2, var(--rule));
8800
9085
  outline: none;
8801
9086
  }
9087
+ @media (pointer: coarse) {
9088
+ .ds-247420 .ds-dropdown-item { min-height: 44px; padding: var(--space-2) var(--space-3); }
9089
+ }
8802
9090
  .ds-247420 .ds-dropdown-item:focus-visible {
8803
9091
  outline: var(--focus-w) solid var(--focus-color);
8804
9092
  outline-offset: calc(var(--focus-offset) * -1);
@@ -8818,9 +9106,12 @@
8818
9106
  color: inherit; font: inherit;
8819
9107
  border: 1px solid var(--rule);
8820
9108
  border-radius: var(--r-1, 6px);
8821
- padding: 6px 12px;
9109
+ padding: 0 var(--space-2-75);
8822
9110
  cursor: pointer;
8823
- min-height: 32px;
9111
+ /* Snapped to the --ctl-sm rung so this small control shares the height
9112
+ ladder with buttons/fields instead of a lone 32px literal. */
9113
+ min-height: var(--ctl-sm); height: var(--ctl-sm);
9114
+ display: inline-flex; align-items: center;
8824
9115
  }
8825
9116
  @media (pointer: coarse) {
8826
9117
  .ds-247420 .ds-dropdown-trigger { min-height: 44px; }