anentrypoint-design 0.0.237 → 0.0.239

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/247420.css CHANGED
@@ -7,17 +7,18 @@
7
7
  Source-of-truth tokens. Component sheet lives in app-shell.css.
8
8
  ============================================================ */
9
9
 
10
- @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:ital,wght@0,400;0,500;0,600;0,700;1,400;1,700&display=swap');
10
+ @import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200..800&family=Hanken+Grotesk:ital,wght@0,300;0,400;0,500;0,600;0,700;1,400&family=JetBrains+Mono:ital,wght@0,400;0,500;0,600;0,700;1,400;1,700&display=swap');
11
11
 
12
- /* Metric-matched fallback for the display face. While Space Grotesk loads,
13
- text falls back to Arial with size-adjust tuned to its cap-height so the
14
- oversized hero does not reflow on swap. Referenced first in --ff-display via
15
- the 'Space Grotesk' family; this only kicks in for the fallback glyphs. */
12
+ /* Metric-matched fallback for the display face. While Bricolage Grotesque
13
+ loads, text falls back to Arial with size-adjust tuned to its cap-height so
14
+ the oversized hero does not reflow on swap. Referenced first in --ff-display
15
+ via the 'Bricolage Grotesque' family; this only kicks in for the fallback
16
+ glyphs. */
16
17
  @font-face {
17
- font-family: 'Space Grotesk Fallback';
18
+ font-family: 'Bricolage Grotesque Fallback';
18
19
  src: local('Arial');
19
- size-adjust: 96%;
20
- ascent-override: 95%;
20
+ size-adjust: 99%;
21
+ ascent-override: 94%;
21
22
  descent-override: 24%;
22
23
  }
23
24
 
@@ -131,13 +132,14 @@
131
132
  --panel-accent-2: var(--accent-bright, var(--accent));
132
133
  --panel-shadow: 0 1px 0 color-mix(in oklab, var(--fg) 6%, transparent), 0 4px 14px color-mix(in oklab, var(--fg) 8%, transparent);
133
134
 
134
- /* Type — Space Grotesk carries display/headings (editorial grotesk with real
135
- character), Inter carries body and UI, JetBrains carries code. The narrow
136
- alias tracks the display face. size-adjust on the fallback keeps the
137
- oversized hero from shifting while Space Grotesk loads. */
138
- --ff-display: 'Space Grotesk', 'Space Grotesk Fallback', 'Inter', system-ui, sans-serif;
139
- --ff-narrow: 'Space Grotesk', 'Space Grotesk Fallback', 'Inter', system-ui, sans-serif;
140
- --ff-body: 'Inter', system-ui, sans-serif;
135
+ /* Type — Bricolage Grotesque carries display/headings (variable editorial
136
+ grotesque with real character), Hanken Grotesk carries body and UI,
137
+ JetBrains carries code. The narrow alias tracks the display face.
138
+ size-adjust on the fallback keeps the oversized hero from shifting while
139
+ Bricolage Grotesque loads. */
140
+ --ff-display: 'Bricolage Grotesque', 'Bricolage Grotesque Fallback', 'Hanken Grotesk', system-ui, sans-serif;
141
+ --ff-narrow: 'Bricolage Grotesque', 'Bricolage Grotesque Fallback', 'Hanken Grotesk', system-ui, sans-serif;
142
+ --ff-body: 'Hanken Grotesk', system-ui, sans-serif;
141
143
  --ff-mono: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
142
144
 
143
145
  --fs-micro: 12px;
@@ -500,9 +502,10 @@
500
502
  /* app-shell.css */
501
503
  /* ============================================================
502
504
  247420 design system — component sheet
503
- "Acid Editorial": Space Grotesk display + Inter body + JetBrains code.
504
- Confident hierarchy, asymmetric grid tension, print texture over glow,
505
- one electric lead accent. Indicator rails over hairlines.
505
+ "Acid Editorial": Bricolage Grotesque display + Hanken Grotesk body +
506
+ JetBrains code. Confident hierarchy, asymmetric grid tension, print
507
+ texture over glow, one electric lead accent. Indicator rails over
508
+ hairlines.
506
509
  ============================================================ */
507
510
 
508
511
  /* ============================================================
@@ -871,17 +874,31 @@
871
874
  .ds-247420 .app-main > .chat,
872
875
  .ds-247420 .app-main > .chat-area,
873
876
  .ds-247420 .app-main > .ds-file-stage,
877
+ .ds-247420 .app-main > .ds-files-stack,
874
878
  .ds-247420 .app-main > .grow { flex: 1 1 auto; min-height: 0; }
875
879
  .ds-247420 .app-main.narrow { max-width: var(--measure-narrow); margin: 0 auto; }
876
880
 
877
881
  @media (min-width: 1400px) {
878
- .ds-247420 .app { max-width: 1400px; margin-left: auto; margin-right: auto; }
882
+ /* Fluid ceiling, not a hard stop: scales from 1400px up to 1920px across the
883
+ 1400-2200px viewport band (matches .ws-shell's 1920px ultrawide cap below)
884
+ instead of freezing at 1400px and leaving >1000px dead margin on a 2560px+
885
+ display. Row/prose measure caps (--measure-wide etc.) still own line-length
886
+ readability, so widening the shell itself does not create unreadable rows. */
887
+ .ds-247420 .app { max-width: clamp(1400px, 92vw, 1920px); margin-left: auto; margin-right: auto; }
879
888
  .ds-247420 .app-main .chat,
880
889
  .ds-247420 .app-main > .chat-area,
881
890
  .ds-247420 .app-main > .main-content { max-width: none; margin: 0; width: 100%; }
882
891
  /* Status bar inherits the .app max-width cap above and stretches edge-to-edge
883
892
  within it; no separate width constraint (which previously narrowed it). */
884
893
  .ds-247420 .app-status { width: 100%; }
894
+ /* Cap row text measure inside the wide capped main (ultrawide readability). */
895
+ .ds-247420 .row .title, .ds-247420 .row .sub { max-width: var(--measure-wide); }
896
+ }
897
+ /* Beyond 1920px the shell itself stops growing (matches .ws-shell's own cap) —
898
+ extra space becomes page margin rather than stretching sidebar/content grid
899
+ tracks to distances a pointer/eye shouldn't have to travel. */
900
+ @media (min-width: 2200px) {
901
+ .ds-247420 .app { max-width: 1920px; }
885
902
  }
886
903
 
887
904
  .ds-247420 .app-status {
@@ -1185,14 +1202,16 @@
1185
1202
  padding: var(--space-9) 0 var(--space-8);
1186
1203
  display: grid; gap: var(--space-5) var(--space-6);
1187
1204
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
1188
- grid-template-areas: 'title title' 'body actions';
1205
+ grid-template-areas: 'title title' 'body actions' 'badge badge';
1189
1206
  align-items: end;
1190
1207
  max-width: var(--measure-wide);
1191
1208
  }
1192
1209
  .ds-247420 .ds-hero-head { grid-area: title; display: grid; gap: var(--space-3); }
1193
1210
  .ds-247420 .ds-hero-body { grid-area: body; }
1194
1211
  .ds-247420 .ds-hero-actions { grid-area: actions; }
