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/app-shell.css CHANGED
@@ -1,8 +1,9 @@
1
1
  /* ============================================================
2
2
  247420 design system — component sheet
3
- "Acid Editorial": Space Grotesk display + Inter body + JetBrains code.
4
- Confident hierarchy, asymmetric grid tension, print texture over glow,
5
- one electric lead accent. Indicator rails over hairlines.
3
+ "Acid Editorial": Bricolage Grotesque display + Hanken Grotesk body +
4
+ JetBrains code. Confident hierarchy, asymmetric grid tension, print
5
+ texture over glow, one electric lead accent. Indicator rails over
6
+ hairlines.
6
7
  ============================================================ */
7
8
 
8
9
  /* ============================================================
@@ -371,17 +372,31 @@ body.canvas-host { background: transparent !important; }
371
372
  .app-main > .chat,
372
373
  .app-main > .chat-area,
373
374
  .app-main > .ds-file-stage,
375
+ .app-main > .ds-files-stack,
374
376
  .app-main > .grow { flex: 1 1 auto; min-height: 0; }
375
377
  .app-main.narrow { max-width: var(--measure-narrow); margin: 0 auto; }
376
378
 
377
379
  @media (min-width: 1400px) {
378
- .app { max-width: 1400px; margin-left: auto; margin-right: auto; }
380
+ /* Fluid ceiling, not a hard stop: scales from 1400px up to 1920px across the
381
+ 1400-2200px viewport band (matches .ws-shell's 1920px ultrawide cap below)
382
+ instead of freezing at 1400px and leaving >1000px dead margin on a 2560px+
383
+ display. Row/prose measure caps (--measure-wide etc.) still own line-length
384
+ readability, so widening the shell itself does not create unreadable rows. */
385
+ .app { max-width: clamp(1400px, 92vw, 1920px); margin-left: auto; margin-right: auto; }
379
386
  .app-main .chat,
380
387
  .app-main > .chat-area,
381
388
  .app-main > .main-content { max-width: none; margin: 0; width: 100%; }
382
389
  /* Status bar inherits the .app max-width cap above and stretches edge-to-edge
383
390
  within it; no separate width constraint (which previously narrowed it). */
384
391
  .app-status { width: 100%; }
392
+ /* Cap row text measure inside the wide capped main (ultrawide readability). */
393
+ .row .title, .row .sub { max-width: var(--measure-wide); }
394
+ }
395
+ /* Beyond 1920px the shell itself stops growing (matches .ws-shell's own cap) —
396
+ extra space becomes page margin rather than stretching sidebar/content grid
397
+ tracks to distances a pointer/eye shouldn't have to travel. */
398
+ @media (min-width: 2200px) {
399
+ .app { max-width: 1920px; }
385
400
  }
386
401
 
387
402
  .app-status {
@@ -685,14 +700,16 @@ a.row { text-decoration: none; }
685
700
  padding: var(--space-9) 0 var(--space-8);
686
701
  display: grid; gap: var(--space-5) var(--space-6);
687
702
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
688
- grid-template-areas: 'title title' 'body actions';
703
+ grid-template-areas: 'title title' 'body actions' 'badge badge';
689
704
  align-items: end;
690
705
  max-width: var(--measure-wide);
691
706
  }
692
707
  .ds-hero-head { grid-area: title; display: grid; gap: var(--space-3); }
693
708
  .ds-hero-body { grid-area: body; }
694
709
  .ds-hero-actions { grid-area: actions; }