1195
- .ds-247420 .ds-hero-badge { grid-area: actions; }
1212
+ /* Badge gets its own row — sharing 'actions' overlapped it onto the CTAs
1213
+ whenever a caller passes both actions and badge. */
1214
+ .ds-247420 .ds-hero-badge { grid-area: badge; }
1196
1215
  .ds-247420 .ds-hero-title {
1197
1216
  font-family: var(--ff-display); font-weight: 700;
1198
1217
  font-size: clamp(40px, 9cqi, 116px);
@@ -1207,10 +1226,13 @@
1207
1226
  /* The lead phrase in the title — printed in the electric lead, not glowing. */
1208
1227
  .ds-247420 .ds-hero-accent { color: var(--accent-ink); font-weight: 700; }
1209
1228
  .ds-247420 .ds-hero-actions { display: flex; gap: var(--space-2, 10px); flex-wrap: wrap; align-self: end; }
1210
- @media (max-width: 900px) {
1229
+ /* Container-queried (the whole shell is; a 500px pane on a wide viewport
1230
+ would keep the two-column grid under a width @media). Left-aligned stack —
1231
+ no centering — preserving the asymmetric intent. */
1232
+ @container (max-width: 900px) {
1211
1233
  .ds-247420 .ds-hero {
1212
1234
  grid-template-columns: minmax(0, 1fr);
1213
- grid-template-areas: 'title' 'body' 'actions';
1235
+ grid-template-areas: 'title' 'body' 'actions' 'badge';
1214
1236
  align-items: start;
1215
1237
  padding: var(--space-7) 0 var(--space-6);
1216
1238
  }
@@ -1278,13 +1300,21 @@
1278
1300
  }
1279
1301
  .ds-247420 .ds-marquee-item { display: inline-flex; align-items: center; gap: var(--space-5); }
1280
1302
  .ds-247420 .ds-marquee-sep { color: var(--accent-ink); }
1281
- .ds-247420 .ds-marquee:hover .ds-marquee-track { animation-play-state: paused; }
1303
+ .ds-247420 .ds-marquee:hover .ds-marquee-track,
1304
+ .ds-247420 .ds-marquee:focus-within .ds-marquee-track,
1305
+ .ds-247420 .ds-marquee:active .ds-marquee-track { animation-play-state: paused; }
1282
1306
  @keyframes ds-marquee-run {
1283
1307
  from { transform: translateX(0); }
1284
1308
  to { transform: translateX(-50%); }
1285
1309
  }
1310
+ /* Touch has no hover-pause; slow the ticker so it burns less attention. */
1311
+ @media (hover: none), (pointer: coarse) {
1312
+ .ds-247420 .ds-marquee-track { animation-duration: 40s; }
1313
+ }
1286
1314
  @media (prefers-reduced-motion: reduce) {
1287
- .ds-247420 .ds-marquee-track { animation: none; }
1315
+ /* Static: wrap to a readable strip instead of a frozen half-offscreen run. */
1316
+ .ds-247420 .ds-marquee-track { animation: none; flex-wrap: wrap; white-space: normal; }
1317
+ .ds-247420 .ds-marquee-run-b { display: none; }
1288
1318
  }
1289
1319
 
1290
1320
  /* ============================================================
@@ -1292,6 +1322,7 @@
1292
1322
  ============================================================ */
1293
1323
  .ds-247420 .cli {
1294
1324
  display: flex; align-items: center; gap: 14px;
1325
+ overflow-x: auto;
1295
1326
  padding: 20px 24px;
1296
1327
  background: var(--ink); color: var(--paper);
1297
1328
  border-radius: var(--r-3);
@@ -1345,6 +1376,15 @@
1345
1376
  }
1346
1377
  .ds-247420 table.kv td:last-child {
1347
1378
  font-weight: 600;
1379
+ overflow-wrap: anywhere; min-width: 0;
1380
+ }
1381
+ /* Tiny screens: stack the key over the value instead of squeezing a 14ch
1382
+ label column beside long unbroken values (URLs, hashes). */
1383
+ @media (max-width: 400px) {
1384
+ .ds-247420 table.kv td { display: block; width: auto; padding: 4px 0; }
1385
+ .ds-247420 table.kv td:first-child { padding-top: 8px; }
1386
+ .ds-247420 table.kv tr + tr td { border-top: 0; }
1387
+ .ds-247420 table.kv tr + tr td:first-child { border-top: 1px solid var(--rule); }
1348
1388
  }
1349
1389
 
1350
1390
  /* ============================================================
@@ -1540,6 +1580,10 @@
1540
1580
  }
1541
1581
  .ds-247420 .row .sub { grid-column: 1 / -1; order: 3; }
1542
1582
  .ds-247420 .row .title { font-size: var(--fs-sm); }
1583
+ /* Changelog carries 3 children: give date+ver line one, message wraps below
1584
+ (the generic 2-col .row override staggers it into an implicit row). */
1585
+ .ds-247420 .ds-changelog-row { grid-template-columns: minmax(70px, 10ch) minmax(0, 1fr) !important; }
1586
+ .ds-247420 .ds-changelog-row .title { grid-column: 1 / -1; }
1543
1587
 
1544
1588
  /* Buttons */
1545
1589
  .ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost {
@@ -1583,7 +1627,9 @@
1583
1627
  gap: var(--space-2);
1584
1628
  }
1585
1629
  .ds-247420 .kpi-card { padding: var(--space-3); }
1586
- .ds-247420 .kpi-card .num { font-size: clamp(22px, 5vw, 32px); }
1630
+ /* Container-relative like the base rule (5vw sized against the viewport and
1631
+ jumped across the breakpoint). */
1632
+ .ds-247420 .kpi-card .num { font-size: clamp(22px, 8cqi, 32px); }
1587
1633
 
1588
1634
  /* Empty State */
1589
1635
  .ds-247420 .empty { padding: var(--space-5); font-size: var(--fs-xs); }
@@ -1617,10 +1663,11 @@
1617
1663
  @container (max-width: 760px) {
1618
1664
  .ds-247420 .app-body { grid-template-columns: 1fr !important; }
1619
1665
  .ds-247420 .app-side-shell { border-right: 0; border-bottom: 1px solid var(--rule); }
1620
- .ds-247420 .app-topbar { grid-template-columns: 1fr auto; }
1621
1666
  .ds-247420 .app-topbar nav { font-size: var(--fs-xs); gap: 14px; }
1622
1667
  .ds-247420 .row { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 4px !important; }
1623
1668
  .ds-247420 .row .sub { grid-column: 1 / -1; order: 3; }
1669
+ .ds-247420 .ds-changelog-row { grid-template-columns: minmax(70px, 10ch) minmax(0, 1fr) !important; }
1670
+ .ds-247420 .ds-changelog-row .title { grid-column: 1 / -1; }
1624
1671
  }
1625
1672
 
1626
1673
  /* --------------------------------------------------------------------
@@ -1635,9 +1682,8 @@
1635
1682
  min-height: 44px;
1636
1683
  }
1637
1684
 
1638
- /* Topbar Navigation */
1685
+ /* Topbar Navigation (flex container — no grid-template here) */
1639
1686
  .ds-247420 .app-topbar {
1640
- grid-template-columns: auto 1fr auto;
1641
1687
  gap: var(--space-3); padding: 12px var(--space-4);
1642
1688
  }
1643
1689
  .ds-247420 .app-topbar nav {
@@ -1716,6 +1762,8 @@
1716
1762
  gap: var(--space-2);
1717
1763
  }
1718
1764
  .ds-247420 .row .code { display: none; }
1765
+ /* Changelog's date lives in span.code — hiding it is data loss, not reflow. */
1766
+ .ds-247420 .ds-changelog-row .code { display: inline; font-size: var(--fs-micro); }
1719
1767
  .ds-247420 .row .sub { grid-column: 1 / -1; }
1720
1768
  }
1721
1769
 
@@ -2053,8 +2101,17 @@
2053
2101
 
2054
2102
  /* Full-width files stack: the stage's space-3 vertical beat without its
2055
2103
  920px cap/auto-margins, so the roots / toolbar / bulkbar / uploads / grid
2056
- bands keep one consistent rhythm instead of touching edge-to-edge. */
2057
- .ds-247420 .ds-files-stack { display: flex; flex-direction: column; gap: var(--space-3); min-height: 0; }
2104
+ bands keep one consistent rhythm instead of touching edge-to-edge. Carries
2105
+ the same side/bottom padding as .ds-file-stage (top collapses the same way
2106
+ when mounted directly under .app-main, which already supplies top padding)
2107
+ so switching a consumer from the capped stage to this full-width stack is a
2108
+ pure width change, not a spacing regression. */
2109
+ .ds-247420 .ds-files-stack {
2110
+ display: flex; flex-direction: column; gap: var(--space-3); min-height: 0;
2111
+ padding: 0 var(--space-3) var(--space-4);
2112
+ }
2113
+ .ds-247420 .app-main > div > .ds-files-stack,
2114
+ .ds-247420 .app-main .ds-files-stack { padding-top: 0; }
2058
2115
 
2059
2116
  /* Breadcrumb path */
2060
2117
  .ds-247420 .ds-crumb-path {
@@ -2066,6 +2123,10 @@
2066
2123
  padding: 4px 8px; border-radius: var(--r-1);
2067
2124
  color: var(--fg-3); font-family: inherit; font-size: var(--fs-sm);
2068
2125
  transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
2126
+ /* A single long unbroken segment (hash-named dir) must never force the
2127
+ whole path past the viewport. */
2128
+ max-width: min(40vw, 220px);
2129
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
2069
2130
  }
2070
2131
  .ds-247420 .ds-crumb-seg:hover { background: var(--bg-2); color: var(--fg); }
2071
2132
  .ds-247420 .ds-crumb-seg.leaf { color: var(--fg); font-weight: 600; }
@@ -2162,6 +2223,14 @@
2162
2223
  border-radius: var(--r-3);
2163
2224
  }
2164
2225
  .ds-247420 .ds-dropzone--wrap.dragover { animation: none; }
2226
+ /* Touch devices can never fire dragover — keep the pick-files affordance
2227
+ visible as a compact static row so upload stays reachable in wrap mode. */
2228
+ @media (hover: none) and (pointer: coarse) {
2229
+ .ds-247420 .ds-dropzone--wrap > .ds-dropzone-inner {
2230
+ display: flex; position: static; padding: var(--space-2);
2231
+ outline: none; background: transparent;
2232
+ }
2233
+ }
2165
2234
 
2166
2235
  /* Upload progress */
2167
2236
  .ds-247420 .ds-upload-progress { display: flex; flex-direction: column; gap: 6px; }
@@ -2190,7 +2259,12 @@
2190
2259
  .ds-247420 .ds-upload-item.error .ds-upload-fill { background: var(--warn); }
2191
2260
  .ds-247420 .ds-upload-item.error .ds-upload-pct { color: var(--warn); }
2192
2261
  /* Per-row upload recovery actions (replace / dismiss) — error rows are not dead ends. */
2193
- .ds-247420 .ds-upload-item { grid-template-columns: minmax(0, 1fr) 120px 44px auto; }
2262
+ .ds-247420 .ds-upload-item { grid-template-columns: minmax(0, 1fr) minmax(60px, 120px) 44px auto; }
2263
+ @media (max-width: 480px) {
2264
+ .ds-247420 .ds-upload-item { grid-template-columns: minmax(0, 1fr) 44px; }
2265
+ .ds-247420 .ds-upload-bar { grid-column: 1 / -1; order: 3; }
2266
+ .ds-247420 .ds-upload-actions { grid-column: 1 / -1; justify-content: flex-end; }
2267
+ }
2194
2268
  .ds-247420 .ds-upload-actions { display: inline-flex; gap: var(--space-1); justify-content: flex-end; }
2195
2269
  .ds-247420 .ds-upload-act {
2196
2270
  padding: 2px 10px; min-height: 24px; cursor: pointer;
@@ -2201,6 +2275,11 @@
2201
2275
  .ds-247420 .ds-upload-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
2202
2276
  @media (hover: none), (pointer: coarse) {
2203
2277
  .ds-247420 .ds-upload-act { min-height: 44px; min-width: 44px; }
2278
+ /* 44px floor for file controls on ANY touch device, not only narrow ones
2279
+ (the width-based mobile block misses wide touch tablets). */
2280
+ .ds-247420 .ds-file-act, .ds-247420 .ds-file-sort-btn, .ds-247420 .ds-crumb-seg, .ds-247420 .ds-file-filter-input { min-height: 44px; }
2281
+ .ds-247420 .ds-file-act { min-width: 44px; }
2282
+ .ds-247420 .ds-file-check, .ds-247420 .ds-file-selectall, .ds-247420 .ds-density-btn { min-height: 44px; min-width: 44px; }
2204
2283
  }
2205
2284
 
2206
2285
  /* Empty state */
@@ -2216,7 +2295,11 @@
2216
2295
  .ds-247420 .ds-modal-backdrop {
2217
2296
  position: fixed; inset: 0; z-index: var(--z-modal, 800);
2218
2297
  display: flex; align-items: center; justify-content: center;
2219
- padding: var(--space-3);
2298
+ /* Notch/home-indicator safe: near-fullscreen modals must not slide under. */
2299
+ padding: max(var(--space-3), env(safe-area-inset-top))
2300
+ max(var(--space-3), env(safe-area-inset-right))
2301
+ max(var(--space-3), env(safe-area-inset-bottom))
2302
+ max(var(--space-3), env(safe-area-inset-left));
2220
2303
  background: color-mix(in oklab, var(--ink) 55%, transparent);
2221
2304
  backdrop-filter: blur(3px);
2222
2305
  }
@@ -2226,7 +2309,9 @@
2226
2309
  @keyframes ds-modal-fade { from { opacity: 0; } to { opacity: 1; } }
2227
2310
  .ds-247420 .ds-modal {
2228
2311
  display: flex; flex-direction: column;
2229
- width: 100%; max-width: 460px; max-height: calc(100vh - 2 * var(--space-4));
2312
+ width: 100%; max-width: 460px;
2313
+ max-height: calc(100vh - 2 * var(--space-4));
2314
+ max-height: calc(100dvh - 2 * var(--space-4));
2230
2315
  background: var(--bg); color: var(--fg);
2231
2316
  border: var(--bw-hair) solid var(--rule);
2232
2317
  border-radius: var(--r-3); box-shadow: var(--shadow-3);
@@ -2259,6 +2344,10 @@
2259
2344
  font-family: inherit; font-size: var(--fs-sm);
2260
2345
  }
2261
2346
  .ds-247420 .ds-modal-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
2347
+ /* iOS auto-zooms inputs under 16px on focus, breaking the modal layout. */
2348
+ @media (hover: none), (pointer: coarse) {
2349
+ .ds-247420 .ds-modal-input { font-size: 16px; min-height: 44px; }
2350
+ }
2262
2351
  /* In-body modal error (role=alert): mutation failures (409/403) surface INSIDE
2263
2352
  the dialog, not behind the fixed overlay. */
2264
2353
  .ds-247420 .ds-modal-error {
@@ -2282,10 +2371,12 @@
2282
2371
  .ds-247420 .ds-preview-name {
2283
2372
  font-weight: 600; font-size: var(--fs-body);
2284
2373
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
2374
+ flex: 1 1 auto;
2285
2375
  }
2286
2376
  .ds-247420 .ds-preview-meta {
2287
2377
  font-family: var(--ff-mono); font-size: var(--fs-xs);
2288
2378
  color: var(--fg-3); white-space: nowrap;
2379
+ flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
2289
2380
  }
2290
2381
  .ds-247420 .ds-preview-actions { display: inline-flex; gap: 2px; margin-left: auto; }
2291
2382
  .ds-247420 .ds-preview-body {
@@ -2294,7 +2385,9 @@
2294
2385
  display: flex; flex-direction: column;
2295
2386
  }
2296
2387
  .ds-247420 .ds-preview-media {
2297
- max-width: 100%; max-height: 70vh; margin: 0 auto;
2388
+ max-width: 100%;
2389
+ max-height: 70vh; max-height: 70dvh;
2390
+ margin: 0 auto;
2298
2391
  border-radius: var(--r-2); object-fit: contain;
2299
2392
  }
2300
2393
  .ds-247420 .ds-preview-audio { width: 100%; }
@@ -2340,10 +2433,22 @@
2340
2433
 
2341
2434
  /* Mobile — modals go near-fullscreen, preview media shrinks. */
2342
2435
  @media (max-width: 560px) {
2343
- .ds-247420 .ds-modal { max-width: 100%; max-height: calc(100vh - 2 * var(--space-3)); }
2344
- .ds-247420 .ds-modal-preview { width: 100%; height: calc(100vh - 2 * var(--space-3)); max-height: none; }
2345
- .ds-247420 .ds-preview-media { max-height: 50vh; }
2436
+ .ds-247420 .ds-modal {
2437
+ max-width: 100%;
2438
+ max-height: calc(100vh - 2 * var(--space-3));
2439
+ max-height: calc(100dvh - 2 * var(--space-3));
2440
+ }
2441
+ .ds-247420 .ds-modal-preview {
2442
+ width: 100%; max-height: none;
2443
+ height: calc(100vh - 2 * var(--space-3));
2444
+ height: calc(100dvh - 2 * var(--space-3));
2445
+ }
2446
+ .ds-247420 .ds-preview-media { max-height: 50vh; max-height: 50dvh; }
2346
2447
  .ds-247420 .ds-file-stage { padding: var(--space-3) var(--space-2); }
2448
+ /* Preview head: let it wrap and drop the nowrap meta (duplicated in body)
2449
+ so the close button can never be pushed past the modal edge. */
2450
+ .ds-247420 .ds-preview-head { flex-wrap: wrap; row-gap: 4px; }
2451
+ .ds-247420 .ds-preview-meta { display: none; }
2347
2452
  }
2348
2453
 
2349
2454
  /* -- File browser UX affordances ---------------------------- */
@@ -2960,10 +3065,21 @@
2960
3065
  .ds-247420 .chat-composer textarea { padding: 10px 12px; }
2961
3066
  }
2962
3067
 
2963
- /* --- landscape orientation: reduce vertical space for composer --- */
3068
+ /* --- landscape orientation: reduce vertical space for chrome + composer --- */
2964
3069
  @media (max-height: 500px) and (orientation: landscape) {
2965
- .ds-247420 .chat-composer { padding: 6px 0; }
2966
- .ds-247420 .chat-composer textarea { min-height: 44px; max-height: 120px; }
3070
+ /* Keep horizontal padding: 0 put the textarea/focus ring flush on the edge. */
3071
+ .ds-247420 .chat-composer { padding: 6px var(--space-2); }
3072
+ .ds-247420 .chat-composer textarea { min-height: 36px; max-height: 96px; }
3073
+ .ds-247420 .chat-composer .chat-composer-hint,
3074
+ .ds-247420 .chat-composer .chat-composer-context { display: none; }
3075
+ /* Compact the shell chrome: ~114px of topbar+crumb+status is a third of a
3076
+ 360px-tall landscape fold. */
3077
+ .ds-247420 { --app-topbar-h: 40px; --app-crumb-h: 24px; }
3078
+ .ds-247420 .app-chrome { padding: 4px var(--pad-x); }
3079
+ .ds-247420 .app-status { display: none; }
3080
+ .ds-247420 .ws-crumb { min-height: 32px; }
3081
+ .ds-247420 .ds-hero { padding: var(--space-4) 0 var(--space-3); }
3082
+ .ds-247420 .ds-hero-title { font-size: clamp(28px, 6cqi, 56px); }
2967
3083
  }
2968
3084
 
2969
3085
  /* ============================================================
@@ -3387,6 +3503,15 @@
3387
3503
  }
3388
3504
  }
3389
3505
 
3506
+ /* Touch floor also for coarse-pointer devices that report hover (hybrid
3507
+ laptops/tablets with mice) — the block above requires hover:none too. */
3508
+ @media (pointer: coarse) {
3509
+ .ds-247420 .ds-icon-btn, .ds-247420 .ds-icon-btn-xs, .ds-247420 .ds-icon-btn-sm, .ds-247420 .ds-icon-btn-base {
3510
+ min-width: 44px; min-height: 44px;
3511
+ }
3512
+ .ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost, .ds-247420 .app-topbar nav a, .ds-247420 .app-side a { min-height: 44px; }
3513
+ }
3514
+
3390
3515
  /* ------------------------------------------------------------
3391
3516
  Theme Transition Smoothness
3392
3517
  -------------------------------------------------------------- */
@@ -3618,16 +3743,24 @@
3618
3743
  .ds-247420 .app-body.no-side { grid-template-columns: 1fr !important; }
3619
3744
  .ds-247420 .app-side-shell {
3620
3745
  position: absolute;
3621
- left: 0; top: var(--app-topbar-h);
3622
- height: calc(100% - var(--app-topbar-h) - var(--app-status-h));
3746
+ /* Full-height overlay drawer: the merged .app-chrome wraps and its real
3747
+ height drifts from --app-topbar-h, so anchoring below it misplaces the
3748
+ drawer. Overlay the chrome instead (z above --z-header), like ws drawers. */
3749
+ left: 0; top: 0;
3750
+ height: 100%;
3623
3751
  width: 280px; max-width: 80%;
3624
3752
  transform: translateX(-100%);
3625
3753
  transition: transform var(--dur-base, 240ms) var(--ease, ease);
3626
- z-index: 50;
3754
+ /* Above the sticky chrome (z-header): scrim > chrome > content budget. */
3755
+ z-index: calc(var(--z-header, 100) + 2);
3627
3756
  background: var(--bg);
3628
3757
  border-right: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
3629
3758
  overflow-y: auto;
3759
+ overscroll-behavior: contain;
3630
3760
  }
3761
+ /* Lock the content scroller while the drawer is open so touch pans don't
3762
+ scroll the page behind the scrim. */
3763
+ .ds-247420 .app-body.side-open .app-main { overflow: hidden; }
3631
3764
  .ds-247420 .app-side-shell.open,
3632
3765
  .ds-247420 .app-side.open,
3633
3766
  .ds-247420 .app-body.side-open .app-side-shell { transform: translateX(0); }
@@ -3660,7 +3793,8 @@
3660
3793
  display: none;
3661
3794
  position: absolute; inset: 0;
3662
3795
  background: color-mix(in oklab, var(--bg) 60%, transparent);
3663
- z-index: 49;
3796
+ /* Above the sticky chrome so nav behind an open drawer is not clickable. */
3797
+ z-index: calc(var(--z-header, 100) + 1);
3664
3798
  }
3665
3799
  @container (max-width: 900px) {
3666
3800
  .ds-247420 .app-body.side-open .app-side-scrim { display: block; }
@@ -3672,7 +3806,9 @@
3672
3806
  .ds-247420 .app-side-toggle {
3673
3807
  display: none;
3674
3808
  position: absolute; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
3675
- z-index: 51;
3809
+ /* Above the sticky topbar/chrome (z-header) and the drawer/scrim so the
3810
+ translucent blurred chrome never paints over or intercepts the toggle. */
3811
+ z-index: calc(var(--z-header, 100) + 3);
3676
3812
  /* 44x44 minimum hit area (WCAG 2.5.5 / Apple HIG) - 36px is below the
3677
3813
  reliable-tap threshold on touch. */
3678
3814
  width: 44px; height: 44px;
@@ -3724,6 +3860,8 @@
3724
3860
  .ds-247420 .app-topbar nav,
3725
3861
  .ds-247420 .app-topbar > :last-child { display: none; }
3726
3862
  .ds-247420 .brand { font-size: var(--fs-tiny); }
3863
+ /* Slightly narrower drawer on tiny phones; max-width:80% remains the guard. */
3864
+ .ds-247420 .app-side-shell { width: 260px; }
3727
3865
  }
3728
3866
 
3729
3867
  /* ----------------------------------------------------------------------------
@@ -3797,6 +3935,11 @@
3797
3935
  @media (prefers-reduced-motion: no-preference) {
3798
3936
  .ds-247420 .ws-shell { transition: grid-template-columns var(--dur-base) var(--ease); }
3799
3937
  }
3938
+ /* Ultrawide: cap the shell so the 1fr content track doesn't stretch to
3939
+ unreadable measures while the fixed side columns pin to their clamps. */
3940
+ @media (min-width: 1920px) {
3941
+ .ds-247420 .ws-shell { max-width: 1920px; margin-inline: auto; }
3942
+ }
3800
3943
 
3801
3944
  /* Rail (left nav) */
3802
3945
  .ds-247420 .ws-rail {
@@ -3832,7 +3975,7 @@
3832
3975
  }
3833
3976
  .ds-247420 .ws-rail-action:hover { filter: brightness(1.08); }
3834
3977
  .ds-247420 .ws-rail-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
3835
- .ds-247420 .ws-rail-nav { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; min-height: 0; overflow-y: auto; }
3978
+ .ds-247420 .ws-rail-nav { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
3836
3979
  .ds-247420 .ws-rail-item {
3837
3980
  display: flex; align-items: center; gap: var(--space-2);
3838
3981
  width: 100%; padding: var(--space-2); min-height: 44px;
@@ -3895,6 +4038,7 @@
3895
4038
  min-height: 0; display: flex; flex-direction: column;
3896
4039
  background: var(--bg-2); border-left: var(--bw-hair) solid var(--bg-3);
3897
4040
  overflow: hidden; transition: width var(--dur-base) var(--ease);
4041
+ overscroll-behavior: contain;
3898
4042
  }
3899
4043
  .ds-247420 .ws-pane-collapsed .ws-pane { width: 0; border-left: none; }
3900
4044
  .ds-247420 .ws-pane-collapsed .ws-pane > * { display: none; }
@@ -3979,12 +4123,19 @@
3979
4123
  }
3980
4124
  .ds-247420 .ws-sessions {
3981
4125
  position: fixed; inset: 0 auto 0 0;
3982
- width: min(var(--ws-sessions-w), 80vw);
4126
+ /* Immune to the desktop collapse var (--ws-sessions-w:0px persisted from
4127
+ a desktop session would open an invisible 0-width drawer). */
4128
+ width: min(max(var(--ws-sessions-w), 280px), 80vw);
3983
4129
  z-index: 42; transform: translateX(-110%);
3984
4130
  transition: transform var(--dur-base) var(--ease);
3985
4131
  border-right: var(--bw-hair) solid var(--bg-3);
4132
+ overscroll-behavior: contain;
3986
4133
  }
3987
4134
  .ds-247420 .ws-shell.ws-sessions-open .ws-sessions { transform: translateX(0); }
4135
+ /* Drawer mode ignores the desktop collapsed state: children stay rendered
4136
+ and the border returns, so a persisted collapse can't blank the drawer. */
4137
+ .ds-247420 .ws-shell.ws-sessions-collapsed .ws-sessions > * { display: revert; }
4138
+ .ds-247420 .ws-shell.ws-sessions-collapsed .ws-sessions { border-right: var(--bw-hair) solid var(--bg-3); }
3988
4139
  .ds-247420 .ws-sessions-drawer-toggle { display: inline-flex; }
3989
4140
  }