695
- .ds-hero-badge { grid-area: actions; }
710
+ /* Badge gets its own row — sharing 'actions' overlapped it onto the CTAs
711
+ whenever a caller passes both actions and badge. */
712
+ .ds-hero-badge { grid-area: badge; }
696
713
  .ds-hero-title {
697
714
  font-family: var(--ff-display); font-weight: 700;
698
715
  font-size: clamp(40px, 9cqi, 116px);
@@ -707,10 +724,13 @@ a.row { text-decoration: none; }
707
724
  /* The lead phrase in the title — printed in the electric lead, not glowing. */
708
725
  .ds-hero-accent { color: var(--accent-ink); font-weight: 700; }
709
726
  .ds-hero-actions { display: flex; gap: var(--space-2, 10px); flex-wrap: wrap; align-self: end; }
710
- @media (max-width: 900px) {
727
+ /* Container-queried (the whole shell is; a 500px pane on a wide viewport
728
+ would keep the two-column grid under a width @media). Left-aligned stack —
729
+ no centering — preserving the asymmetric intent. */
730
+ @container (max-width: 900px) {
711
731
  .ds-hero {
712
732
  grid-template-columns: minmax(0, 1fr);
713
- grid-template-areas: 'title' 'body' 'actions';
733
+ grid-template-areas: 'title' 'body' 'actions' 'badge';
714
734
  align-items: start;
715
735
  padding: var(--space-7) 0 var(--space-6);
716
736
  }
@@ -778,13 +798,21 @@ a.row { text-decoration: none; }
778
798
  }
779
799
  .ds-marquee-item { display: inline-flex; align-items: center; gap: var(--space-5); }
780
800
  .ds-marquee-sep { color: var(--accent-ink); }
781
- .ds-marquee:hover .ds-marquee-track { animation-play-state: paused; }
801
+ .ds-marquee:hover .ds-marquee-track,
802
+ .ds-marquee:focus-within .ds-marquee-track,
803
+ .ds-marquee:active .ds-marquee-track { animation-play-state: paused; }
782
804
  @keyframes ds-marquee-run {
783
805
  from { transform: translateX(0); }
784
806
  to { transform: translateX(-50%); }
785
807
  }
808
+ /* Touch has no hover-pause; slow the ticker so it burns less attention. */
809
+ @media (hover: none), (pointer: coarse) {
810
+ .ds-marquee-track { animation-duration: 40s; }
811
+ }
786
812
  @media (prefers-reduced-motion: reduce) {
787
- .ds-marquee-track { animation: none; }
813
+ /* Static: wrap to a readable strip instead of a frozen half-offscreen run. */
814
+ .ds-marquee-track { animation: none; flex-wrap: wrap; white-space: normal; }
815
+ .ds-marquee-run-b { display: none; }
788
816
  }
789
817
 
790
818
  /* ============================================================
@@ -792,6 +820,7 @@ a.row { text-decoration: none; }
792
820
  ============================================================ */
793
821
  .cli {
794
822
  display: flex; align-items: center; gap: 14px;
823
+ overflow-x: auto;
795
824
  padding: 20px 24px;
796
825
  background: var(--ink); color: var(--paper);
797
826
  border-radius: var(--r-3);
@@ -845,6 +874,15 @@ table.kv td:first-child {
845
874
  }
846
875
  table.kv td:last-child {
847
876
  font-weight: 600;
877
+ overflow-wrap: anywhere; min-width: 0;
878
+ }
879
+ /* Tiny screens: stack the key over the value instead of squeezing a 14ch
880
+ label column beside long unbroken values (URLs, hashes). */
881
+ @media (max-width: 400px) {
882
+ table.kv td { display: block; width: auto; padding: 4px 0; }
883
+ table.kv td:first-child { padding-top: 8px; }
884
+ table.kv tr + tr td { border-top: 0; }
885
+ table.kv tr + tr td:first-child { border-top: 1px solid var(--rule); }
848
886
  }
849
887
 
850
888
  /* ============================================================
@@ -1040,6 +1078,10 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1040
1078
  }
1041
1079
  .row .sub { grid-column: 1 / -1; order: 3; }
1042
1080
  .row .title { font-size: var(--fs-sm); }
1081
+ /* Changelog carries 3 children: give date+ver line one, message wraps below
1082
+ (the generic 2-col .row override staggers it into an implicit row). */
1083
+ .ds-changelog-row { grid-template-columns: minmax(70px, 10ch) minmax(0, 1fr) !important; }
1084
+ .ds-changelog-row .title { grid-column: 1 / -1; }
1043
1085
 
1044
1086
  /* Buttons */
1045
1087
  .btn, .btn-primary, .btn-ghost {
@@ -1083,7 +1125,9 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1083
1125
  gap: var(--space-2);
1084
1126
  }
1085
1127
  .kpi-card { padding: var(--space-3); }
1086
- .kpi-card .num { font-size: clamp(22px, 5vw, 32px); }
1128
+ /* Container-relative like the base rule (5vw sized against the viewport and
1129
+ jumped across the breakpoint). */
1130
+ .kpi-card .num { font-size: clamp(22px, 8cqi, 32px); }
1087
1131
 
1088
1132
  /* Empty State */
1089
1133
  .empty { padding: var(--space-5); font-size: var(--fs-xs); }
@@ -1117,10 +1161,11 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1117
1161
  @container (max-width: 760px) {
1118
1162
  .app-body { grid-template-columns: 1fr !important; }
1119
1163
  .app-side-shell { border-right: 0; border-bottom: 1px solid var(--rule); }
1120
- .app-topbar { grid-template-columns: 1fr auto; }
1121
1164
  .app-topbar nav { font-size: var(--fs-xs); gap: 14px; }
1122
1165
  .row { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 4px !important; }
1123
1166
  .row .sub { grid-column: 1 / -1; order: 3; }
1167
+ .ds-changelog-row { grid-template-columns: minmax(70px, 10ch) minmax(0, 1fr) !important; }
1168
+ .ds-changelog-row .title { grid-column: 1 / -1; }
1124
1169
  }
1125
1170
 
1126
1171
  /* --------------------------------------------------------------------
@@ -1135,9 +1180,8 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1135
1180
  min-height: 44px;
1136
1181
  }
1137
1182
 
1138
- /* Topbar Navigation */
1183
+ /* Topbar Navigation (flex container — no grid-template here) */
1139
1184
  .app-topbar {
1140
- grid-template-columns: auto 1fr auto;
1141
1185
  gap: var(--space-3); padding: 12px var(--space-4);
1142
1186
  }
1143
1187
  .app-topbar nav {
@@ -1216,6 +1260,8 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1216
1260
  gap: var(--space-2);
1217
1261
  }
1218
1262
  .row .code { display: none; }
1263
+ /* Changelog's date lives in span.code — hiding it is data loss, not reflow. */
1264
+ .ds-changelog-row .code { display: inline; font-size: var(--fs-micro); }
1219
1265
  .row .sub { grid-column: 1 / -1; }
1220
1266
  }
1221
1267
 
@@ -1553,8 +1599,17 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1553
1599
 
1554
1600
  /* Full-width files stack: the stage's space-3 vertical beat without its
1555
1601
  920px cap/auto-margins, so the roots / toolbar / bulkbar / uploads / grid
1556
- bands keep one consistent rhythm instead of touching edge-to-edge. */
1557
- .ds-files-stack { display: flex; flex-direction: column; gap: var(--space-3); min-height: 0; }
1602
+ bands keep one consistent rhythm instead of touching edge-to-edge. Carries
1603
+ the same side/bottom padding as .ds-file-stage (top collapses the same way
1604
+ when mounted directly under .app-main, which already supplies top padding)
1605
+ so switching a consumer from the capped stage to this full-width stack is a
1606
+ pure width change, not a spacing regression. */
1607
+ .ds-files-stack {
1608
+ display: flex; flex-direction: column; gap: var(--space-3); min-height: 0;
1609
+ padding: 0 var(--space-3) var(--space-4);
1610
+ }
1611
+ .app-main > div > .ds-files-stack,
1612
+ .app-main .ds-files-stack { padding-top: 0; }
1558
1613
 
1559
1614
  /* Breadcrumb path */
1560
1615
  .ds-crumb-path {
@@ -1566,6 +1621,10 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1566
1621
  padding: 4px 8px; border-radius: var(--r-1);
1567
1622
  color: var(--fg-3); font-family: inherit; font-size: var(--fs-sm);
1568
1623
  transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
1624
+ /* A single long unbroken segment (hash-named dir) must never force the
1625
+ whole path past the viewport. */
1626
+ max-width: min(40vw, 220px);
1627
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
1569
1628
  }
1570
1629
  .ds-crumb-seg:hover { background: var(--bg-2); color: var(--fg); }
1571
1630
  .ds-crumb-seg.leaf { color: var(--fg); font-weight: 600; }
@@ -1662,6 +1721,14 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1662
1721
  border-radius: var(--r-3);
1663
1722
  }
1664
1723
  .ds-dropzone--wrap.dragover { animation: none; }
1724
+ /* Touch devices can never fire dragover — keep the pick-files affordance
1725
+ visible as a compact static row so upload stays reachable in wrap mode. */
1726
+ @media (hover: none) and (pointer: coarse) {
1727
+ .ds-dropzone--wrap > .ds-dropzone-inner {
1728
+ display: flex; position: static; padding: var(--space-2);
1729
+ outline: none; background: transparent;
1730
+ }
1731
+ }
1665
1732
 
1666
1733
  /* Upload progress */
1667
1734
  .ds-upload-progress { display: flex; flex-direction: column; gap: 6px; }
@@ -1690,7 +1757,12 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1690
1757
  .ds-upload-item.error .ds-upload-fill { background: var(--warn); }
1691
1758
  .ds-upload-item.error .ds-upload-pct { color: var(--warn); }
1692
1759
  /* Per-row upload recovery actions (replace / dismiss) — error rows are not dead ends. */
1693
- .ds-upload-item { grid-template-columns: minmax(0, 1fr) 120px 44px auto; }
1760
+ .ds-upload-item { grid-template-columns: minmax(0, 1fr) minmax(60px, 120px) 44px auto; }
1761
+ @media (max-width: 480px) {
1762
+ .ds-upload-item { grid-template-columns: minmax(0, 1fr) 44px; }
1763
+ .ds-upload-bar { grid-column: 1 / -1; order: 3; }
1764
+ .ds-upload-actions { grid-column: 1 / -1; justify-content: flex-end; }
1765
+ }
1694
1766
  .ds-upload-actions { display: inline-flex; gap: var(--space-1); justify-content: flex-end; }
1695
1767
  .ds-upload-act {
1696
1768
  padding: 2px 10px; min-height: 24px; cursor: pointer;
@@ -1701,6 +1773,11 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1701
1773
  .ds-upload-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
1702
1774
  @media (hover: none), (pointer: coarse) {
1703
1775
  .ds-upload-act { min-height: 44px; min-width: 44px; }
1776
+ /* 44px floor for file controls on ANY touch device, not only narrow ones
1777
+ (the width-based mobile block misses wide touch tablets). */
1778
+ .ds-file-act, .ds-file-sort-btn, .ds-crumb-seg, .ds-file-filter-input { min-height: 44px; }
1779
+ .ds-file-act { min-width: 44px; }
1780
+ .ds-file-check, .ds-file-selectall, .ds-density-btn { min-height: 44px; min-width: 44px; }
1704
1781
  }
1705
1782
 
1706
1783
  /* Empty state */
@@ -1716,7 +1793,11 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1716
1793
  .ds-modal-backdrop {
1717
1794
  position: fixed; inset: 0; z-index: var(--z-modal, 800);
1718
1795
  display: flex; align-items: center; justify-content: center;
1719
- padding: var(--space-3);
1796
+ /* Notch/home-indicator safe: near-fullscreen modals must not slide under. */
1797
+ padding: max(var(--space-3), env(safe-area-inset-top))
1798
+ max(var(--space-3), env(safe-area-inset-right))
1799
+ max(var(--space-3), env(safe-area-inset-bottom))
1800
+ max(var(--space-3), env(safe-area-inset-left));
1720
1801
  background: color-mix(in oklab, var(--ink) 55%, transparent);
1721
1802
  backdrop-filter: blur(3px);
1722
1803
  }
@@ -1726,7 +1807,9 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1726
1807
  @keyframes ds-modal-fade { from { opacity: 0; } to { opacity: 1; } }
1727
1808
  .ds-modal {
1728
1809
  display: flex; flex-direction: column;
1729
- width: 100%; max-width: 460px; max-height: calc(100vh - 2 * var(--space-4));
1810
+ width: 100%; max-width: 460px;
1811
+ max-height: calc(100vh - 2 * var(--space-4));
1812
+ max-height: calc(100dvh - 2 * var(--space-4));
1730
1813
  background: var(--bg); color: var(--fg);
1731
1814
  border: var(--bw-hair) solid var(--rule);
1732
1815
  border-radius: var(--r-3); box-shadow: var(--shadow-3);
@@ -1759,6 +1842,10 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1759
1842
  font-family: inherit; font-size: var(--fs-sm);
1760
1843
  }
1761
1844
  .ds-modal-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1845
+ /* iOS auto-zooms inputs under 16px on focus, breaking the modal layout. */
1846
+ @media (hover: none), (pointer: coarse) {
1847
+ .ds-modal-input { font-size: 16px; min-height: 44px; }
1848
+ }
1762
1849
  /* In-body modal error (role=alert): mutation failures (409/403) surface INSIDE
1763
1850
  the dialog, not behind the fixed overlay. */
1764
1851
  .ds-modal-error {
@@ -1782,10 +1869,12 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1782
1869
  .ds-preview-name {
1783
1870
  font-weight: 600; font-size: var(--fs-body);
1784
1871
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
1872
+ flex: 1 1 auto;
1785
1873
  }
1786
1874
  .ds-preview-meta {
1787
1875
  font-family: var(--ff-mono); font-size: var(--fs-xs);
1788
1876
  color: var(--fg-3); white-space: nowrap;
1877
+ flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
1789
1878
  }
1790
1879
  .ds-preview-actions { display: inline-flex; gap: 2px; margin-left: auto; }
1791
1880
  .ds-preview-body {
@@ -1794,7 +1883,9 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1794
1883
  display: flex; flex-direction: column;
1795
1884
  }
1796
1885
  .ds-preview-media {
1797
- max-width: 100%; max-height: 70vh; margin: 0 auto;
1886
+ max-width: 100%;
1887
+ max-height: 70vh; max-height: 70dvh;
1888
+ margin: 0 auto;
1798
1889
  border-radius: var(--r-2); object-fit: contain;
1799
1890
  }
1800
1891
  .ds-preview-audio { width: 100%; }
@@ -1840,10 +1931,22 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1840
1931
 
1841
1932
  /* Mobile — modals go near-fullscreen, preview media shrinks. */
1842
1933
  @media (max-width: 560px) {
1843
- .ds-modal { max-width: 100%; max-height: calc(100vh - 2 * var(--space-3)); }
1844
- .ds-modal-preview { width: 100%; height: calc(100vh - 2 * var(--space-3)); max-height: none; }
1845
- .ds-preview-media { max-height: 50vh; }
1934
+ .ds-modal {
1935
+ max-width: 100%;
1936
+ max-height: calc(100vh - 2 * var(--space-3));
1937
+ max-height: calc(100dvh - 2 * var(--space-3));
1938
+ }
1939
+ .ds-modal-preview {
1940
+ width: 100%; max-height: none;
1941
+ height: calc(100vh - 2 * var(--space-3));
1942
+ height: calc(100dvh - 2 * var(--space-3));
1943
+ }
1944
+ .ds-preview-media { max-height: 50vh; max-height: 50dvh; }
1846
1945
  .ds-file-stage { padding: var(--space-3) var(--space-2); }
1946
+ /* Preview head: let it wrap and drop the nowrap meta (duplicated in body)
1947
+ so the close button can never be pushed past the modal edge. */
1948
+ .ds-preview-head { flex-wrap: wrap; row-gap: 4px; }
1949
+ .ds-preview-meta { display: none; }
1847
1950
  }
1848
1951
 
1849
1952
  /* -- File browser UX affordances ---------------------------- */
@@ -2460,10 +2563,21 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
2460
2563
  .chat-composer textarea { padding: 10px 12px; }
2461
2564
  }
2462
2565
 
2463
- /* --- landscape orientation: reduce vertical space for composer --- */
2566
+ /* --- landscape orientation: reduce vertical space for chrome + composer --- */
2464
2567
  @media (max-height: 500px) and (orientation: landscape) {
2465
- .chat-composer { padding: 6px 0; }
2466
- .chat-composer textarea { min-height: 44px; max-height: 120px; }
2568
+ /* Keep horizontal padding: 0 put the textarea/focus ring flush on the edge. */
2569
+ .chat-composer { padding: 6px var(--space-2); }
2570
+ .chat-composer textarea { min-height: 36px; max-height: 96px; }
2571
+ .chat-composer .chat-composer-hint,
2572
+ .chat-composer .chat-composer-context { display: none; }
2573
+ /* Compact the shell chrome: ~114px of topbar+crumb+status is a third of a
2574
+ 360px-tall landscape fold. */
2575
+ :root { --app-topbar-h: 40px; --app-crumb-h: 24px; }
2576
+ .app-chrome { padding: 4px var(--pad-x); }
2577
+ .app-status { display: none; }
2578
+ .ws-crumb { min-height: 32px; }
2579
+ .ds-hero { padding: var(--space-4) 0 var(--space-3); }
2580
+ .ds-hero-title { font-size: clamp(28px, 6cqi, 56px); }
2467
2581
  }
2468
2582
 
2469
2583
  /* ============================================================
@@ -2896,6 +3010,16 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
2896
3010
  }
2897
3011
  }
2898
3012
 
3013
+ /* Touch floor also for coarse-pointer devices that report hover (hybrid
3014
+ laptops/tablets with mice) — the block above requires hover:none too. */
3015
+ @media (pointer: coarse) {
3016
+ .ds-icon-btn, .ds-icon-btn-xs, .ds-icon-btn-sm, .ds-icon-btn-base {
3017
+ min-width: 44px; min-height: 44px;
3018
+ }
3019
+ .btn, .btn-primary, .btn-ghost,
3020
+ .app-topbar nav a, .app-side a { min-height: 44px; }
3021
+ }
3022
+
2899
3023
  /* ------------------------------------------------------------
2900
3024
  Theme Transition Smoothness
2901
3025
  -------------------------------------------------------------- */
@@ -3127,16 +3251,24 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3127
3251
  .app-body.no-side { grid-template-columns: 1fr !important; }
3128
3252
  .app-side-shell {
3129
3253
  position: absolute;
3130
- left: 0; top: var(--app-topbar-h);
3131
- height: calc(100% - var(--app-topbar-h) - var(--app-status-h));
3254
+ /* Full-height overlay drawer: the merged .app-chrome wraps and its real
3255
+ height drifts from --app-topbar-h, so anchoring below it misplaces the
3256
+ drawer. Overlay the chrome instead (z above --z-header), like ws drawers. */
3257
+ left: 0; top: 0;
3258
+ height: 100%;
3132
3259
  width: 280px; max-width: 80%;
3133
3260
  transform: translateX(-100%);
3134
3261
  transition: transform var(--dur-base, 240ms) var(--ease, ease);
3135
- z-index: 50;
3262
+ /* Above the sticky chrome (z-header): scrim > chrome > content budget. */
3263
+ z-index: calc(var(--z-header, 100) + 2);
3136
3264
  background: var(--bg);
3137
3265
  border-right: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
3138
3266
  overflow-y: auto;
3267
+ overscroll-behavior: contain;
3139
3268
  }
3269
+ /* Lock the content scroller while the drawer is open so touch pans don't
3270
+ scroll the page behind the scrim. */
3271
+ .app-body.side-open .app-main { overflow: hidden; }
3140
3272
  .app-side-shell.open,
3141
3273
  .app-side.open,
3142
3274
  .app-body.side-open .app-side-shell { transform: translateX(0); }
@@ -3169,7 +3301,8 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3169
3301
  display: none;
3170
3302
  position: absolute; inset: 0;
3171
3303
  background: color-mix(in oklab, var(--bg) 60%, transparent);
3172
- z-index: 49;
3304
+ /* Above the sticky chrome so nav behind an open drawer is not clickable. */
3305
+ z-index: calc(var(--z-header, 100) + 1);
3173
3306
  }
3174
3307
  @container (max-width: 900px) {
3175
3308
  .app-body.side-open .app-side-scrim { display: block; }
@@ -3181,7 +3314,9 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3181
3314
  .app-side-toggle {
3182
3315
  display: none;
3183
3316
  position: absolute; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
3184
- z-index: 51;
3317
+ /* Above the sticky topbar/chrome (z-header) and the drawer/scrim so the
3318
+ translucent blurred chrome never paints over or intercepts the toggle. */
3319
+ z-index: calc(var(--z-header, 100) + 3);
3185
3320
  /* 44x44 minimum hit area (WCAG 2.5.5 / Apple HIG) - 36px is below the
3186
3321
  reliable-tap threshold on touch. */
3187
3322
  width: 44px; height: 44px;
@@ -3233,6 +3368,8 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3233
3368
  .app-topbar nav,
3234
3369
  .app-topbar > :last-child { display: none; }
3235
3370
  .brand { font-size: var(--fs-tiny); }
3371
+ /* Slightly narrower drawer on tiny phones; max-width:80% remains the guard. */
3372
+ .app-side-shell { width: 260px; }
3236
3373
  }
3237
3374
 
3238
3375
  /* ----------------------------------------------------------------------------
@@ -3306,6 +3443,11 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3306
3443
  @media (prefers-reduced-motion: no-preference) {
3307
3444
  .ws-shell { transition: grid-template-columns var(--dur-base) var(--ease); }
3308
3445
  }
3446
+ /* Ultrawide: cap the shell so the 1fr content track doesn't stretch to
3447
+ unreadable measures while the fixed side columns pin to their clamps. */
3448
+ @media (min-width: 1920px) {
3449
+ .ws-shell { max-width: 1920px; margin-inline: auto; }
3450
+ }
3309
3451
 
3310
3452
  /* Rail (left nav) */
3311
3453
  .ws-rail {
@@ -3341,7 +3483,7 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3341
3483
  }
3342
3484
  .ws-rail-action:hover { filter: brightness(1.08); }
3343
3485
  .ws-rail-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
3344
- .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; }
3486
+ .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; }
3345
3487
  .ws-rail-item {
3346
3488
  display: flex; align-items: center; gap: var(--space-2);
3347
3489
  width: 100%; padding: var(--space-2); min-height: 44px;
@@ -3404,6 +3546,7 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3404
3546
  min-height: 0; display: flex; flex-direction: column;
3405
3547
  background: var(--bg-2); border-left: var(--bw-hair) solid var(--bg-3);
3406
3548
  overflow: hidden; transition: width var(--dur-base) var(--ease);
3549
+ overscroll-behavior: contain;
3407
3550
  }
3408
3551
  .ws-pane-collapsed .ws-pane { width: 0; border-left: none; }
3409
3552
  .ws-pane-collapsed .ws-pane > * { display: none; }
@@ -3488,12 +3631,19 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3488
3631
  }
3489
3632
  .ws-sessions {
3490
3633
  position: fixed; inset: 0 auto 0 0;
3491
- width: min(var(--ws-sessions-w), 80vw);
3634
+ /* Immune to the desktop collapse var (--ws-sessions-w:0px persisted from
3635
+ a desktop session would open an invisible 0-width drawer). */
3636
+ width: min(max(var(--ws-sessions-w), 280px), 80vw);
3492
3637
  z-index: 42; transform: translateX(-110%);
3493
3638
  transition: transform var(--dur-base) var(--ease);
3494
3639
  border-right: var(--bw-hair) solid var(--bg-3);
3640
+ overscroll-behavior: contain;
3495
3641
  }
3496
3642
  .ws-shell.ws-sessions-open .ws-sessions { transform: translateX(0); }
3643
+ /* Drawer mode ignores the desktop collapsed state: children stay rendered
3644
+ and the border returns, so a persisted collapse can't blank the drawer. */
3645
+ .ws-shell.ws-sessions-collapsed .ws-sessions > * { display: revert; }
3646
+ .ws-shell.ws-sessions-collapsed .ws-sessions { border-right: var(--bw-hair) solid var(--bg-3); }
3497
3647
  .ws-sessions-drawer-toggle { display: inline-flex; }