3990
4141
 
@@ -4094,6 +4245,21 @@
4094
4245
  .ds-247420 .ws-crumb,
4095
4246
  .ds-247420 .app-status { display: none; }
4096
4247
  .ds-247420 .ws-main { overflow: visible; height: auto; }
4248
+ /* AppShell: unpin the viewport-height frame so content flows across pages,
4249
+ and drop all chrome (it prints as page furniture otherwise). */
4250
+ .ds-247420 .app { height: auto; min-height: 0; overflow: visible; display: block; }
4251
+ .ds-247420 .app-body { display: block; }
4252
+ .ds-247420 .app-main { overflow: visible; height: auto; display: block; max-width: 100%; }
4253
+ .ds-247420 .app-topbar, .ds-247420 .app-chrome, .ds-247420 .app-crumb, .ds-247420 .app-side-shell, .ds-247420 .app-side-scrim, .ds-247420 .app-side-toggle, .ds-247420 .btn-fab, .ds-247420 .skip-link, .ds-247420 .ds-marquee { display: none; }
4254
+ /* Modals/preview: print the content, not a blurred overlay clipped to one page. */
4255
+ .ds-247420 .ds-modal-backdrop { position: static; background: none; backdrop-filter: none; padding: 0; }
4256
+ .ds-247420 .ds-modal, .ds-247420 .ds-modal-preview { max-width: 100%; max-height: none; box-shadow: none; }
4257
+ .ds-247420 .ds-modal-body, .ds-247420 .ds-preview-body, .ds-247420 .ds-preview-code, .ds-247420 .ds-preview-text { overflow: visible; }
4258
+ .ds-247420 .ds-modal-actions, .ds-247420 .ds-preview-actions { display: none; }
4259
+ /* Data-density: fixed-height log clips; bg-only tiles lose their boundary. */
4260
+ .ds-247420 .ds-live-log { height: auto; max-height: none; overflow: visible; }
4261
+ .ds-247420 .ds-stat, .ds-247420 .kpi-card { border: 1px solid var(--rule); }
4262
+ .ds-247420 .ds-session-row { break-inside: avoid; }
4097
4263
  }
4098
4264
 
4099
4265
  /* ============================================================
@@ -4118,15 +4284,26 @@
4118
4284
  }
4119
4285
  .ds-247420 .ds-phasewalk-seg.is-reached { background: var(--success); }
4120
4286
  .ds-247420 .ds-phasewalk-seg.is-gap { background: var(--warn); }
4287
+ /* Standalone PhaseWalk reserves headroom for the labels instead of letting
4288
+ them escape upward and overlap the element above. */
4289
+ .ds-247420 .ds-phasewalk { padding-top: 15px; }
4121
4290
  .ds-247420 .ds-phasewalk-lbl {
4122
4291
  position: absolute; top: -15px; left: 0;
4123
4292
  font-size: var(--fs-micro); color: var(--fg-3); white-space: nowrap;
4124
4293
  }
4294
+ /* Inline in a single-line SessionRow the labels would overlap the row above —
4295
+ segments already carry title tooltips. */
4296
+ .ds-247420 .ds-session-row .ds-phasewalk { padding-top: 0; }
4297
+ .ds-247420 .ds-session-row .ds-phasewalk-lbl { display: none; }
4125
4298
 
4126
4299
  /* TreeNode */
4127
4300
  .ds-247420 .ds-tree-node {
4128
4301
  padding: 5px 10px; border-left: var(--bw-rule) solid var(--bg-3);
4129
4302
  margin: 2px 0 2px 16px; font-size: var(--fs-tiny);
4303
+ min-width: 0; overflow-wrap: anywhere;
4304
+ }
4305
+ @media (max-width: 400px) {
4306
+ .ds-247420 .ds-tree-node { margin-left: 8px; padding-left: 8px; }
4130
4307
  }
4131
4308
  .ds-247420 .ds-tree-node.is-phase { border-color: var(--accent); background: var(--bg-3); font-weight: 600; }
4132
4309
  .ds-247420 .ds-tree-node.is-deviation { border-color: var(--warn); background: var(--danger-surface); color: var(--warn); }
@@ -4141,17 +4318,26 @@
4141
4318
  /* BarRow */
4142
4319
  .ds-247420 .ds-bar-row { display: flex; align-items: center; gap: 8px; margin: 3px 0; font-size: var(--fs-tiny); }
4143
4320
  .ds-247420 .ds-bar-row-label { width: 100px; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4144
- .ds-247420 .ds-bar-bg { flex: 1; background: var(--bg-3); border-radius: 2px; height: 6px; overflow: hidden; }
4321
+ .ds-247420 .ds-bar-bg { flex: 1; min-width: 60px; background: var(--bg-3); border-radius: 2px; height: 6px; overflow: hidden; }
4145
4322
  .ds-247420 .ds-bar-fill { background: var(--accent); height: 100%; border-radius: 2px; }
4146
- .ds-247420 .ds-bar-row-value { flex-shrink: 0; color: var(--fg-2); }
4323
+ .ds-247420 .ds-bar-row-value { flex-shrink: 0; color: var(--fg-2); max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4324
+ @media (max-width: 400px) {
4325
+ .ds-247420 .ds-bar-row-label { width: 72px; }
4326
+ }
4147
4327
 
4148
4328
  /* StatTile / StatsGrid */
4149
- .ds-247420 .ds-stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--space-2); }
4329
+ /* min(140px, 100%) keeps the grid from collapsing to 1 column early inside
4330
+ padded panels; the wrapper div stretches its tile to equal row height. */
4331
+ .ds-247420 .ds-stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); gap: var(--space-2); }
4332
+ .ds-247420 .ds-stats-grid > div { display: grid; }
4333
+ @media (max-width: 360px) {
4334
+ .ds-247420 .ds-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-1); }
4335
+ }
4150
4336
  .ds-247420 .ds-stats-grid-empty { padding: var(--space-3); color: var(--fg-3); font-size: var(--fs-tiny); }
4151
- .ds-247420 .ds-stat { background: var(--bg-3); border-radius: 4px; padding: 10px 12px; }
4152
- .ds-247420 .ds-stat-val { font-size: 22px; font-weight: 700; color: var(--accent-ink); }
4153
- .ds-247420 .ds-stat-val.rate-big { font-size: 32px; color: var(--success); }
4154
- .ds-247420 .ds-stat-val.err-rate { font-size: 32px; color: var(--warn); }
4337
+ .ds-247420 .ds-stat { min-width: 0; background: var(--bg-3); border-radius: 4px; padding: 10px 12px; }
4338
+ .ds-247420 .ds-stat-val { font-size: clamp(18px, 5cqi, 22px); font-weight: 700; color: var(--accent-ink); overflow-wrap: anywhere; }
4339
+ .ds-247420 .ds-stat-val.rate-big { font-size: clamp(24px, 7cqi, 32px); color: var(--success); }
4340
+ .ds-247420 .ds-stat-val.err-rate { font-size: clamp(24px, 7cqi, 32px); color: var(--warn); }
4155
4341
  .ds-247420 .ds-stat-lbl { font-size: var(--fs-micro); color: var(--fg-3); margin-top: 2px; }
4156
4342
 
4157
4343
  /* SubGrid */
@@ -4168,14 +4354,22 @@
4168
4354
  /* SessionRow */
4169
4355
  .ds-247420 .ds-session-row {
4170
4356
  display: flex; align-items: center; gap: 8px; padding: 6px 10px;
4357
+ flex-wrap: wrap; min-width: 0;
4171
4358
  border-bottom: var(--bw-hair) solid var(--bg-3); cursor: pointer;
4172
4359
  }
4173
4360
  .ds-247420 .ds-session-row:hover { background: var(--bg-3); }
4174
4361
  .ds-247420 .ds-session-row-id {
4175
4362
  font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--accent-ink);
4176
- width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
4363
+ flex: 0 1 160px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
4364
+ }
4365
+ .ds-247420 .ds-session-row-counts {
4366
+ font-size: var(--fs-micro); color: var(--fg-3);
4367
+ flex: 1 1 200px; min-width: 0;
4368
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
4369
+ }
4370
+ @media (max-width: 640px) {
4371
+ .ds-247420 .ds-session-row-span { flex-basis: 100%; }
4177
4372
  }
4178
- .ds-247420 .ds-session-row-counts { font-size: var(--fs-micro); color: var(--fg-3); width: 280px; }
4179
4373
  .ds-247420 .ds-session-row-devcnt { color: var(--warn); font-weight: 600; }
4180
4374
  .ds-247420 .ds-session-row-span { font-size: var(--fs-micro); color: var(--fg-3); }
4181
4375
 
@@ -4186,17 +4380,363 @@
4186
4380
  }
4187
4381
  .ds-247420 .ds-dev-row strong { color: var(--warn); }
4188
4382
 
4189
- /* LiveLog */
4383
+ /* LiveLog — natural height with a viewport-tracking cap (dvh follows mobile
4384
+ URL-bar chrome; min-height keeps short-landscape from going near-zero). */
4190
4385
  .ds-247420 .ds-live-log {
4191
- height: calc(100vh - 200px); overflow-y: auto;
4386
+ height: auto;
4387
+ max-height: calc(100vh - 200px);
4388
+ max-height: calc(100dvh - 200px);
4389
+ min-height: 160px;
4390
+ overflow-y: auto; overflow-x: hidden;
4192
4391
  font-family: var(--ff-mono); font-size: var(--fs-micro); line-height: 1.5;
4193
4392
  }
4194
- .ds-247420 .ds-live-log-empty { height: auto; padding: var(--space-3); color: var(--fg-3); }
4195
- .ds-247420 .ds-live-log-entry { padding: 2px 8px; border-bottom: var(--bw-hair) solid var(--bg-3); }
4393
+ /* Embedded in a WM window the viewport calc is meaningless — fill the container. */
4394
+ .ds-247420 .fd-root .ds-live-log { height: 100%; max-height: none; min-height: 0; flex: 1 1 auto; }
4395
+ .ds-247420 .ds-live-log-empty { height: auto; min-height: 0; padding: var(--space-3); color: var(--fg-3); }
4396
+ .ds-247420 .ds-live-log-entry { padding: 2px 8px; border-bottom: var(--bw-hair) solid var(--bg-3); overflow-wrap: anywhere; }
4196
4397
  .ds-247420 .ds-live-log-entry:hover { background: var(--bg-3); }
4197
4398
  .ds-247420 .ds-live-log-ts { margin-right: 6px; color: var(--fg-3); }
4198
4399
  .ds-247420 .ds-live-log-subtag { margin-right: 6px; padding: 0 5px; border-radius: 2px; font-size: var(--fs-micro); }