3498
3648
  }
3499
3649
 
@@ -3603,6 +3753,22 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3603
3753
  .ws-crumb,
3604
3754
  .app-status { display: none; }
3605
3755
  .ws-main { overflow: visible; height: auto; }
3756
+ /* AppShell: unpin the viewport-height frame so content flows across pages,
3757
+ and drop all chrome (it prints as page furniture otherwise). */
3758
+ .app { height: auto; min-height: 0; overflow: visible; display: block; }
3759
+ .app-body { display: block; }
3760
+ .app-main { overflow: visible; height: auto; display: block; max-width: 100%; }
3761
+ .app-topbar, .app-chrome, .app-crumb, .app-side-shell, .app-side-scrim,
3762
+ .app-side-toggle, .btn-fab, .skip-link, .ds-marquee { display: none; }
3763
+ /* Modals/preview: print the content, not a blurred overlay clipped to one page. */
3764
+ .ds-modal-backdrop { position: static; background: none; backdrop-filter: none; padding: 0; }
3765
+ .ds-modal, .ds-modal-preview { max-width: 100%; max-height: none; box-shadow: none; }
3766
+ .ds-modal-body, .ds-preview-body, .ds-preview-code, .ds-preview-text { overflow: visible; }
3767
+ .ds-modal-actions, .ds-preview-actions { display: none; }
3768
+ /* Data-density: fixed-height log clips; bg-only tiles lose their boundary. */
3769
+ .ds-live-log { height: auto; max-height: none; overflow: visible; }
3770
+ .ds-stat, .kpi-card { border: 1px solid var(--rule); }
3771
+ .ds-session-row { break-inside: avoid; }
3606
3772
  }
3607
3773
 
3608
3774
  /* ============================================================
@@ -3627,15 +3793,26 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3627
3793
  }
3628
3794
  .ds-phasewalk-seg.is-reached { background: var(--success); }
3629
3795
  .ds-phasewalk-seg.is-gap { background: var(--warn); }
3796
+ /* Standalone PhaseWalk reserves headroom for the labels instead of letting
3797
+ them escape upward and overlap the element above. */
3798
+ .ds-phasewalk { padding-top: 15px; }
3630
3799
  .ds-phasewalk-lbl {
3631
3800
  position: absolute; top: -15px; left: 0;
3632
3801
  font-size: var(--fs-micro); color: var(--fg-3); white-space: nowrap;
3633
3802
  }
3803
+ /* Inline in a single-line SessionRow the labels would overlap the row above —
3804
+ segments already carry title tooltips. */
3805
+ .ds-session-row .ds-phasewalk { padding-top: 0; }
3806
+ .ds-session-row .ds-phasewalk-lbl { display: none; }
3634
3807
 
3635
3808
  /* TreeNode */
3636
3809
  .ds-tree-node {
3637
3810
  padding: 5px 10px; border-left: var(--bw-rule) solid var(--bg-3);
3638
3811
  margin: 2px 0 2px 16px; font-size: var(--fs-tiny);
3812
+ min-width: 0; overflow-wrap: anywhere;
3813
+ }
3814
+ @media (max-width: 400px) {
3815
+ .ds-tree-node { margin-left: 8px; padding-left: 8px; }
3639
3816
  }
3640
3817
  .ds-tree-node.is-phase { border-color: var(--accent); background: var(--bg-3); font-weight: 600; }
3641
3818
  .ds-tree-node.is-deviation { border-color: var(--warn); background: var(--danger-surface); color: var(--warn); }
@@ -3650,17 +3827,26 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3650
3827
  /* BarRow */
3651
3828
  .ds-bar-row { display: flex; align-items: center; gap: 8px; margin: 3px 0; font-size: var(--fs-tiny); }
3652
3829
  .ds-bar-row-label { width: 100px; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3653
- .ds-bar-bg { flex: 1; background: var(--bg-3); border-radius: 2px; height: 6px; overflow: hidden; }
3830
+ .ds-bar-bg { flex: 1; min-width: 60px; background: var(--bg-3); border-radius: 2px; height: 6px; overflow: hidden; }
3654
3831
  .ds-bar-fill { background: var(--accent); height: 100%; border-radius: 2px; }
3655
- .ds-bar-row-value { flex-shrink: 0; color: var(--fg-2); }
3832
+ .ds-bar-row-value { flex-shrink: 0; color: var(--fg-2); max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
3833
+ @media (max-width: 400px) {
3834
+ .ds-bar-row-label { width: 72px; }
3835
+ }
3656
3836
 
3657
3837
  /* StatTile / StatsGrid */
3658
- .ds-stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--space-2); }
3838
+ /* min(140px, 100%) keeps the grid from collapsing to 1 column early inside
3839
+ padded panels; the wrapper div stretches its tile to equal row height. */
3840
+ .ds-stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); gap: var(--space-2); }
3841
+ .ds-stats-grid > div { display: grid; }
3842
+ @media (max-width: 360px) {
3843
+ .ds-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-1); }
3844
+ }
3659
3845
  .ds-stats-grid-empty { padding: var(--space-3); color: var(--fg-3); font-size: var(--fs-tiny); }
3660
- .ds-stat { background: var(--bg-3); border-radius: 4px; padding: 10px 12px; }
3661
- .ds-stat-val { font-size: 22px; font-weight: 700; color: var(--accent-ink); }
3662
- .ds-stat-val.rate-big { font-size: 32px; color: var(--success); }
3663
- .ds-stat-val.err-rate { font-size: 32px; color: var(--warn); }
3846
+ .ds-stat { min-width: 0; background: var(--bg-3); border-radius: 4px; padding: 10px 12px; }
3847
+ .ds-stat-val { font-size: clamp(18px, 5cqi, 22px); font-weight: 700; color: var(--accent-ink); overflow-wrap: anywhere; }
3848
+ .ds-stat-val.rate-big { font-size: clamp(24px, 7cqi, 32px); color: var(--success); }
3849
+ .ds-stat-val.err-rate { font-size: clamp(24px, 7cqi, 32px); color: var(--warn); }
3664
3850
  .ds-stat-lbl { font-size: var(--fs-micro); color: var(--fg-3); margin-top: 2px; }
3665
3851
 
3666
3852
  /* SubGrid */
@@ -3677,14 +3863,22 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3677
3863
  /* SessionRow */
3678
3864
  .ds-session-row {
3679
3865
  display: flex; align-items: center; gap: 8px; padding: 6px 10px;
3866
+ flex-wrap: wrap; min-width: 0;
3680
3867
  border-bottom: var(--bw-hair) solid var(--bg-3); cursor: pointer;
3681
3868
  }
3682
3869
  .ds-session-row:hover { background: var(--bg-3); }
3683
3870
  .ds-session-row-id {
3684
3871
  font-family: var(--ff-mono); font-size: var(--fs-micro); color: var(--accent-ink);
3685
- width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
3872
+ flex: 0 1 160px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
3873
+ }
3874
+ .ds-session-row-counts {
3875
+ font-size: var(--fs-micro); color: var(--fg-3);
3876
+ flex: 1 1 200px; min-width: 0;
3877
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
3878
+ }
3879
+ @media (max-width: 640px) {
3880
+ .ds-session-row-span { flex-basis: 100%; }
3686
3881
  }
3687
- .ds-session-row-counts { font-size: var(--fs-micro); color: var(--fg-3); width: 280px; }
3688
3882
  .ds-session-row-devcnt { color: var(--warn); font-weight: 600; }
3689
3883
  .ds-session-row-span { font-size: var(--fs-micro); color: var(--fg-3); }
3690
3884
 
@@ -3695,14 +3889,360 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
3695
3889
  }
3696
3890
  .ds-dev-row strong { color: var(--warn); }
3697
3891
 
3698
- /* LiveLog */
3892
+ /* LiveLog — natural height with a viewport-tracking cap (dvh follows mobile
3893
+ URL-bar chrome; min-height keeps short-landscape from going near-zero). */
3699
3894
  .ds-live-log {
3700
- height: calc(100vh - 200px); overflow-y: auto;
3895
+ height: auto;
3896
+ max-height: calc(100vh - 200px);
3897
+ max-height: calc(100dvh - 200px);
3898
+ min-height: 160px;
3899
+ overflow-y: auto; overflow-x: hidden;
3701
3900
  font-family: var(--ff-mono); font-size: var(--fs-micro); line-height: 1.5;
3702
3901
  }
3703
- .ds-live-log-empty { height: auto; padding: var(--space-3); color: var(--fg-3); }
3704
- .ds-live-log-entry { padding: 2px 8px; border-bottom: var(--bw-hair) solid var(--bg-3); }
3902
+ /* Embedded in a WM window the viewport calc is meaningless — fill the container. */
3903
+ .fd-root .ds-live-log { height: 100%; max-height: none; min-height: 0; flex: 1 1 auto; }
3904
+ .ds-live-log-empty { height: auto; min-height: 0; padding: var(--space-3); color: var(--fg-3); }
3905
+ .ds-live-log-entry { padding: 2px 8px; border-bottom: var(--bw-hair) solid var(--bg-3); overflow-wrap: anywhere; }
3705
3906
  .ds-live-log-entry:hover { background: var(--bg-3); }