4199
- .ds-247420 .ds-live-log-preview { margin-left: 6px; color: var(--fg-3); }
4400
+ .ds-247420 .ds-live-log-preview { margin-left: 6px; color: var(--fg-3); word-break: break-word; }
4401
+
4402
+ /* Touch floors for the dense controls (not covered by the mobile width blocks). */
4403
+ @media (pointer: coarse) {
4404
+ .ds-247420 .ds-sub-btn { min-height: 44px; }
4405
+ .ds-247420 .ds-session-row { min-height: 44px; }
4406
+ .ds-247420 .ds-live-log-entry { padding-block: 6px; }
4407
+ }
4408
+
4409
+
4410
+ /* == appended: popovers-files == */
4411
+ /* FilePreviewMedia controls row — spacing + coarse-pointer tap floor */
4412
+ .ds-247420 .ds-preview-media-controls {
4413
+ display: flex;
4414
+ align-items: center;
4415
+ gap: var(--space-2);
4416
+ flex-wrap: wrap;
4417
+ }
4418
+ @media (hover: none), (pointer: coarse) {
4419
+ .ds-247420 .ds-preview-media-controls .chat-code-copy,
4420
+ .ds-247420 .chat-code-copy-head {
4421
+ min-height: 44px;
4422
+ min-width: 44px;
4423
+ }
4424
+ }
4425
+
4426
+ /* == appended: ui-kits == */
4427
+ /* ============================================================
4428
+ ui_kit responsive helpers (kits-grids sweep) */
4429
+ .ds-247420 .ds-section-pad { padding: clamp(6px, 1.2vw, 16px); }
4430
+ .ds-247420 .ds-panel-gap { margin: var(--space-2) 0; }
4431
+ .ds-247420 .ds-panel-duo { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); margin: var(--space-2) 0; }
4432
+ @media (max-width: 760px) {
4433
+ .ds-247420 .ds-panel-duo { grid-template-columns: 1fr; }
4434
+ }
4435
+ /* wide dense rows/tables scroll inside their panel, never the page */
4436
+ .ds-247420 .ds-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
4437
+
4438
+ /* --- slide deck ------------------------------------------- */
4439
+ .ds-247420 .ds-deck-stage {
4440
+ aspect-ratio: 16 / 9;
4441
+ width: 100%;
4442
+ max-width: min(1100px, 100%);
4443
+ margin: var(--space-3) auto;
4444
+ background: var(--bg-2);
4445
+ border-radius: 18px;
4446
+ padding: clamp(16px, 5vw, 64px);
4447
+ box-sizing: border-box;
4448
+ display: flex;
4449
+ overflow: hidden;
4450
+ container-type: inline-size; /* cqw units track the stage, not the viewport */
4451
+ }
4452
+ @media (max-height: 500px) and (orientation: landscape) {
4453
+ .ds-247420 .ds-deck-stage {
4454
+ max-height: calc(100vh - 140px);
4455
+ max-height: calc(100dvh - 140px);
4456
+ aspect-ratio: auto;
4457
+ }
4458
+ }
4459
+ .ds-247420 .ds-deck-slide { flex: 1; display: flex; min-width: 0; }
4460
+ .ds-247420 .ds-deck-controls {
4461
+ display: flex; align-items: center; justify-content: center; gap: 14px;
4462
+ padding: 8px; font-family: var(--ff-mono); font-size: var(--fs-sm);
4463
+ }
4464
+ .ds-247420 .ds-deck-count { color: var(--fg-3); }
4465
+ @media (pointer: coarse) {
4466
+ .ds-247420 .ds-deck-controls .btn { min-height: 44px; min-width: 44px; }
4467
+ }
4468
+ .ds-247420 .ds-slide-eyebrow {
4469
+ font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.1em;
4470
+ text-transform: uppercase; color: var(--fg-3); margin-bottom: clamp(12px, 2.5cqw, 24px);
4471
+ }
4472
+ .ds-247420 .ds-slide-col { display: flex; flex-direction: column; justify-content: center; gap: clamp(12px, 2.5cqw, 24px); min-width: 0; }
4473
+ .ds-247420 .ds-slide-col--start { align-items: flex-start; }
4474
+ .ds-247420 .ds-slide-col--narrow { max-width: 38ch; }
4475
+ .ds-247420 .ds-slide-col--quote { max-width: 42ch; }
4476
+ .ds-247420 .ds-slide-hero {
4477
+ font-size: clamp(var(--fs-h2), 6cqw, var(--fs-hero));
4478
+ line-height: var(--lh-tight); letter-spacing: var(--tr-tight); font-weight: 600;
4479
+ color: var(--slide-accent, var(--accent-ink));
4480
+ overflow-wrap: anywhere;
4481
+ }
4482
+ .ds-247420 .ds-slide-h1 {
4483
+ font-size: clamp(var(--fs-h3), 4.5cqw, var(--fs-h1));
4484
+ line-height: var(--lh-snug); color: var(--fg); font-weight: 500; min-width: 0;
4485
+ }
4486
+ .ds-247420 .ds-slide-h1--lead { margin-bottom: 12px; }
4487
+ .ds-247420 .ds-slide-quote-body {
4488
+ font-size: clamp(var(--fs-lg), 3.5cqw, var(--fs-h2));
4489
+ line-height: var(--lh-snug); color: var(--fg); font-weight: 400; font-style: italic;
4490
+ }
4491
+ .ds-247420 .ds-slide-cite { font-family: var(--ff-mono); font-size: var(--fs-sm); color: var(--fg-3); }
4492
+ .ds-247420 .ds-slide-bullet {
4493
+ display: flex; gap: clamp(8px, 2vw, 18px); align-items: baseline;
4494
+ border-bottom: 1px solid var(--rule); padding: 12px 0; flex-wrap: wrap;
4495
+ }
4496
+ .ds-247420 .ds-slide-bullet-key {
4497
+ flex: 0 1 clamp(56px, 18%, 100px); min-width: 0;
4498
+ font-family: var(--ff-mono); font-size: var(--fs-sm);
4499
+ color: var(--slide-accent, var(--accent-ink));
4500
+ }
4501
+ .ds-247420 .ds-slide-bullet-val { color: var(--fg-2); font-size: var(--fs-lg); min-width: 0; }
4502
+ .ds-247420 .ds-slide-split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(12px, 3vw, 32px); margin-top: 12px; }
4503
+ @media (max-width: 760px) {
4504
+ .ds-247420 .ds-slide-split { grid-template-columns: 1fr; }
4505
+ }
4506
+ .ds-247420 .ds-slide-split-cell {
4507
+ padding: 18px; background: var(--bg-2); border-radius: 14px;
4508
+ color: var(--fg-2); font-size: var(--fs-lg); line-height: var(--lh-base); min-width: 0;
4509
+ }
4510
+ .ds-247420 .ds-slide-split-cell--accent { border-left: 3px solid var(--slide-accent, var(--accent)); }
4511
+
4512
+ /* --- error 404 --------------------------------------------- */
4513
+ .ds-247420 .ds-err-hero {
4514
+ padding: clamp(16px, 5vw, 36px) clamp(12px, 4vw, 22px);
4515
+ text-align: center; display: flex; flex-direction: column; gap: 14px; align-items: center;
4516
+ }
4517
+ .ds-247420 .ds-err-numeral {
4518
+ font-family: var(--ff-mono); font-size: clamp(56px, 20vw, 120px);
4519
+ line-height: 1; color: var(--panel-text-3); letter-spacing: -0.03em;
4520
+ }
4521
+ .ds-247420 .ds-err-path {
4522
+ display: inline-flex; gap: 6px; align-items: baseline; flex-wrap: wrap; max-width: 100%;
4523
+ font-family: var(--ff-mono); font-size: 13px; color: var(--panel-text-2);
4524
+ background: var(--panel-1); padding: 6px 12px; border-radius: 8px;
4525
+ overflow-wrap: anywhere; word-break: break-all;
4526
+ }
4527
+
4528
+ /* --- gallery ------------------------------------------------ */
4529
+ .ds-247420 .ds-tile-grid {
4530
+ padding: clamp(8px, 2.5vw, 16px);
4531
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr)); gap: 8px;
4532
+ }
4533
+ .ds-247420 .ds-tile-grid--tight { grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); }
4534
+ .ds-247420 .ds-swatch-grid {
4535
+ padding: clamp(8px, 2.5vw, 16px);
4536
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr)); gap: 12px;
4537
+ }
4538
+ .ds-247420 .ds-gallery-tile {
4539
+ cursor: pointer; display: flex; flex-direction: column; gap: 6px;
4540
+ padding: 12px; border-radius: 10px; min-height: clamp(120px, 18vw, 160px);
4541
+ border: 0; text-align: left; font: inherit; color: inherit;
4542
+ background: var(--tile-tone, var(--panel-1));
4543
+ }
4544
+ .ds-247420 .ds-gallery-tile:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
4545
+ .ds-247420 .ds-gallery-tile--tight { min-height: clamp(96px, 14vw, 120px); }
4546
+ .ds-247420 .ds-lightbox {
4547
+ position: fixed; inset: 0; background: var(--scrim);
4548
+ display: flex; align-items: center; justify-content: center;
4549
+ padding: clamp(12px, 4vw, 32px);
4550
+ padding-bottom: max(clamp(12px, 4vw, 32px), env(safe-area-inset-bottom));
4551
+ z-index: 50;
4552
+ }
4553
+ .ds-247420 .ds-lightbox-card {
4554
+ background: var(--panel-0); border-radius: 14px; padding: clamp(16px, 4vw, 28px);
4555
+ width: min(520px, 100%); min-width: 0;
4556
+ max-height: calc(100vh - 24px);
4557
+ max-height: calc(100dvh - 24px);
4558
+ overflow: auto;
4559
+ display: flex; flex-direction: column; gap: 14px;
4560
+ }
4561
+ .ds-247420 .ds-lightbox-preview {
4562
+ padding: clamp(16px, 6vw, 36px); border-radius: 10px; text-align: center;
4563
+ font-family: var(--ff-mono); white-space: pre-line; font-size: clamp(16px, 5vw, 24px);
4564
+ background: var(--tile-tone, var(--panel-1));
4565
+ }
4566
+
4567
+ /* --- search ------------------------------------------------- */
4568
+ .ds-247420 .ds-topbar-search { width: min(280px, 100%); min-width: 0; flex: 1 1 clamp(140px, 30vw, 280px); }
4569
+ @media (max-width: 480px) {
4570
+ .ds-247420 .ds-topbar-search { flex-basis: 100%; }
4571
+ }
4572
+ .ds-247420 .ds-empty-state { padding: clamp(16px, 5vw, 24px); text-align: center; color: var(--panel-text-3); }
4573
+ .ds-247420 .ds-empty-state-glyph { font-size: clamp(24px, 6vw, 32px); }
4574
+ .ds-247420 .ds-empty-state-msg { margin: 6px 0; }
4575
+ .ds-247420 .ds-empty-state-hint { margin: 0; font-size: var(--fs-sm); }
4576
+
4577
+ /* --- system primer ------------------------------------------ */
4578
+ .ds-247420 .ds-swatch-grid-sm {
4579
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(110px, 100%), 1fr));
4580
+ gap: 12px; padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px);
4581
+ }
4582
+ .ds-247420 .ds-swatch-grid-lg { grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); }
4583
+ .ds-247420 .ds-swatch-col { display: flex; flex-direction: column; gap: 6px; }
4584
+ .ds-247420 .ds-swatch-chip { height: 48px; border-radius: 10px; border: 1px solid var(--rule); background: var(--swatch, var(--panel-1)); }
4585
+ .ds-247420 .ds-swatch-chip--big { height: 64px; }
4586
+ .ds-247420 .ds-swatch-name { font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
4587
+ .ds-247420 .ds-type-panel { padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px); display: flex; flex-direction: column; gap: 14px; }
4588
+ .ds-247420 .ds-type-row {
4589
+ display: flex; align-items: baseline; gap: 14px;
4590
+ border-bottom: 1px solid var(--rule); padding-bottom: 8px; flex-wrap: wrap;
4591
+ }
4592
+ .ds-247420 .ds-type-row-label { flex: 0 0 64px; font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
4593
+ .ds-247420 .ds-type-sample {
4594
+ min-width: 0; overflow-wrap: anywhere; line-height: var(--lh-tight); color: var(--fg);
4595
+ font-size: var(--sample-size, var(--fs-body));
4596
+ }
4597
+ .ds-247420 .ds-prim-panel { padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px); display: flex; flex-direction: column; gap: 18px; }
4598
+ .ds-247420 .ds-prim-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
4599
+ .ds-247420 .ds-prim-label { flex: 0 0 64px; font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
4600
+
4601
+ /* == appended: content-site == */
4602
+ /* Home landing wrappers (site/theme.mjs) — replace banned inline styles. */
4603
+ .ds-247420 .ds-home-hero-wrap { padding: 0 var(--space-2, 8px); }
4604
+ .ds-247420 .ds-home-panel { margin: var(--space-2, 8px); }
4605
+ @media (max-width: 480px) {
4606
+ .ds-247420 .ds-home-panel { margin: var(--space-1, 4px) 0; }
4607
+ }
4608
+ .ds-247420 .ds-quickstart {
4609
+ padding: var(--space-3, 16px) var(--space-4, 22px);
4610
+ display: flex;
4611
+ flex-direction: column;
4612
+ gap: 6px;
4613
+ }
4614
+ /* Table() scroll containment — wide tables scroll inside their own box,
4615
+ never the page body. */
4616
+ .ds-247420 .ds-table-wrap {
4617
+ overflow-x: auto;
4618
+ -webkit-overflow-scrolling: touch;
4619
+ max-width: 100%;
4620
+ }
4621
+ .ds-247420 .ds-table-wrap > table { min-width: 100%; }
4622
+
4623
+
4624
+ /* == appended: settings kit cleanup == */
4625
+ /* == appended: settings kit == */
4626
+ .ds-247420 .ds-settings-main { padding: 8px; }
4627
+ .ds-247420 .ds-settings-body { padding: 14px 18px; }
4628
+ .ds-247420 .ds-settings-body-stack { display: flex; flex-direction: column; gap: 10px; }
4629
+ .ds-247420 .ds-field-block { margin: 10px 0; }
4630
+ .ds-247420 .ds-field-eyebrow {
4631
+ font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.06em;
4632
+ text-transform: uppercase; color: var(--panel-text-3);
4633
+ }
4634
+ .ds-247420 .ds-hint-sm { font-size: 12px; color: var(--panel-text-2); }
4635
+ .ds-247420 .ds-note-quiet { margin: 0; color: var(--panel-text-2); }
4636
+ .ds-247420 .ds-btn-row { display: flex; gap: 8px; flex-wrap: wrap; }
4637
+ .ds-247420 .ds-btn-row-tight { gap: 6px; }
4638
+ .ds-247420 .ds-key-input { flex: 1 1 160px; min-width: 0; font-family: var(--ff-mono); }
4639
+ .ds-247420 .ds-toggle-btn { min-width: 78px; }
4640
+ .ds-247420 .ds-toggle-label { margin-left: 8px; color: inherit; opacity: 0.7; }
4641
+ .ds-247420 .ds-btn-warn { color: var(--warn); }
4642
+ .ds-247420 .ds-btn-mascot { color: var(--mascot); }
4643
+ .ds-247420 .ds-savebar {
4644
+ position: sticky; bottom: 8px; display: flex; align-items: center;
4645
+ justify-content: flex-end; gap: 8px; flex-wrap: wrap; padding: 10px;
4646
+ background: var(--panel-2); border-radius: 10px; margin: 8px 0;
4647
+ }
4648
+ .ds-247420 .ds-savebar-note { flex: 1 1 160px; min-width: 0; color: var(--panel-text-2); }
4649
+ .ds-247420 .ds-settings-modal { min-width: min(320px, calc(100vw - 32px)); max-width: 480px; }
4650
+ .ds-247420 .ds-modal-body-form { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
4651
+ .ds-247420 .ds-modal-note { margin: 0 0 8px; color: var(--panel-text-2); font-size: 14px; }
4652
+ .ds-247420 .ds-draft-preview {
4653
+ background: var(--panel-1); padding: 12px; border-radius: 6px;
4654
+ font-size: 13px; color: var(--panel-text-2); max-height: 120px;
4655
+ overflow-y: auto; font-family: var(--ff-mono); overflow-wrap: anywhere;
4656
+ }
4657
+ .ds-247420 .ds-modal-actions { display: flex; gap: 8px; margin-top: 12px; justify-content: space-between; flex-wrap: wrap; }
4658
+
4659
+ /* == appended: signin kit cleanup == */
4660
+ /* -- signin kit (ui_kits/signin) -- */
4661
+ .ds-247420 .ds-auth-wrap { padding: var(--space-2, 8px); display: flex; flex-direction: column; align-items: center; }
4662
+ .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; }
4663
+ .ds-247420 .ds-auth-form { padding: clamp(12px, 3vw, 18px); display: flex; flex-direction: column; gap: 10px; }
4664
+ .ds-247420 .ds-auth-sent { align-items: center; text-align: center; }
4665
+ .ds-247420 .ds-auth-sent-glyph { font-size: 32px; color: var(--panel-accent); }
4666
+ .ds-247420 .ds-auth-sent-title { margin: 0; font-weight: 600; }
4667
+ .ds-247420 .ds-auth-sent-sub { margin: 0; color: var(--panel-text-2); overflow-wrap: anywhere; }
4668
+ .ds-247420 .ds-auth-field { display: flex; flex-direction: column; gap: 4px; }
4669
+ .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); }
4670
+ .ds-247420 .ds-auth-row-between { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
4671
+ .ds-247420 .ds-auth-remember { display: flex; align-items: center; gap: 6px; cursor: pointer; }
4672
+ .ds-247420 .ds-auth-remember-text { color: var(--panel-text-2); font-size: 13px; }
4673
+ .ds-247420 .ds-auth-forgot { font-size: 13px; }
4674
+ .ds-247420 .ds-auth-error { padding: 8px 10px; background: var(--panel-1); border-radius: 8px; color: var(--danger); font-size: 13px; overflow-wrap: anywhere; }
4675
+ .ds-247420 .ds-auth-divider { display: flex; align-items: center; gap: 10px; margin: 6px 0; color: var(--panel-text-3); font-size: 12px; }
4676
+ .ds-247420 .ds-auth-divider-line { flex: 1; height: 1px; background: var(--panel-2); }
4677
+ .ds-247420 .ds-auth-providers { display: flex; gap: 8px; flex-wrap: wrap; }
4678
+ .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; }
4679
+ .ds-247420 .ds-auth-provider-btn--loading { opacity: 0.7; pointer-events: none; }
4680
+ .ds-247420 .ds-auth-provider-glyph { font-family: var(--ff-mono); color: var(--panel-text-3); display: inline-flex; }
4681
+ .ds-247420 .ds-auth-modes { display: flex; justify-content: center; gap: 14px; margin-top: 8px; font-size: 13px; flex-wrap: wrap; }
4682
+ .ds-247420 .ds-auth-mode-link { color: var(--panel-text-3); text-decoration: none; }
4683
+ .ds-247420 .ds-auth-mode-link--active { color: var(--panel-text); text-decoration: underline; }
4684
+ .ds-247420 .ds-auth-fineprint { text-align: center; font-size: 12px; color: var(--panel-text-3); margin: 6px 0; }
4685
+
4686
+ /* == appended: gallery-misc kit cleanup == */
4687
+ /* --- shared helpers (converted from inline styles) --- */
4688
+ .ds-247420 .ds-m0 { margin: 0; }
4689
+ .ds-247420 .ds-text-2 { color: var(--panel-text-2); }
4690
+ .ds-247420 .ds-text-3 { color: var(--panel-text-3); }
4691
+ .ds-247420 .ds-kit-head { display: flex; align-items: center; justify-content: space-between; gap: clamp(8px, 2vw, 16px); flex-wrap: wrap; }
4692
+
4693
+ /* --- gallery kit --- */
4694
+ .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; }
4695
+ .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; }
4696
+ .ds-247420 .ds-tile-glyph { font-family: var(--ff-mono); color: var(--panel-text-3); }
4697
+ .ds-247420 .ds-tile-label { color: var(--panel-text); overflow-wrap: anywhere; }
4698
+ .ds-247420 .ds-gal-swatch { height: 64px; border-radius: 8px; background: var(--swatch, var(--panel-1)); }
4699
+ .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; }
4700
+ .ds-247420 .ds-gal-swatch-name { color: var(--panel-text); }
4701
+ .ds-247420 .ds-gal-swatch-hint { color: var(--panel-text-3); overflow-wrap: anywhere; }
4702
+ .ds-247420 .ds-lightbox-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
4703
+ .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); }
4704
+
4705
+ /* --- error_404 kit --- */
4706
+ .ds-247420 .ds-err-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-top: 6px; }
4707
+ .ds-247420 .ds-err-chips { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; margin-top: 4px; }
4708
+
4709
+ /* == appended: terminal-capp kit cleanup == */
4710
+ /* --- terminal kit ------------------------------------------ */
4711
+ .ds-247420 .ds-section-pad-sm { padding: 8px; }
4712
+ .ds-247420 .ds-kit-head-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
4713
+ .ds-247420 .ds-cli-cmt .cmd { color: var(--fg-3); }
4714
+ .ds-247420 .ds-cli-out .cmd { color: var(--fg-2); }
4715
+ .ds-247420 .ds-cli-ok .prompt, .ds-247420 .ds-cli-ok .cmd { color: var(--accent-ink); }
4716
+ .ds-247420 .ds-cli-warn .prompt, .ds-247420 .ds-cli-warn .cmd { color: var(--mascot); }
4717
+ .ds-247420 .ds-cli-log .prompt { color: var(--fg-3); }
4718
+ .ds-247420 .ds-cli-log .cmd { color: var(--fg-2); font-family: var(--ff-mono); }
4719
+ .ds-247420 .ds-term-body { padding: 14px 18px; display: flex; flex-direction: column; gap: 4px; background: var(--bg-2); border-radius: 10px; }
4720
+ .ds-247420 .ds-term-body--tall { min-height: 280px; }
4721
+ .ds-247420 .ds-term-input-row { margin-top: 6px; }
4722
+ .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); }
4723
+ /* full-viewport render root (community-app) */
4724
+ .ds-247420 .ds-root-viewport { height: 100vh; height: 100dvh; }
4725
+
4726
+ /* --- chat kit: widescreen detail pane -----------------------
4727
+ .chat itself stays single-column (shared component, untouched) and
4728
+ stretches full-width on ultrawide via the existing .app-main > .chat
4729
+ max-width:none rule above (~L380) — that's fine for a bare thread, but
4730
+ it leaves a lone thread column growing to 1400px+ with no other use of
4731
+ the extra width. This wrapper adds a persistent "thread info" rail once
4732
+ there is room to spare, instead of just widening the message column. */
4733
+ .ds-247420 .ds-chat-layout { display: flex; flex-direction: column; flex: 1; min-height: 0; gap: var(--space-3); }
4734
+ .ds-247420 .ds-chat-layout > .chat { min-width: 0; }
4735
+ .ds-247420 .ds-chat-detail { display: none; }
4736
+ @media (min-width: 1100px) {
4737
+ .ds-247420 .ds-chat-layout { display: grid; grid-template-columns: minmax(0, 1fr) 280px; align-items: start; gap: var(--space-4); }
4738
+ .ds-247420 .ds-chat-detail { display: block; position: sticky; top: 0; }
4739
+ }
4200
4740
 