3706
3907
  .ds-live-log-ts { margin-right: 6px; color: var(--fg-3); }
3707
3908
  .ds-live-log-subtag { margin-right: 6px; padding: 0 5px; border-radius: 2px; font-size: var(--fs-micro); }
3708
- .ds-live-log-preview { margin-left: 6px; color: var(--fg-3); }
3909
+ .ds-live-log-preview { margin-left: 6px; color: var(--fg-3); word-break: break-word; }
3910
+
3911
+ /* Touch floors for the dense controls (not covered by the mobile width blocks). */
3912
+ @media (pointer: coarse) {
3913
+ .ds-sub-btn { min-height: 44px; }
3914
+ .ds-session-row { min-height: 44px; }
3915
+ .ds-live-log-entry { padding-block: 6px; }
3916
+ }
3917
+
3918
+
3919
+ /* == appended: popovers-files == */
3920
+ /* FilePreviewMedia controls row — spacing + coarse-pointer tap floor */
3921
+ .ds-preview-media-controls {
3922
+ display: flex;
3923
+ align-items: center;
3924
+ gap: var(--space-2);
3925
+ flex-wrap: wrap;
3926
+ }
3927
+ @media (hover: none), (pointer: coarse) {
3928
+ .ds-preview-media-controls .chat-code-copy,
3929
+ .chat-code-copy-head {
3930
+ min-height: 44px;
3931
+ min-width: 44px;
3932
+ }
3933
+ }
3934
+
3935
+ /* == appended: ui-kits == */
3936
+ /* ============================================================
3937
+ ui_kit responsive helpers (kits-grids sweep) */
3938
+ .ds-section-pad { padding: clamp(6px, 1.2vw, 16px); }
3939
+ .ds-panel-gap { margin: var(--space-2) 0; }
3940
+ .ds-panel-duo { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); margin: var(--space-2) 0; }
3941
+ @media (max-width: 760px) {
3942
+ .ds-panel-duo { grid-template-columns: 1fr; }
3943
+ }
3944
+ /* wide dense rows/tables scroll inside their panel, never the page */
3945
+ .ds-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
3946
+
3947
+ /* --- slide deck ------------------------------------------- */
3948
+ .ds-deck-stage {
3949
+ aspect-ratio: 16 / 9;
3950
+ width: 100%;
3951
+ max-width: min(1100px, 100%);
3952
+ margin: var(--space-3) auto;
3953
+ background: var(--bg-2);
3954
+ border-radius: 18px;
3955
+ padding: clamp(16px, 5vw, 64px);
3956
+ box-sizing: border-box;
3957
+ display: flex;
3958
+ overflow: hidden;
3959
+ container-type: inline-size; /* cqw units track the stage, not the viewport */
3960
+ }
3961
+ @media (max-height: 500px) and (orientation: landscape) {
3962
+ .ds-deck-stage {
3963
+ max-height: calc(100vh - 140px);
3964
+ max-height: calc(100dvh - 140px);
3965
+ aspect-ratio: auto;
3966
+ }
3967
+ }
3968
+ .ds-deck-slide { flex: 1; display: flex; min-width: 0; }
3969
+ .ds-deck-controls {
3970
+ display: flex; align-items: center; justify-content: center; gap: 14px;
3971
+ padding: 8px; font-family: var(--ff-mono); font-size: var(--fs-sm);
3972
+ }
3973
+ .ds-deck-count { color: var(--fg-3); }
3974
+ @media (pointer: coarse) {
3975
+ .ds-deck-controls .btn { min-height: 44px; min-width: 44px; }
3976
+ }
3977
+ .ds-slide-eyebrow {
3978
+ font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.1em;
3979
+ text-transform: uppercase; color: var(--fg-3); margin-bottom: clamp(12px, 2.5cqw, 24px);
3980
+ }
3981
+ .ds-slide-col { display: flex; flex-direction: column; justify-content: center; gap: clamp(12px, 2.5cqw, 24px); min-width: 0; }
3982
+ .ds-slide-col--start { align-items: flex-start; }
3983
+ .ds-slide-col--narrow { max-width: 38ch; }
3984
+ .ds-slide-col--quote { max-width: 42ch; }
3985
+ .ds-slide-hero {
3986
+ font-size: clamp(var(--fs-h2), 6cqw, var(--fs-hero));
3987
+ line-height: var(--lh-tight); letter-spacing: var(--tr-tight); font-weight: 600;
3988
+ color: var(--slide-accent, var(--accent-ink));
3989
+ overflow-wrap: anywhere;
3990
+ }
3991
+ .ds-slide-h1 {
3992
+ font-size: clamp(var(--fs-h3), 4.5cqw, var(--fs-h1));
3993
+ line-height: var(--lh-snug); color: var(--fg); font-weight: 500; min-width: 0;
3994
+ }
3995
+ .ds-slide-h1--lead { margin-bottom: 12px; }
3996
+ .ds-slide-quote-body {
3997
+ font-size: clamp(var(--fs-lg), 3.5cqw, var(--fs-h2));
3998
+ line-height: var(--lh-snug); color: var(--fg); font-weight: 400; font-style: italic;
3999
+ }
4000
+ .ds-slide-cite { font-family: var(--ff-mono); font-size: var(--fs-sm); color: var(--fg-3); }
4001
+ .ds-slide-bullet {
4002
+ display: flex; gap: clamp(8px, 2vw, 18px); align-items: baseline;
4003
+ border-bottom: 1px solid var(--rule); padding: 12px 0; flex-wrap: wrap;
4004
+ }
4005
+ .ds-slide-bullet-key {
4006
+ flex: 0 1 clamp(56px, 18%, 100px); min-width: 0;
4007
+ font-family: var(--ff-mono); font-size: var(--fs-sm);
4008
+ color: var(--slide-accent, var(--accent-ink));
4009
+ }
4010
+ .ds-slide-bullet-val { color: var(--fg-2); font-size: var(--fs-lg); min-width: 0; }
4011
+ .ds-slide-split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(12px, 3vw, 32px); margin-top: 12px; }
4012
+ @media (max-width: 760px) {
4013
+ .ds-slide-split { grid-template-columns: 1fr; }
4014
+ }
4015
+ .ds-slide-split-cell {
4016
+ padding: 18px; background: var(--bg-2); border-radius: 14px;
4017
+ color: var(--fg-2); font-size: var(--fs-lg); line-height: var(--lh-base); min-width: 0;
4018
+ }
4019
+ .ds-slide-split-cell--accent { border-left: 3px solid var(--slide-accent, var(--accent)); }
4020
+
4021
+ /* --- error 404 --------------------------------------------- */
4022
+ .ds-err-hero {
4023
+ padding: clamp(16px, 5vw, 36px) clamp(12px, 4vw, 22px);
4024
+ text-align: center; display: flex; flex-direction: column; gap: 14px; align-items: center;
4025
+ }
4026
+ .ds-err-numeral {
4027
+ font-family: var(--ff-mono); font-size: clamp(56px, 20vw, 120px);
4028
+ line-height: 1; color: var(--panel-text-3); letter-spacing: -0.03em;
4029
+ }
4030
+ .ds-err-path {
4031
+ display: inline-flex; gap: 6px; align-items: baseline; flex-wrap: wrap; max-width: 100%;
4032
+ font-family: var(--ff-mono); font-size: 13px; color: var(--panel-text-2);
4033
+ background: var(--panel-1); padding: 6px 12px; border-radius: 8px;
4034
+ overflow-wrap: anywhere; word-break: break-all;
4035
+ }
4036
+
4037
+ /* --- gallery ------------------------------------------------ */
4038
+ .ds-tile-grid {
4039
+ padding: clamp(8px, 2.5vw, 16px);
4040
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr)); gap: 8px;
4041
+ }
4042
+ .ds-tile-grid--tight { grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); }
4043
+ .ds-swatch-grid {
4044
+ padding: clamp(8px, 2.5vw, 16px);
4045
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr)); gap: 12px;
4046
+ }
4047
+ .ds-gallery-tile {
4048
+ cursor: pointer; display: flex; flex-direction: column; gap: 6px;
4049
+ padding: 12px; border-radius: 10px; min-height: clamp(120px, 18vw, 160px);
4050
+ border: 0; text-align: left; font: inherit; color: inherit;
4051
+ background: var(--tile-tone, var(--panel-1));
4052
+ }
4053
+ .ds-gallery-tile:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
4054
+ .ds-gallery-tile--tight { min-height: clamp(96px, 14vw, 120px); }
4055
+ .ds-lightbox {
4056
+ position: fixed; inset: 0; background: var(--scrim);
4057
+ display: flex; align-items: center; justify-content: center;
4058
+ padding: clamp(12px, 4vw, 32px);
4059
+ padding-bottom: max(clamp(12px, 4vw, 32px), env(safe-area-inset-bottom));
4060
+ z-index: 50;
4061
+ }
4062
+ .ds-lightbox-card {
4063
+ background: var(--panel-0); border-radius: 14px; padding: clamp(16px, 4vw, 28px);
4064
+ width: min(520px, 100%); min-width: 0;
4065
+ max-height: calc(100vh - 24px);
4066
+ max-height: calc(100dvh - 24px);
4067
+ overflow: auto;
4068
+ display: flex; flex-direction: column; gap: 14px;
4069
+ }
4070
+ .ds-lightbox-preview {
4071
+ padding: clamp(16px, 6vw, 36px); border-radius: 10px; text-align: center;
4072
+ font-family: var(--ff-mono); white-space: pre-line; font-size: clamp(16px, 5vw, 24px);
4073
+ background: var(--tile-tone, var(--panel-1));
4074
+ }
4075
+
4076
+ /* --- search ------------------------------------------------- */
4077
+ .ds-topbar-search { width: min(280px, 100%); min-width: 0; flex: 1 1 clamp(140px, 30vw, 280px); }
4078
+ @media (max-width: 480px) {
4079
+ .ds-topbar-search { flex-basis: 100%; }
4080
+ }
4081
+ .ds-empty-state { padding: clamp(16px, 5vw, 24px); text-align: center; color: var(--panel-text-3); }
4082
+ .ds-empty-state-glyph { font-size: clamp(24px, 6vw, 32px); }
4083
+ .ds-empty-state-msg { margin: 6px 0; }
4084
+ .ds-empty-state-hint { margin: 0; font-size: var(--fs-sm); }
4085
+
4086
+ /* --- system primer ------------------------------------------ */
4087
+ .ds-swatch-grid-sm {
4088
+ display: grid; grid-template-columns: repeat(auto-fill, minmax(min(110px, 100%), 1fr));
4089
+ gap: 12px; padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px);
4090
+ }
4091
+ .ds-swatch-grid-lg { grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); }
4092
+ .ds-swatch-col { display: flex; flex-direction: column; gap: 6px; }
4093
+ .ds-swatch-chip { height: 48px; border-radius: 10px; border: 1px solid var(--rule); background: var(--swatch, var(--panel-1)); }
4094
+ .ds-swatch-chip--big { height: 64px; }
4095
+ .ds-swatch-name { font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
4096
+ .ds-type-panel { padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px); display: flex; flex-direction: column; gap: 14px; }
4097
+ .ds-type-row {
4098
+ display: flex; align-items: baseline; gap: 14px;
4099
+ border-bottom: 1px solid var(--rule); padding-bottom: 8px; flex-wrap: wrap;
4100
+ }
4101
+ .ds-type-row-label { flex: 0 0 64px; font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
4102
+ .ds-type-sample {
4103
+ min-width: 0; overflow-wrap: anywhere; line-height: var(--lh-tight); color: var(--fg);
4104
+ font-size: var(--sample-size, var(--fs-body));
4105
+ }
4106
+ .ds-prim-panel { padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px); display: flex; flex-direction: column; gap: 18px; }
4107
+ .ds-prim-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
4108
+ .ds-prim-label { flex: 0 0 64px; font-family: var(--ff-mono); font-size: 11px; color: var(--fg-3); }
4109
+
4110
+ /* == appended: content-site == */
4111
+ /* Home landing wrappers (site/theme.mjs) — replace banned inline styles. */
4112
+ .ds-home-hero-wrap { padding: 0 var(--space-2, 8px); }
4113
+ .ds-home-panel { margin: var(--space-2, 8px); }
4114
+ @media (max-width: 480px) {
4115
+ .ds-home-panel { margin: var(--space-1, 4px) 0; }
4116
+ }
4117
+ .ds-quickstart {
4118
+ padding: var(--space-3, 16px) var(--space-4, 22px);
4119
+ display: flex;
4120
+ flex-direction: column;
4121
+ gap: 6px;
4122
+ }
4123
+ /* Table() scroll containment — wide tables scroll inside their own box,
4124
+ never the page body. */
4125
+ .ds-table-wrap {
4126
+ overflow-x: auto;
4127
+ -webkit-overflow-scrolling: touch;
4128
+ max-width: 100%;
4129
+ }
4130
+ .ds-table-wrap > table { min-width: 100%; }
4131
+
4132
+
4133
+ /* == appended: settings kit cleanup == */
4134
+ /* == appended: settings kit == */
4135
+ .ds-settings-main { padding: 8px; }
4136
+ .ds-settings-body { padding: 14px 18px; }
4137
+ .ds-settings-body-stack { display: flex; flex-direction: column; gap: 10px; }
4138
+ .ds-field-block { margin: 10px 0; }
4139
+ .ds-field-eyebrow {
4140
+ font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.06em;
4141
+ text-transform: uppercase; color: var(--panel-text-3);
4142
+ }
4143
+ .ds-hint-sm { font-size: 12px; color: var(--panel-text-2); }
4144
+ .ds-note-quiet { margin: 0; color: var(--panel-text-2); }
4145
+ .ds-btn-row { display: flex; gap: 8px; flex-wrap: wrap; }
4146
+ .ds-btn-row-tight { gap: 6px; }
4147
+ .ds-key-input { flex: 1 1 160px; min-width: 0; font-family: var(--ff-mono); }
4148
+ .ds-toggle-btn { min-width: 78px; }
4149
+ .ds-toggle-label { margin-left: 8px; color: inherit; opacity: 0.7; }
4150
+ .ds-btn-warn { color: var(--warn); }
4151
+ .ds-btn-mascot { color: var(--mascot); }
4152
+ .ds-savebar {
4153
+ position: sticky; bottom: 8px; display: flex; align-items: center;
4154
+ justify-content: flex-end; gap: 8px; flex-wrap: wrap; padding: 10px;
4155
+ background: var(--panel-2); border-radius: 10px; margin: 8px 0;
4156
+ }
4157
+ .ds-savebar-note { flex: 1 1 160px; min-width: 0; color: var(--panel-text-2); }
4158
+ .ds-settings-modal { min-width: min(320px, calc(100vw - 32px)); max-width: 480px; }
4159
+ .ds-modal-body-form { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
4160
+ .ds-modal-note { margin: 0 0 8px; color: var(--panel-text-2); font-size: 14px; }
4161
+ .ds-draft-preview {
4162
+ background: var(--panel-1); padding: 12px; border-radius: 6px;
4163
+ font-size: 13px; color: var(--panel-text-2); max-height: 120px;
4164
+ overflow-y: auto; font-family: var(--ff-mono); overflow-wrap: anywhere;
4165
+ }
4166
+ .ds-modal-actions { display: flex; gap: 8px; margin-top: 12px; justify-content: space-between; flex-wrap: wrap; }
4167
+
4168
+ /* == appended: signin kit cleanup == */
4169
+ /* -- signin kit (ui_kits/signin) -- */
4170
+ .ds-auth-wrap { padding: var(--space-2, 8px); display: flex; flex-direction: column; align-items: center; }
4171
+ .ds-auth-col { width: 100%; max-width: 440px; display: flex; flex-direction: column; gap: 8px; margin: clamp(12px, 4vw, 24px) 0; min-width: 0; }
4172
+ .ds-auth-form { padding: clamp(12px, 3vw, 18px); display: flex; flex-direction: column; gap: 10px; }
4173
+ .ds-auth-sent { align-items: center; text-align: center; }
4174
+ .ds-auth-sent-glyph { font-size: 32px; color: var(--panel-accent); }
4175
+ .ds-auth-sent-title { margin: 0; font-weight: 600; }
4176
+ .ds-auth-sent-sub { margin: 0; color: var(--panel-text-2); overflow-wrap: anywhere; }
4177
+ .ds-auth-field { display: flex; flex-direction: column; gap: 4px; }
4178
+ .ds-auth-field-label { font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--panel-text-3); }
4179
+ .ds-auth-row-between { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
4180
+ .ds-auth-remember { display: flex; align-items: center; gap: 6px; cursor: pointer; }
4181
+ .ds-auth-remember-text { color: var(--panel-text-2); font-size: 13px; }
4182
+ .ds-auth-forgot { font-size: 13px; }
4183
+ .ds-auth-error { padding: 8px 10px; background: var(--panel-1); border-radius: 8px; color: var(--danger); font-size: 13px; overflow-wrap: anywhere; }
4184
+ .ds-auth-divider { display: flex; align-items: center; gap: 10px; margin: 6px 0; color: var(--panel-text-3); font-size: 12px; }
4185
+ .ds-auth-divider-line { flex: 1; height: 1px; background: var(--panel-2); }
4186
+ .ds-auth-providers { display: flex; gap: 8px; flex-wrap: wrap; }
4187
+ .ds-auth-provider-btn { flex: 1 1 100px; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px; }
4188
+ .ds-auth-provider-btn--loading { opacity: 0.7; pointer-events: none; }
4189
+ .ds-auth-provider-glyph { font-family: var(--ff-mono); color: var(--panel-text-3); display: inline-flex; }
4190
+ .ds-auth-modes { display: flex; justify-content: center; gap: 14px; margin-top: 8px; font-size: 13px; flex-wrap: wrap; }
4191
+ .ds-auth-mode-link { color: var(--panel-text-3); text-decoration: none; }
4192
+ .ds-auth-mode-link--active { color: var(--panel-text); text-decoration: underline; }
4193
+ .ds-auth-fineprint { text-align: center; font-size: 12px; color: var(--panel-text-3); margin: 6px 0; }
4194
+
4195
+ /* == appended: gallery-misc kit cleanup == */
4196
+ /* --- shared helpers (converted from inline styles) --- */
4197
+ .ds-m0 { margin: 0; }
4198
+ .ds-text-2 { color: var(--panel-text-2); }
4199
+ .ds-text-3 { color: var(--panel-text-3); }
4200
+ .ds-kit-head { display: flex; align-items: center; justify-content: space-between; gap: clamp(8px, 2vw, 16px); flex-wrap: wrap; }
4201
+
4202
+ /* --- gallery kit --- */
4203
+ .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; }
4204
+ .ds-tile-meta { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-size: 12px; flex-wrap: wrap; min-width: 0; }
4205
+ .ds-tile-glyph { font-family: var(--ff-mono); color: var(--panel-text-3); }
4206
+ .ds-tile-label { color: var(--panel-text); overflow-wrap: anywhere; }
4207
+ .ds-gal-swatch { height: 64px; border-radius: 8px; background: var(--swatch, var(--panel-1)); }
4208
+ .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; }
4209
+ .ds-gal-swatch-name { color: var(--panel-text); }
4210
+ .ds-gal-swatch-hint { color: var(--panel-text-3); overflow-wrap: anywhere; }
4211
+ .ds-lightbox-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
4212
+ .ds-lightbox-tag { font-family: var(--ff-mono); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--panel-text-3); }
4213
+
4214
+ /* --- error_404 kit --- */
4215
+ .ds-err-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-top: 6px; }
4216
+ .ds-err-chips { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; margin-top: 4px; }
4217
+
4218
+ /* == appended: terminal-capp kit cleanup == */
4219
+ /* --- terminal kit ------------------------------------------ */
4220
+ .ds-section-pad-sm { padding: 8px; }
4221
+ .ds-kit-head-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
4222
+ .ds-cli-cmt .cmd { color: var(--fg-3); }
4223
+ .ds-cli-out .cmd { color: var(--fg-2); }
4224
+ .ds-cli-ok .prompt, .ds-cli-ok .cmd { color: var(--accent-ink); }
4225
+ .ds-cli-warn .prompt, .ds-cli-warn .cmd { color: var(--mascot); }
4226
+ .ds-cli-log .prompt { color: var(--fg-3); }
4227
+ .ds-cli-log .cmd { color: var(--fg-2); font-family: var(--ff-mono); }
4228
+ .ds-term-body { padding: 14px 18px; display: flex; flex-direction: column; gap: 4px; background: var(--bg-2); border-radius: 10px; }
4229
+ .ds-term-body--tall { min-height: 280px; }
4230
+ .ds-term-input-row { margin-top: 6px; }
4231
+ .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); }
4232
+ /* full-viewport render root (community-app) */
4233
+ .ds-root-viewport { height: 100vh; height: 100dvh; }
4234
+
4235
+ /* --- chat kit: widescreen detail pane -----------------------
4236
+ .chat itself stays single-column (shared component, untouched) and
4237
+ stretches full-width on ultrawide via the existing .app-main > .chat
4238
+ max-width:none rule above (~L380) — that's fine for a bare thread, but
4239
+ it leaves a lone thread column growing to 1400px+ with no other use of
4240
+ the extra width. This wrapper adds a persistent "thread info" rail once
4241
+ there is room to spare, instead of just widening the message column. */
4242
+ .ds-chat-layout { display: flex; flex-direction: column; flex: 1; min-height: 0; gap: var(--space-3); }
4243
+ .ds-chat-layout > .chat { min-width: 0; }
4244
+ .ds-chat-detail { display: none; }
4245
+ @media (min-width: 1100px) {
4246
+ .ds-chat-layout { display: grid; grid-template-columns: minmax(0, 1fr) 280px; align-items: start; gap: var(--space-4); }
4247
+ .ds-chat-detail { display: block; position: sticky; top: 0; }
4248
+ }