4201
4741
  /* community.css */
4202
4742
  /* ============================================================
@@ -4211,8 +4751,13 @@
4211
4751
  .ds-247420 .cm-shell {
4212
4752
  display: flex;
4213
4753
  height: 100vh;
4754
+ height: 100dvh;
4214
4755
  width: 100%;
4215
4756
  overflow: hidden;
4757
+ /* Notched devices: keep the rail and bottom chrome out of the unsafe zones. */
4758
+ padding-bottom: env(safe-area-inset-bottom);
4759
+ padding-left: env(safe-area-inset-left);
4760
+ padding-right: env(safe-area-inset-right);
4216
4761
  background: var(--bg);
4217
4762
  color: var(--fg);
4218
4763
  font-family: var(--ff-body);
@@ -4999,7 +5544,7 @@
4999
5544
  scrollbar-width: thin;
5000
5545
  scrollbar-color: color-mix(in oklab, var(--fg) 18%, transparent) transparent;
5001
5546
  transition: width var(--dur-base) var(--ease), flex-basis var(--dur-base) var(--ease);
5002
- will-change: width, flex-basis, opacity, transform; contain: layout style;
5547
+ contain: layout style;
5003
5548
  }
5004
5549
  .ds-247420 .cm-member-list:not(.open) {
5005
5550
  width: 0;
@@ -5144,7 +5689,7 @@
5144
5689
  /* ============================================================
5145
5690
  Responsive — collapse sidebars on narrow viewports
5146
5691
  ============================================================ */
5147
- @media (max-width: 768px) {
5692
+ @media (max-width: 900px) {
5148
5693
  .ds-247420 .cm-channel-sidebar {
5149
5694
  position: absolute;
5150
5695
  z-index: 20;
@@ -5171,6 +5716,21 @@
5171
5716
  .ds-247420 .cm-chat-header-topic { display: none; }
5172
5717
  }
5173
5718
 
5719
+ /* Drawer scrim — dims the chat while a drawer overlays it on narrow screens.
5720
+ Visual affordance only (pointer-events: none): tap-to-close needs a real
5721
+ element + handler in CommunityShell, which lives outside this stylesheet. */
5722
+ @media (max-width: 900px) {
5723
+ .ds-247420 .cm-shell:has(.cm-channel-sidebar.open) .cm-main::before,
5724
+ .ds-247420 .cm-shell:has(.cm-member-list.open) .cm-main::before {
5725
+ content: '';
5726
+ position: absolute;
5727
+ inset: 0;
5728
+ z-index: 15;
5729
+ background: color-mix(in oklab, var(--ink) 40%, transparent);
5730
+ pointer-events: none;
5731
+ }
5732
+ }
5733
+
5174
5734
  @media (max-width: 480px) {
5175
5735
  .ds-247420 .cm-server-rail {
5176
5736
  flex: 0 0 56px;
@@ -5183,22 +5743,12 @@
5183
5743
  height: 44px;
5184
5744
  padding: 4px;
5185
5745
  }
5186
- .ds-247420 .cm-channel-sidebar {
5187
- left: 56px;
5188
- width: 80vw;
5189
- max-width: 200px;
5190
- }
5746
+ .ds-247420 .cm-channel-sidebar,
5191
5747
  .ds-247420 .cm-channel-sidebar.open {
5748
+ left: 56px;
5192
5749
  width: 80vw;
5193
- max-width: 200px;
5194
- }
5195
-
5196
- /* Mobile touch target fixes for icon buttons */
5197
- .ds-247420 .cm-cat-add,
5198
- .ds-247420 .cm-ch-action-btn {
5199
- width: 44px;
5200
- height: 44px;
5201
- padding: 8px;
5750
+ /* Use the width beside the 56px rail, not a 200px sliver. */
5751
+ max-width: min(320px, calc(100vw - 56px));
5202
5752
  }
5203
5753
  .ds-247420 .cm-ch-icon {
5204
5754
  flex: 0 0 24px;
@@ -5207,6 +5757,44 @@
5207
5757
  }
5208
5758
  }
5209
5759
 
5760
+ /* Touch target floors — applies on any coarse-pointer device (phones AND
5761
+ touch tablets/laptops), not just narrow viewports. */
5762
+ @media (pointer: coarse) {
5763
+ .ds-247420 .cm-channel-item,
5764
+ .ds-247420 .cm-member-item { min-height: 44px; }
5765
+ .ds-247420 .cm-cat-add,
5766
+ .ds-247420 .cm-ch-action-btn,
5767
+ .ds-247420 .cm-user-btn,
5768
+ .ds-247420 .cm-vs-btn,
5769
+ .ds-247420 .cm-tp-new,
5770
+ .ds-247420 .cm-tp-close,
5771
+ .ds-247420 .cm-rb-cancel,
5772
+ .ds-247420 .cm-mh-btn {
5773
+ min-width: 44px;
5774
+ min-height: 44px;
5775
+ }
5776
+ .ds-247420 .cm-forum-search,
5777
+ .ds-247420 .cm-forum-sort,
5778
+ .ds-247420 .cm-forum-new { min-height: 44px; }
5779
+ }
5780
+
5781
+ /* Ultrawide: clamp the message/forum/page column to a readable measure. */
5782
+ @media (min-width: 1600px) {
5783
+ .ds-247420 .cm-main > .chat,
5784
+ .ds-247420 .cm-forum-list,
5785
+ .ds-247420 .cm-page-body {
5786
+ max-width: 110ch;
5787
+ margin-inline: auto;
5788
+ width: 100%;
5789
+ }
5790
+ }
5791
+
5792
+ /* No hover on touch: hover-revealed channel actions must stay reachable. */
5793
+ @media (hover: none) {
5794
+ .ds-247420 .cm-channel-item .cm-ch-actions { opacity: 0.6; }
5795
+ .ds-247420 .cm-category-header .cm-cat-add { opacity: 0.6; }
5796
+ }
5797
+
5210
5798
  /* ---------- a11y polish: focus-visible coverage on community interactive elements ---------- */
5211
5799
  /* Every interactive surface with a :hover state must also have a :focus-visible state so
5212
5800
  keyboard users get equivalent feedback. The selectors here mirror the existing :hover rules. */
@@ -5259,8 +5847,8 @@
5259
5847
  display: flex;
5260
5848
  align-items: center;
5261
5849
  gap: var(--space-2);
5262
- height: 48px;
5263
- padding: 0 var(--space-2);
5850
+ height: calc(48px + env(safe-area-inset-top));
5851
+ padding: env(safe-area-inset-top) max(var(--space-2), env(safe-area-inset-right)) 0 max(var(--space-2), env(safe-area-inset-left));
5264
5852
  background: var(--bg-2);
5265
5853
  border-bottom: 1px solid var(--panel-3);
5266
5854
  }
@@ -5535,6 +6123,7 @@
5535
6123
  .ds-247420 .vx-modal {
5536
6124
  width: 100%; max-width: 440px;
5537
6125
  max-height: 90vh;
6126
+ max-height: 90dvh;
5538
6127
  display: flex; flex-direction: column;
5539
6128
  border-radius: var(--r-3);
5540
6129
  background: var(--bg);
@@ -5660,10 +6249,21 @@
5660
6249
  /* ThreadPanel — cm-thread-panel / cm-tp-* */
5661
6250
  .ds-247420 .cm-thread-panel {
5662
6251
  display: flex; flex-direction: column;
6252
+ flex: 0 0 300px; width: 300px; min-width: 0;
5663
6253
  height: 100%; min-height: 0;
5664
6254
  background: var(--bg-2); color: var(--fg);
5665
6255
  border-left: var(--bw-hair) solid var(--rule);
5666
6256
  }
6257
+ @media (max-width: 900px) {
6258
+ .ds-247420 .cm-thread-panel {
6259
+ position: absolute;
6260
+ z-index: 20;
6261
+ top: 0; right: 0; bottom: 0;
6262
+ height: auto;
6263
+ width: min(320px, 90vw);
6264
+ box-shadow: -2px 0 16px color-mix(in oklab, var(--ink) 30%, transparent);
6265
+ }
6266
+ }
5667
6267
  .ds-247420 .cm-tp-head {
5668
6268
  display: flex; align-items: center; justify-content: space-between;
5669
6269
  padding: var(--space-2); border-bottom: var(--bw-hair) solid var(--rule);
@@ -5677,6 +6277,7 @@
5677
6277
  .ds-247420 .cm-tp-new:hover, .ds-247420 .cm-tp-close:hover { background: var(--bg-3); color: var(--fg); }
5678
6278
  .ds-247420 .cm-tp-list { flex: 1; min-height: 0; overflow-y: auto; }
5679
6279
  .ds-247420 .cm-tp-item {
6280
+ position: relative; /* anchors .cm-tp-dot to the row, not the panel */
5680
6281
  display: flex; flex-direction: column; gap: 2px;
5681
6282
  width: 100%; text-align: left; cursor: pointer;
5682
6283
  padding: var(--space-2); border: none; background: transparent;
@@ -5686,7 +6287,7 @@
5686
6287
  .ds-247420 .cm-tp-item:hover { background: var(--bg-3); }
5687
6288
  .ds-247420 .cm-tp-item.is-active { background: var(--bg-3); box-shadow: inset 3px 0 0 var(--accent); }
5688
6289
  .ds-247420 .cm-tp-item.is-unread .cm-tp-item-title { font-weight: 700; }
5689
- .ds-247420 .cm-tp-dot { position: absolute; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
6290
+ .ds-247420 .cm-tp-dot { position: absolute; left: 4px; top: 50%; transform: translateY(-50%); width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
5690
6291
  .ds-247420 .cm-tp-item-title { font-size: var(--fs-1, 14px); }
5691
6292
  .ds-247420 .cm-tp-item-snippet { font-size: var(--fs-0, 12px); color: var(--fg-2, var(--fg)); opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
5692
6293
  .ds-247420 .cm-tp-item-meta { display: flex; gap: var(--space-2); font-size: var(--fs-micro, 11px); color: var(--fg-2, var(--fg)); opacity: .7; }
@@ -5694,7 +6295,7 @@
5694
6295
 
5695
6296
  /* ForumView — cm-forum / cm-forum-* */
5696
6297
  .ds-247420 .cm-forum { display: flex; flex-direction: column; height: 100%; min-height: 0; background: var(--bg-1, var(--bg-2)); color: var(--fg); }
5697
- .ds-247420 .cm-forum-toolbar { display: flex; gap: var(--space-2); align-items: center; padding: var(--space-2); border-bottom: var(--bw-hair) solid var(--rule); }
6298
+ .ds-247420 .cm-forum-toolbar { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; padding: var(--space-2); border-bottom: var(--bw-hair) solid var(--rule); }
5698
6299
  .ds-247420 .cm-forum-search { flex: 1; padding: var(--space-1) var(--space-2); border: var(--bw-hair) solid var(--rule-strong); border-radius: var(--r-1); background: var(--bg-3); color: var(--fg); }
5699
6300
  .ds-247420 .cm-forum-sort { padding: var(--space-1); border: var(--bw-hair) solid var(--rule-strong); border-radius: var(--r-1); background: var(--bg-3); color: var(--fg); }
5700
6301
  .ds-247420 .cm-forum-new { padding: var(--space-1) var(--space-2); border: none; border-radius: var(--r-1); background: var(--accent); color: var(--accent-fg); cursor: pointer; }
@@ -6611,6 +7212,9 @@
6611
7212
  neutral pill and from the accent-toned running pill (--success = green-2). */
6612
7213
  .ds-247420 .chat-msg .chat-tool.tool-done .chat-tool-status { color: var(--success); background: color-mix(in oklab, var(--success) 12%, transparent); }
6613
7214
  .ds-247420 .chat-tool-body { border-top: var(--bw-hair) solid var(--rule); padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
7215
+ /* details' intrinsic min-content sizing: an unbroken token in the pre must not
7216
+ widen the tool card past the bubble column. */
7217
+ .ds-247420 .chat-msg .chat-tool, .ds-247420 .chat-tool-body, .ds-247420 .chat-tool-section { min-width: 0; max-width: 100%; }
6614
7218
  .ds-247420 .chat-tool-section { display: flex; flex-direction: column; gap: var(--space-1); }
6615
7219
  .ds-247420 .chat-tool-section-label { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); font-size: var(--fs-tiny); font-weight: 600; text-transform: uppercase; letter-spacing: var(--tr-caps); color: var(--fg-3); }
6616
7220
  .ds-247420 .chat-tool-copy { position: static; opacity: 0; }
@@ -7161,6 +7765,11 @@
7161
7765
  .ds-247420 .ds-ep-ctxmenu {
7162
7766
  position: absolute;
7163
7767
  min-width: 180px;
7768
+ max-width: calc(100vw - 8px);
7769
+ max-height: calc(100vh - 8px);
7770
+ max-height: calc(100dvh - 8px);
7771
+ overflow-y: auto;
7772
+ overscroll-behavior: contain;
7164
7773
  background: var(--panel-1, var(--panel-bg));
7165
7774
  color: var(--panel-text, var(--fg-text));
7166
7775
  border: 1px solid var(--rule);
@@ -7209,7 +7818,7 @@
7209
7818
  }
7210
7819
  .ds-247420 .ds-ep-drawer.side-left { left: 0; top: 0; bottom: 0; width: 86vw; max-width: 320px; }
7211
7820
  .ds-247420 .ds-ep-drawer.side-right { right: 0; top: 0; bottom: 0; width: 86vw; max-width: 320px; }
7212
- .ds-247420 .ds-ep-drawer.side-bottom { left: 0; right: 0; bottom: 0; max-height: 80vh; border-top-left-radius: 12px; border-top-right-radius: 12px; }
7821
+ .ds-247420 .ds-ep-drawer.side-bottom { left: 0; right: 0; bottom: 0; max-height: 80vh; max-height: 80dvh; border-top-left-radius: 12px; border-top-right-radius: 12px; }
7213
7822
  @media (min-width: 768px) {
7214
7823
  .ds-247420 .ds-ep-drawer.side-left, .ds-247420 .ds-ep-drawer.side-right { width: 360px; max-width: 360px; }
7215
7824
  }
@@ -7221,7 +7830,7 @@
7221
7830
  position: fixed; inset: 0; z-index: 9500;
7222
7831
  background: var(--scrim-strong);
7223
7832
  display: flex; align-items: center; justify-content: center;
7224
- padding: 16px;
7833
+ 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));
7225
7834
  }
7226
7835
  .ds-247420 .ds-ep-dialog {
7227
7836
  background: var(--panel-1, var(--panel-bg));
@@ -7230,7 +7839,9 @@
7230
7839
  border-radius: var(--r-2, 10px);
7231
7840
  box-shadow: var(--shadow-overlay);
7232
7841
  min-width: 280px; max-width: min(560px, 100%);
7233
- max-height: 90vh; overflow: auto;
7842
+ max-height: 90vh;
7843
+ max-height: min(90dvh, calc(100dvh - 32px));
7844
+ overflow: auto;
7234
7845
  display: flex; flex-direction: column;
7235
7846
  outline: none;
7236
7847
  }
@@ -7506,6 +8117,11 @@
7506
8117
  padding: 0;
7507
8118
  outline: none;
7508
8119
  min-width: 160px;
8120
+ max-width: calc(100vw - 8px);
8121
+ max-height: calc(100vh - 8px);
8122
+ max-height: calc(100dvh - 8px);
8123
+ overflow-y: auto;
8124
+ overscroll-behavior: contain;
7509
8125
  }
7510
8126
  @media (prefers-reduced-motion: no-preference) {
7511
8127
  .ds-247420 .ds-popover { transition: opacity 140ms ease, transform 140ms ease; }
@@ -7979,6 +8595,7 @@
7979
8595
  display: flex;
7980
8596
  flex-direction: column;
7981
8597
  height: 100vh;
8598
+ height: 100dvh;
7982
8599
  min-height: 0;
7983
8600
  overflow: hidden;
7984
8601
  }
@@ -8080,6 +8697,40 @@
8080
8697
  align-content: start;
8081
8698
  }
8082
8699
 
8700
+ /* ============================================================
8701
+ Responsive — collapse the server+channel rail on narrow viewports.
8702
+ community-app builds its own hand-rolled .ca-app/.app-body/.ca-rail tree
8703
+ (not AppShell()), so it does not inherit AppShell's @container drawer CSS
8704
+ (keyed off .app/.app-side-shell, which .ca-app/.ca-rail never establish).
8705
+ Mirrors the .cm-channel-sidebar off-canvas idiom in community.css 1:1: same
8706
+ breakpoint, same translateX(-110%) + .open reveal, same :has() scrim — so
8707
+ the .ca-rail drawer driven by MobileHeader's hamburger (mobileMenuOpen in
8708
+ the adapter snapshot) behaves identically to the community kit's sidebar.
8709
+ ============================================================ */
8710
+ @media (max-width: 900px) {
8711
+ .ds-247420.ds-247420 .ca-rail {
8712
+ position: absolute;
8713
+ z-index: 20;
8714
+ top: 0; left: 0; bottom: 0;
8715
+ width: 240px; min-width: 240px;
8716
+ transform: translateX(-110%);
8717
+ transition: transform var(--dur-base, 240ms) var(--ease, ease);
8718
+ box-shadow: 2px 0 16px color-mix(in oklab, var(--ink, #000) 30%, transparent);
8719
+ }
8720
+ .ds-247420.ds-247420 .ca-rail.open { transform: translateX(0); }
8721
+ .ds-247420.ds-247420 .ca-app:has(.ca-rail.open) .app-main {
8722
+ position: relative;
8723
+ }
8724
+ .ds-247420.ds-247420 .ca-app:has(.ca-rail.open) .app-main::before {
8725
+ content: '';
8726
+ position: absolute;
8727
+ inset: 0;
8728
+ z-index: 15;
8729
+ background: color-mix(in oklab, var(--ink, #000) 40%, transparent);
8730
+ pointer-events: none;
8731
+ }
8732
+ }
8733
+
8083
8734
  /* app-surfaces.css */
8084
8735
  /* app-surfaces.css — agentgui application-surface styling.
8085
8736
  *
@@ -8304,6 +8955,11 @@
8304
8955
  .ds-247420 .app, .ds-247420 .app-main, .ds-247420 .panel, .ds-247420 .chat, .ds-247420 .chat-thread {
8305
8956
  background: var(--paper) !important; color: var(--ink) !important; box-shadow: none !important;
8306
8957
  }
8958
+ /* Community surface: unclamp the fixed-height shell and hide the chrome so a
8959
+ transcript prints as flowing pages instead of one clipped viewport. */
8960
+ .ds-247420 .cm-shell { height: auto; overflow: visible; display: block; }
8961
+ .ds-247420 .cm-server-rail, .ds-247420 .cm-channel-sidebar, .ds-247420 .cm-member-list, .ds-247420 .cm-mobile-header, .ds-247420 .cm-voice-strip { display: none !important; }
8962
+ .ds-247420 .cm-main, .ds-247420 .cm-channel-list { overflow: visible; height: auto; }
8307
8963
  }
8308
8964
 
8309
8965
  /* gm-prose.css */
@@ -8355,6 +9011,7 @@
8355
9011
  top: 24px;
8356
9012
  align-self: start;
8357
9013
  max-height: calc(100vh - 48px);
9014
+ max-height: calc(100dvh - 48px);
8358
9015
  overflow-y: auto;
8359
9016
  overscroll-behavior: contain;
8360
9017
  margin: 0;
@@ -8621,8 +9278,9 @@
8621
9278
  }
8622
9279
  .ds-247420 .sp-hud-ammo {
8623
9280
  position: fixed;
8624
- bottom: 50px;
8625
- right: 20px;
9281
+ /* Fixed chrome clears notch/home-indicator on cutout devices. */
9282
+ bottom: calc(50px + env(safe-area-inset-bottom, 0px));
9283
+ right: calc(20px + env(safe-area-inset-right, 0px));
8626
9284
  font-size: 24px;
8627
9285
  font-weight: bold;
8628
9286
  color: var(--fg);
@@ -8631,7 +9289,7 @@
8631
9289
  .ds-247420 .sp-hud-ammo-reloading { color: var(--warn); }
8632
9290
  .ds-247420 .sp-hud-health {
8633
9291
  position: fixed;
8634
- bottom: 20px;
9292
+ bottom: calc(20px + env(safe-area-inset-bottom, 0px));
8635
9293
  left: 50%;
8636
9294
  transform: translateX(-50%);
8637
9295
  width: 200px;
@@ -8658,7 +9316,7 @@
8658
9316
  .ds-247420 .sp-hud-boost {
8659
9317
  position: fixed;
8660
9318
  top: 80px;
8661
- right: 20px;
9319
+ right: calc(20px + env(safe-area-inset-right, 0px));
8662
9320
  padding: 8px 16px;
8663
9321
  background: var(--accent);
8664
9322
  color: var(--accent-fg);
@@ -8691,6 +9349,11 @@
8691
9349
  border: 1px solid var(--bw-rule, var(--rule));
8692
9350
  border-radius: var(--r-2, 10px);
8693
9351
  color: var(--fg);
9352
+ /* Short landscape phones: keep lower controls reachable inside the card. */
9353
+ max-height: calc(100vh - 32px);
9354
+ max-height: calc(100dvh - 32px);
9355
+ overflow-y: auto;
9356
+ overscroll-behavior: contain;
8694
9357
  }
8695
9358
  .ds-247420 .sp-lobby-title {
8696
9359
  margin: 0;