agentgui 1.0.940 → 1.0.941
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/AGENTS.md +3 -8
- package/package.json +1 -1
- package/server.js +10 -1
- package/site/app/index.html +14 -37
- package/site/app/js/app.js +243 -65
- package/site/app/js/backend.js +20 -10
- package/site/app/vendor/anentrypoint-design/247420.css +274 -86
- package/site/app/vendor/anentrypoint-design/247420.js +13 -13
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
Source-of-truth tokens. Component sheet lives in app-shell.css.
|
|
7
7
|
============================================================ */
|
|
8
8
|
|
|
9
|
-
@import url('
|
|
9
|
+
@import url('https://fonts.googleapis.com/css2?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
10
|
|
|
11
11
|
.ds-247420 {
|
|
12
12
|
/* Tree view indentation tokens */
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
--mascot: #E84B8A;
|
|
34
34
|
--mascot-2: #FF3CA7;
|
|
35
35
|
--mascot-tint: #F5D2DF;
|
|
36
|
+
--mascot-deep: #B81F63;
|
|
36
37
|
|
|
37
38
|
/* Signals */
|
|
38
39
|
--sun: #F5C344;
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
|
|
54
55
|
--accent: var(--green);
|
|
55
56
|
--accent-fg: var(--paper);
|
|
56
|
-
--accent-tint: color-mix(in oklab, var(--accent)
|
|
57
|
+
--accent-tint: color-mix(in oklab, var(--accent) 26%, var(--bg));
|
|
57
58
|
|
|
58
59
|
--panel-bg: var(--bg);
|
|
59
60
|
--panel-bg-2: var(--bg-2);
|
|
@@ -68,18 +69,17 @@
|
|
|
68
69
|
--panel-accent-2: var(--accent-bright, var(--accent));
|
|
69
70
|
--panel-shadow: 0 1px 0 color-mix(in oklab, var(--fg) 6%, transparent), 0 4px 14px color-mix(in oklab, var(--fg) 8%, transparent);
|
|
70
71
|
|
|
71
|
-
/* Type —
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
--ff-
|
|
75
|
-
--ff-
|
|
76
|
-
--ff-body: 'Space Grotesk', system-ui, sans-serif;
|
|
72
|
+
/* Type — Inter for everything non-mono. The display/narrow aliases stay so
|
|
73
|
+
consumers that reference them keep working; they resolve to the body font. */
|
|
74
|
+
--ff-display: 'Inter', system-ui, sans-serif;
|
|
75
|
+
--ff-narrow: 'Inter', system-ui, sans-serif;
|
|
76
|
+
--ff-body: 'Inter', system-ui, sans-serif;
|
|
77
77
|
--ff-mono: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
|
|
78
78
|
|
|
79
|
-
--fs-micro:
|
|
80
|
-
--fs-tiny:
|
|
81
|
-
--fs-xs:
|
|
82
|
-
--fs-sm:
|
|
79
|
+
--fs-micro: 12px;
|
|
80
|
+
--fs-tiny: 13px;
|
|
81
|
+
--fs-xs: 14px;
|
|
82
|
+
--fs-sm: 15px;
|
|
83
83
|
--fs-body: 16px;
|
|
84
84
|
--fs-lg: 18px;
|
|
85
85
|
--fs-xl: 21px;
|
|
@@ -90,6 +90,15 @@
|
|
|
90
90
|
--fs-hero: clamp(42px, 7cqi, 96px);
|
|
91
91
|
--fs-mega: clamp(56px, 11cqi, 168px);
|
|
92
92
|
|
|
93
|
+
/* App/chrome typescale: the default heading scale above is tuned for
|
|
94
|
+
marketing/hero layouts (h1 up to 64px). Application chrome — page titles,
|
|
95
|
+
panel headers — needs a compact ceiling so a PageHeader title doesn't
|
|
96
|
+
dwarf the content. Opt in with `data-typescale="app"` on a container. */
|
|
97
|
+
--fs-h1-app: clamp(22px, 2.4cqi, 30px);
|
|
98
|
+
--fs-h2-app: clamp(19px, 2cqi, 24px);
|
|
99
|
+
--fs-h3-app: clamp(17px, 1.8cqi, 20px);
|
|
100
|
+
--fs-h4-app: clamp(15px, 1.6cqi, 17px);
|
|
101
|
+
|
|
93
102
|
--lh-tight: 1.05;
|
|
94
103
|
--lh-snug: 1.2;
|
|
95
104
|
--lh-base: 1.55;
|
|
@@ -195,6 +204,7 @@
|
|
|
195
204
|
|
|
196
205
|
.ds-247420[data-theme="ink"],
|
|
197
206
|
.ds-247420[data-theme="dark"] {
|
|
207
|
+
color-scheme: dark;
|
|
198
208
|
--bg: var(--ink);
|
|
199
209
|
--bg-2: var(--ink-2);
|
|
200
210
|
--bg-3: #464650;
|
|
@@ -381,6 +391,12 @@
|
|
|
381
391
|
.ds-247420 h3, .ds-247420 .t-h3 { font-family: var(--ff-body); font-size: var(--fs-h3); line-height: var(--lh-snug); letter-spacing: -0.01em; font-weight: 600; margin: 0; }
|
|
382
392
|
.ds-247420 h4, .ds-247420 .t-h4 { font-family: var(--ff-body); font-size: var(--fs-h4); line-height: var(--lh-snug); font-weight: 600; margin: 0; }
|
|
383
393
|
|
|
394
|
+
/* App/chrome typescale opt-in: compact heading ceiling for application UIs. */
|
|
395
|
+
.ds-247420[data-typescale="app"] h1, .ds-247420[data-typescale="app"] .t-h1 { font-size: var(--fs-h1-app); line-height: 1.15; }
|
|
396
|
+
.ds-247420[data-typescale="app"] h2, .ds-247420[data-typescale="app"] .t-h2 { font-size: var(--fs-h2-app); }
|
|
397
|
+
.ds-247420[data-typescale="app"] h3, .ds-247420[data-typescale="app"] .t-h3 { font-size: var(--fs-h3-app); }
|
|
398
|
+
.ds-247420[data-typescale="app"] h4, .ds-247420[data-typescale="app"] .t-h4 { font-size: var(--fs-h4-app); }
|
|
399
|
+
|
|
384
400
|
.ds-247420 .t-hero { font-family: var(--ff-body); font-size: var(--fs-hero); line-height: var(--lh-tight); letter-spacing: var(--tr-tighter); font-weight: 600; margin: 0; }
|
|
385
401
|
.ds-247420 .t-mega { font-family: var(--ff-body); font-size: var(--fs-mega); line-height: 0.95; letter-spacing: var(--tr-tighter); font-weight: 600; margin: 0; }
|
|
386
402
|
|
|
@@ -471,6 +487,11 @@
|
|
|
471
487
|
.ds-247420 .app {
|
|
472
488
|
display: flex; flex-direction: column;
|
|
473
489
|
min-height: 100vh;
|
|
490
|
+
/* Definite height so the flex column resolves height:100% for descendants
|
|
491
|
+
(e.g. a full-height chat) at every breakpoint, not just where a desktop
|
|
492
|
+
media override happened to set explicit heights. dvh tracks mobile chrome. */
|
|
493
|
+
min-height: 100dvh;
|
|
494
|
+
height: 100dvh;
|
|
474
495
|
background: var(--bg);
|
|
475
496
|
color: var(--fg);
|
|
476
497
|
/* Notched-device safe area padding (no-op on devices without notches) */
|
|
@@ -480,6 +501,15 @@
|
|
|
480
501
|
padding-right: env(safe-area-inset-right);
|
|
481
502
|
}
|
|
482
503
|
|
|
504
|
+
/* When the app shell is embedded inside a windowed surface (e.g. the freddie
|
|
505
|
+
dashboard mounted in a WM window via .fd-root) it is NOT a full-page app:
|
|
506
|
+
`min-height:100vh` and the absence of an explicit width make it collapse to
|
|
507
|
+
0 width at desktop, where the responsive single-column @media rules don't
|
|
508
|
+
apply. Inside .fd-root it must fill its container instead. (At <=767px the
|
|
509
|
+
grid already linearizes, which is why the bug only showed at desktop width.) */
|
|
510
|
+
.ds-247420 .fd-root .app { width: 100%; height: 100%; min-height: 0; flex: 1 1 auto; }
|
|
511
|
+
.ds-247420 .fd-root .app-body { min-width: 0; }
|
|
512
|
+
|
|
483
513
|
.ds-247420 {
|
|
484
514
|
--app-status-h: var(--size-base);
|
|
485
515
|
--app-topbar-h: var(--size-lg);
|
|
@@ -604,6 +634,21 @@
|
|
|
604
634
|
height: 100%;
|
|
605
635
|
}
|
|
606
636
|
.ds-247420 .app-main > * { min-height: 0; }
|
|
637
|
+
/* The main region scrolls its own overflow at every breakpoint (previously
|
|
638
|
+
only ≥901px), so a fixed-height .app never clips route content and inner
|
|
639
|
+
panels don't fight the page scroll. */
|
|
640
|
+
.ds-247420 .app-main { overflow-y: auto; }
|
|
641
|
+
/* Reserve the scrollbar track so routes with/without overflow don't shift
|
|
642
|
+
the layout horizontally when the bar appears. */
|
|
643
|
+
.ds-247420 .app-main { scrollbar-gutter: stable; }
|
|
644
|
+
/* Jump-target anchors clear the inner-scroll top edge (no chrome overlap,
|
|
645
|
+
but a little breathing room when deep-linked within .app-main). */
|
|
646
|
+
.ds-247420 .app-main [id] { scroll-margin-top: var(--space-4); }
|
|
647
|
+
/* Full-height route children fill the region instead of scrolling the page. */
|
|
648
|
+
.ds-247420 .app-main > .chat,
|
|
649
|
+
.ds-247420 .app-main > .chat-area,
|
|
650
|
+
.ds-247420 .app-main > .ds-file-stage,
|
|
651
|
+
.ds-247420 .app-main > .grow { flex: 1 1 auto; min-height: 0; }
|
|
607
652
|
.ds-247420 .app-main.narrow { max-width: var(--measure-narrow); margin: 0 auto; }
|
|
608
653
|
|
|
609
654
|
@media (min-width: 1400px) {
|
|
@@ -688,7 +733,7 @@
|
|
|
688
733
|
.ds-247420 .ds-badge {
|
|
689
734
|
display: inline-flex; align-items: center; justify-content: center;
|
|
690
735
|
min-width: 18px; height: 18px; padding: 0 6px;
|
|
691
|
-
font-size:
|
|
736
|
+
font-size: var(--fs-micro); font-weight: 600; line-height: 1;
|
|
692
737
|
border-radius: 999px;
|
|
693
738
|
background: var(--bg-3); color: var(--fg-2);
|
|
694
739
|
}
|
|
@@ -722,6 +767,9 @@
|
|
|
722
767
|
.ds-247420 .chip.tone-error { background: var(--flame); color: var(--paper); }
|
|
723
768
|
.ds-247420 .chip.tone-success { background: var(--green-tint); color: var(--green-deep); }
|
|
724
769
|
.ds-247420 .chip.tone-disabled { background: var(--bg-3); color: var(--fg-3); }
|
|
770
|
+
.ds-247420 .chip.tone-ok { background: var(--green-tint); color: var(--green-deep); }
|
|
771
|
+
.ds-247420 .chip.tone-miss { background: var(--flame); color: var(--paper); }
|
|
772
|
+
.ds-247420 .chip.tone-neutral { background: var(--bg-3); color: var(--fg-2); }
|
|
725
773
|
|
|
726
774
|
.ds-247420 .glyph {
|
|
727
775
|
display: inline-flex; align-items: center; justify-content: center;
|
|
@@ -734,9 +782,11 @@
|
|
|
734
782
|
Panel — soft tonal container, no border decoration
|
|
735
783
|
============================================================ */
|
|
736
784
|
.ds-247420 .panel {
|
|
737
|
-
background: var(--bg);
|
|
785
|
+
background: var(--panel-1, var(--bg-2));
|
|
738
786
|
border-radius: var(--r-3);
|
|
739
787
|
margin: 0 0 var(--space-5);
|
|
788
|
+
padding: var(--space-3);
|
|
789
|
+
box-shadow: var(--panel-shadow);
|
|
740
790
|
position: relative;
|
|
741
791
|
}
|
|
742
792
|
.ds-247420 .panel.panel-inline { background: var(--bg-2); padding: var(--space-3) var(--space-3); }
|
|
@@ -847,6 +897,27 @@
|
|
|
847
897
|
}
|
|
848
898
|
.ds-247420 .cli .copy:hover { background: #6A6A70; }
|
|
849
899
|
|
|
900
|
+
/* Multi-line CLI block: when .cli holds .cli-line / .cli-cmt children
|
|
901
|
+
(quickstart scripts, multi-command snippets) it stacks as a column
|
|
902
|
+
instead of the single-line install row. */
|
|
903
|
+
.ds-247420 .cli:has(.cli-line),
|
|
904
|
+
.ds-247420 .cli:has(.cli-cmt) {
|
|
905
|
+
flex-direction: column; align-items: stretch; gap: 0;
|
|
906
|
+
font-size: var(--fs-sm); line-height: 1.6;
|
|
907
|
+
}
|
|
908
|
+
.ds-247420 .cli-line {
|
|
909
|
+
display: flex; gap: 10px;
|
|
910
|
+
font-family: var(--ff-mono); font-size: 13px; line-height: 1.6;
|
|
911
|
+
padding: 3px 0;
|
|
912
|
+
}
|
|
913
|
+
.ds-247420 .cli-line .prompt { color: var(--green-2); flex: 0 0 auto; user-select: none; }
|
|
914
|
+
.ds-247420 .cli-line .cmd { flex: 1 1 auto; white-space: pre-wrap; word-break: break-word; color: var(--paper); }
|
|
915
|
+
.ds-247420 .cli-cmt {
|
|
916
|
+
color: var(--fg-3);
|
|
917
|
+
font-family: var(--ff-mono); font-size: var(--fs-tiny); line-height: 1.6;
|
|
918
|
+
padding: 3px 0; white-space: pre-wrap; word-break: break-word;
|
|
919
|
+
}
|
|
920
|
+
|
|
850
921
|
/* ============================================================
|
|
851
922
|
Receipt — key/value table
|
|
852
923
|
============================================================ */
|
|
@@ -884,6 +955,11 @@
|
|
|
884
955
|
.ds-247420 table td { padding: 14px 16px; border-top: 1px solid var(--rule); }
|
|
885
956
|
.ds-247420 table tr.clickable { cursor: pointer; }
|
|
886
957
|
.ds-247420 table tr.clickable:hover td { background: var(--bg-2); }
|
|
958
|
+
.ds-247420 table tr.clickable:focus-visible {
|
|
959
|
+
outline: 2px solid var(--accent);
|
|
960
|
+
outline-offset: -2px;
|
|
961
|
+
}
|
|
962
|
+
.ds-247420 table tr.clickable:focus-visible td { background: var(--bg-2); }
|
|
887
963
|
|
|
888
964
|
/* ============================================================
|
|
889
965
|
Changelog
|
|
@@ -1004,9 +1080,8 @@
|
|
|
1004
1080
|
Mobile Portrait Breakpoint (480px and below)
|
|
1005
1081
|
────────────────────────────────────────────────────────────────────── */
|
|
1006
1082
|
@media (max-width: 480px) {
|
|
1007
|
-
/* App Layout
|
|
1008
|
-
|
|
1009
|
-
.ds-247420 .app-body.no-side { grid-template-columns: 1fr; }
|
|
1083
|
+
/* App Layout: single-column + drawer is handled once in the ≤900px block;
|
|
1084
|
+
no need to re-declare grid-template-columns here (was a redundant !important). */
|
|
1010
1085
|
|
|
1011
1086
|
/* Topbar Navigation */
|
|
1012
1087
|
.ds-247420 .app-topbar {
|
|
@@ -1017,9 +1092,16 @@
|
|
|
1017
1092
|
padding: 12px 10px;
|
|
1018
1093
|
min-height: 44px;
|
|
1019
1094
|
}
|
|
1095
|
+
/* Keep primary nav reachable on small screens (apps without a sidebar have
|
|
1096
|
+
no other entry point). Compact it and let it scroll horizontally rather
|
|
1097
|
+
than hiding it entirely. */
|
|
1020
1098
|
.ds-247420 .app-topbar nav {
|
|
1021
|
-
display:
|
|
1099
|
+
display: flex; gap: 2px;
|
|
1100
|
+
overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
|
|
1101
|
+
max-width: 60vw;
|
|
1022
1102
|
}
|
|
1103
|
+
.ds-247420 .app-topbar nav::-webkit-scrollbar { display: none; }
|
|
1104
|
+
.ds-247420 .app-topbar nav a { padding: 10px 8px; white-space: nowrap; }
|
|
1023
1105
|
.ds-247420 .brand { font-size: var(--fs-tiny); font-weight: 600; }
|
|
1024
1106
|
|
|
1025
1107
|
/* Search */
|
|
@@ -1031,12 +1113,7 @@
|
|
|
1031
1113
|
.ds-247420 .app-main { padding: var(--space-4) var(--space-2); }
|
|
1032
1114
|
.ds-247420 .app-main.narrow { max-width: 100%; margin: 0; }
|
|
1033
1115
|
|
|
1034
|
-
/*
|
|
1035
|
-
.ds-247420 .t-hero { font-size: clamp(28px, 8vw, 48px); }
|
|
1036
|
-
.ds-247420 .t-mega { font-size: clamp(24px, 6vw, 42px); }
|
|
1037
|
-
.ds-247420 h1, .ds-247420 .t-h1 { font-size: clamp(22px, 6vw, 36px); }
|
|
1038
|
-
.ds-247420 h2, .ds-247420 .t-h2 { font-size: clamp(18px, 5vw, 28px); }
|
|
1039
|
-
.ds-247420 h3, .ds-247420 .t-h3 { font-size: clamp(16px, 4.5vw, 24px); }
|
|
1116
|
+
/* Headings stay on the fluid base clamps (cqi) — no mobile re-clamp. */
|
|
1040
1117
|
|
|
1041
1118
|
/* Panel & Row */
|
|
1042
1119
|
.ds-247420 .panel { margin: 0 0 var(--space-3); }
|
|
@@ -1101,10 +1178,10 @@
|
|
|
1101
1178
|
.ds-247420 .row-form input,
|
|
1102
1179
|
.ds-247420 .row-form textarea { padding: 11px 12px; font-size: var(--fs-sm); }
|
|
1103
1180
|
|
|
1104
|
-
/* Hero Section */
|
|
1181
|
+
/* Hero Section — keep fluid base font-size, just unconstrain width on mobile. */
|
|
1105
1182
|
.ds-247420 .ds-hero { padding: var(--space-6) 0 var(--space-5); }
|
|
1106
|
-
.ds-247420 .ds-hero-title {
|
|
1107
|
-
.ds-247420 .ds-hero-body {
|
|
1183
|
+
.ds-247420 .ds-hero-title { max-width: 100%; }
|
|
1184
|
+
.ds-247420 .ds-hero-body { max-width: 100%; }
|
|
1108
1185
|
|
|
1109
1186
|
/* Table Responsiveness */
|
|
1110
1187
|
.ds-247420 table { font-size: var(--fs-xs); }
|
|
@@ -1169,12 +1246,7 @@
|
|
|
1169
1246
|
.ds-247420 .app-main { padding: var(--space-6) var(--space-4); }
|
|
1170
1247
|
.ds-247420 .app-main.narrow { max-width: 100%; }
|
|
1171
1248
|
|
|
1172
|
-
/*
|
|
1173
|
-
.ds-247420 .t-hero { font-size: clamp(32px, 6.5cqi, 56px); }
|
|
1174
|
-
.ds-247420 .t-mega { font-size: clamp(28px, 5.5cqi, 80px); }
|
|
1175
|
-
.ds-247420 h1, .ds-247420 .t-h1 { font-size: clamp(24px, 5cqi, 48px); }
|
|
1176
|
-
.ds-247420 h2, .ds-247420 .t-h2 { font-size: clamp(20px, 4cqi, 36px); }
|
|
1177
|
-
.ds-247420 h3, .ds-247420 .t-h3 { font-size: clamp(18px, 3.5cqi, 28px); }
|
|
1249
|
+
/* Headings stay on the fluid base clamps (cqi) — no tablet re-clamp. */
|
|
1178
1250
|
|
|
1179
1251
|
/* File list — single column rows on tablet (cards only via data-columns) */
|
|
1180
1252
|
.ds-247420 .ds-file-row {
|
|
@@ -1204,9 +1276,9 @@
|
|
|
1204
1276
|
.ds-247420 .panel-head { padding: var(--space-4) var(--space-4); }
|
|
1205
1277
|
.ds-247420 .panel-body { padding: var(--space-2) var(--space-3); }
|
|
1206
1278
|
|
|
1207
|
-
/* Hero */
|
|
1279
|
+
/* Hero — fluid base font-size; only width unconstrained on tablet. */
|
|
1208
1280
|
.ds-247420 .ds-hero { padding: var(--space-7) 0 var(--space-6); max-width: 100%; }
|
|
1209
|
-
.ds-247420 .ds-hero-title {
|
|
1281
|
+
.ds-247420 .ds-hero-title { max-width: 100%; }
|
|
1210
1282
|
|
|
1211
1283
|
/* Row */
|
|
1212
1284
|
.ds-247420 .row {
|
|
@@ -1640,7 +1712,7 @@
|
|
|
1640
1712
|
display: inline-flex; align-items: center; justify-content: center;
|
|
1641
1713
|
border: var(--bw-hair) solid var(--rule); border-radius: 5px;
|
|
1642
1714
|
background: var(--bg); color: var(--accent-fg);
|
|
1643
|
-
font-size:
|
|
1715
|
+
font-size: var(--fs-micro); line-height: 1; cursor: pointer;
|
|
1644
1716
|
opacity: 0; transition: opacity var(--dur-base) var(--ease), background var(--dur-snap) var(--ease);
|
|
1645
1717
|
}
|
|
1646
1718
|
.ds-247420 .ds-file-row:hover .ds-file-check,
|
|
@@ -1719,7 +1791,6 @@
|
|
|
1719
1791
|
.ds-247420 .chat {
|
|
1720
1792
|
display: flex; flex-direction: column;
|
|
1721
1793
|
flex: 1; min-height: 0; gap: var(--space-3);
|
|
1722
|
-
padding-bottom: calc(var(--app-status-h, 42px) + var(--space-2));
|
|
1723
1794
|
}
|
|
1724
1795
|
.ds-247420 .chat-head {
|
|
1725
1796
|
display: flex; align-items: baseline; gap: 8px;
|
|
@@ -1730,6 +1801,7 @@
|
|
|
1730
1801
|
margin-bottom: var(--space-2);
|
|
1731
1802
|
}
|
|
1732
1803
|
.ds-247420 .chat-head .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
|
|
1804
|
+
.ds-247420 .chat-head .ds-chat-title,
|
|
1733
1805
|
.ds-247420 .chat-head > span:nth-child(2) {
|
|
1734
1806
|
font-family: var(--ff-body); font-size: var(--fs-h4);
|
|
1735
1807
|
font-weight: 600; color: var(--fg);
|
|
@@ -1743,21 +1815,21 @@
|
|
|
1743
1815
|
flex: 1; min-height: 0; overflow-y: auto;
|
|
1744
1816
|
padding: var(--space-2) 0;
|
|
1745
1817
|
scrollbar-width: thin; scrollbar-color: var(--bg-3) transparent;
|
|
1746
|
-
|
|
1818
|
+
}
|
|
1819
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1820
|
+
.ds-247420 .chat-thread { scroll-behavior: smooth; }
|
|
1747
1821
|
}
|
|
1748
1822
|
.ds-247420 .chat-thread::-webkit-scrollbar { width: 8px; }
|
|
1749
1823
|
.ds-247420 .chat-thread::-webkit-scrollbar-thumb { background: var(--bg-3); border-radius: 4px; }
|
|
1750
|
-
.ds-247420 .chat-
|
|
1751
|
-
|
|
1752
|
-
|
|
1824
|
+
.ds-247420 .chat-empty {
|
|
1825
|
+
margin: auto;
|
|
1826
|
+
text-align: center;
|
|
1753
1827
|
color: var(--fg-3);
|
|
1754
1828
|
font-family: var(--ff-mono);
|
|
1755
|
-
font-size: var(--fs-sm);
|
|
1756
|
-
text-align: center;
|
|
1757
|
-
margin: auto;
|
|
1758
|
-
opacity: 0.6;
|
|
1759
1829
|
pointer-events: none;
|
|
1760
1830
|
}
|
|
1831
|
+
.ds-247420 .chat-empty-title { font-size: var(--fs-sm); margin: 0 0 var(--space-1); }
|
|
1832
|
+
.ds-247420 .chat-empty-sub { font-size: var(--fs-tiny); margin: 0; opacity: .7; }
|
|
1761
1833
|
|
|
1762
1834
|
.ds-247420 .chat-msg { display: flex; gap: 12px; align-items: flex-start; padding: 6px 0; position: relative; min-width: 0; }
|
|
1763
1835
|
.ds-247420 .chat-msg.you { flex-direction: row-reverse; }
|
|
@@ -1791,10 +1863,10 @@
|
|
|
1791
1863
|
|
|
1792
1864
|
.ds-247420 .chat-bubble {
|
|
1793
1865
|
padding: 10px 14px; background: var(--bg-2); color: var(--fg);
|
|
1794
|
-
|
|
1866
|
+
max-width: 100%;
|
|
1867
|
+
border-radius: var(--r-2); line-height: 1.55;
|
|
1795
1868
|
word-wrap: break-word; overflow-wrap: anywhere;
|
|
1796
1869
|
font-size: var(--fs-sm);
|
|
1797
|
-
max-width: clamp(220px, min(75vw, 28em), 480px);
|
|
1798
1870
|
min-width: 0;
|
|
1799
1871
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
|
1800
1872
|
}
|
|
@@ -2078,27 +2150,34 @@
|
|
|
2078
2150
|
box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 20%, transparent);
|
|
2079
2151
|
outline: none;
|
|
2080
2152
|
}
|
|
2081
|
-
.ds-247420 .chat-composer .send
|
|
2082
|
-
.ds-247420 .chat-composer button {
|
|
2153
|
+
.ds-247420 .chat-composer .send {
|
|
2083
2154
|
width: 44px; height: 44px; border-radius: 50%;
|
|
2084
2155
|
background: var(--accent); color: var(--accent-fg);
|
|
2085
|
-
border: 0; cursor: pointer;
|
|
2156
|
+
border: 0; cursor: pointer;
|
|
2086
2157
|
display: inline-flex; align-items: center; justify-content: center;
|
|
2087
|
-
flex-shrink: 0;
|
|
2158
|
+
flex-shrink: 0;
|
|
2088
2159
|
transition: background var(--dur-snap, .15s) var(--ease, ease), transform .1s ease;
|
|
2089
|
-
will-change: transform; contain: layout style paint;
|
|
2090
2160
|
}
|
|
2091
|
-
.ds-247420 .chat-composer .send:
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
.ds-247420 .
|
|
2161
|
+
.ds-247420 .chat-composer .send:disabled { opacity: .5; cursor: not-allowed; }
|
|
2162
|
+
/* Ghost icon buttons in the toolbar (attach / emoji / more) — NOT the round
|
|
2163
|
+
accent send button. */
|
|
2164
|
+
.ds-247420 .composer-btn {
|
|
2165
|
+
width: 40px; height: 40px; border-radius: 50%;
|
|
2166
|
+
background: transparent; color: var(--fg-3);
|
|
2167
|
+
border: 0; cursor: pointer;
|
|
2168
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2169
|
+
flex-shrink: 0;
|
|
2170
|
+
transition: background var(--dur-snap, .15s) var(--ease, ease), color var(--dur-snap, .15s) var(--ease, ease);
|
|
2171
|
+
}
|
|
2172
|
+
.ds-247420 .composer-btn:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); color: var(--fg); }
|
|
2173
|
+
.ds-247420 .chat-composer .send:hover { transform: scale(1.04); }
|
|
2174
|
+
.ds-247420 .chat-composer .send:active { transform: scale(0.96); }
|
|
2095
2175
|
.ds-247420 .chat-composer .send:focus-visible,
|
|
2096
|
-
.ds-247420 .
|
|
2176
|
+
.ds-247420 .composer-btn:focus-visible {
|
|
2097
2177
|
outline: 2px solid var(--accent);
|
|
2098
2178
|
outline-offset: 2px;
|
|
2099
2179
|
}
|
|
2100
|
-
.ds-247420 .chat-composer .send:disabled
|
|
2101
|
-
.ds-247420 .chat-composer button:disabled {
|
|
2180
|
+
.ds-247420 .chat-composer .send:disabled {
|
|
2102
2181
|
background: var(--bg-3); color: var(--fg-3); cursor: not-allowed; transform: none;
|
|
2103
2182
|
}
|
|
2104
2183
|
|
|
@@ -2110,7 +2189,8 @@
|
|
|
2110
2189
|
border-radius: 50%; flex-shrink: 0;
|
|
2111
2190
|
}
|
|
2112
2191
|
.ds-247420 .aicat-meta { display: flex; flex-direction: column; font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); }
|
|
2113
|
-
.ds-247420 .aicat-meta .name { color: var(--mascot); font-weight: 600; }
|
|
2192
|
+
.ds-247420 .aicat-meta .name { color: var(--mascot-deep, var(--mascot)); font-weight: 600; }
|
|
2193
|
+
.ds-247420[data-theme="dark"] .aicat-meta .name, .ds-247420[data-theme="ink"] .aicat-meta .name { color: var(--mascot); }
|
|
2114
2194
|
|
|
2115
2195
|
/* ============================================================
|
|
2116
2196
|
Sidebar polish: hide zero-count badges; tonal active state;
|
|
@@ -2118,7 +2198,7 @@
|
|
|
2118
2198
|
============================================================ */
|
|
2119
2199
|
.ds-247420 .app-side .count {
|
|
2120
2200
|
background: color-mix(in oklab, var(--mascot) 92%, transparent);
|
|
2121
|
-
padding: 1px 8px; font-size:
|
|
2201
|
+
padding: 1px 8px; font-size: var(--fs-micro); font-weight: 700;
|
|
2122
2202
|
font-family: var(--ff-mono); letter-spacing: 0.04em;
|
|
2123
2203
|
min-width: 18px; text-align: center;
|
|
2124
2204
|
}
|
|
@@ -2239,10 +2319,14 @@
|
|
|
2239
2319
|
transform: scale(0.98);
|
|
2240
2320
|
}
|
|
2241
2321
|
|
|
2242
|
-
/* Enhanced hover transitions
|
|
2322
|
+
/* Enhanced hover transitions — transition only the properties that actually
|
|
2323
|
+
change (not `all`, which animates layout and is a perf trap), and drop the
|
|
2324
|
+
blanket `will-change` (it forces a permanent compositor layer per element). */
|
|
2243
2325
|
.ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost, .ds-247420 button, .ds-247420 a.row, .ds-247420 .row, .ds-247420 .chip, .ds-247420[role="button"], .ds-247420 input[type="checkbox"], .ds-247420 input[type="radio"] {
|
|
2244
|
-
transition:
|
|
2245
|
-
|
|
2326
|
+
transition: background-color var(--dur-snap) var(--ease),
|
|
2327
|
+
color var(--dur-snap) var(--ease),
|
|
2328
|
+
box-shadow var(--dur-snap) var(--ease),
|
|
2329
|
+
transform var(--dur-snap) var(--ease);
|
|
2246
2330
|
}
|
|
2247
2331
|
|
|
2248
2332
|
/* Prevent double-tap zoom on buttons (iOS) */
|
|
@@ -2383,6 +2467,9 @@
|
|
|
2383
2467
|
.ds-247420 input[type="email"],
|
|
2384
2468
|
.ds-247420 input[type="password"],
|
|
2385
2469
|
.ds-247420 input[type="number"],
|
|
2470
|
+
.ds-247420 input[type="search"],
|
|
2471
|
+
.ds-247420 input[type="url"],
|
|
2472
|
+
.ds-247420 input[type="tel"],
|
|
2386
2473
|
.ds-247420 textarea,
|
|
2387
2474
|
.ds-247420 select {
|
|
2388
2475
|
transition: background var(--dur-snap) var(--ease),
|
|
@@ -2394,10 +2481,74 @@
|
|
|
2394
2481
|
.ds-247420 input[type="email"]::placeholder,
|
|
2395
2482
|
.ds-247420 input[type="password"]::placeholder,
|
|
2396
2483
|
.ds-247420 input[type="number"]::placeholder,
|
|
2484
|
+
.ds-247420 input[type="search"]::placeholder,
|
|
2485
|
+
.ds-247420 input[type="url"]::placeholder,
|
|
2397
2486
|
.ds-247420 textarea::placeholder {
|
|
2398
2487
|
color: var(--fg-3);
|
|
2399
2488
|
}
|
|
2400
2489
|
|
|
2490
|
+
/* ── Field controls: themed base for TextField / Select / SearchInput ──
|
|
2491
|
+
Root fix: previously only `transition` was set, so themed apps got
|
|
2492
|
+
browser-default white boxes in dark mode and labels collided with inputs
|
|
2493
|
+
because `.ds-field` had no layout. */
|
|
2494
|
+
.ds-247420 .ds-field {
|
|
2495
|
+
display: flex;
|
|
2496
|
+
flex-direction: column;
|
|
2497
|
+
gap: var(--space-1, 6px);
|
|
2498
|
+
align-items: stretch;
|
|
2499
|
+
width: 100%;
|
|
2500
|
+
}
|
|
2501
|
+
.ds-247420 .ds-field-label {
|
|
2502
|
+
font-size: var(--fs-sm, 14px);
|
|
2503
|
+
color: var(--fg-2);
|
|
2504
|
+
line-height: 1.3;
|
|
2505
|
+
}
|
|
2506
|
+
.ds-247420 .ds-field-hint {
|
|
2507
|
+
font-size: var(--fs-tiny, 13px);
|
|
2508
|
+
color: var(--fg-3);
|
|
2509
|
+
line-height: 1.35;
|
|
2510
|
+
}
|
|
2511
|
+
.ds-247420 .ds-field-count {
|
|
2512
|
+
font-size: var(--fs-tiny, 13px);
|
|
2513
|
+
color: var(--fg-3);
|
|
2514
|
+
align-self: flex-end;
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
.ds-247420 .ds-field input,
|
|
2518
|
+
.ds-247420 .ds-field textarea,
|
|
2519
|
+
.ds-247420 .ds-field .ds-select,
|
|
2520
|
+
.ds-247420 .ds-search-input {
|
|
2521
|
+
width: 100%;
|
|
2522
|
+
box-sizing: border-box;
|
|
2523
|
+
font: inherit;
|
|
2524
|
+
color: var(--fg);
|
|
2525
|
+
background: var(--bg-2);
|
|
2526
|
+
border: 0;
|
|
2527
|
+
box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--rule);
|
|
2528
|
+
border-radius: var(--r-2, 10px);
|
|
2529
|
+
padding: 10px 14px;
|
|
2530
|
+
}
|
|
2531
|
+
.ds-247420 .ds-field textarea { min-height: calc(4 * 1.5em); resize: vertical; }
|
|
2532
|
+
.ds-247420 .ds-search-input::placeholder { color: var(--fg-3); }
|
|
2533
|
+
|
|
2534
|
+
.ds-247420 .ds-field input:focus-visible,
|
|
2535
|
+
.ds-247420 .ds-field textarea:focus-visible,
|
|
2536
|
+
.ds-247420 .ds-field .ds-select:focus-visible,
|
|
2537
|
+
.ds-247420 .ds-search-input:focus-visible {
|
|
2538
|
+
outline: none;
|
|
2539
|
+
box-shadow: inset 0 0 0 2px var(--accent);
|
|
2540
|
+
}
|
|
2541
|
+
.ds-247420 .ds-field input:disabled,
|
|
2542
|
+
.ds-247420 .ds-field textarea:disabled,
|
|
2543
|
+
.ds-247420 .ds-field .ds-select:disabled {
|
|
2544
|
+
opacity: .55;
|
|
2545
|
+
cursor: not-allowed;
|
|
2546
|
+
}
|
|
2547
|
+
.ds-247420 .ds-field input[aria-invalid="true"],
|
|
2548
|
+
.ds-247420 .ds-field textarea[aria-invalid="true"] {
|
|
2549
|
+
box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--flame, #d64545);
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2401
2552
|
/* Clear button for text inputs */
|
|
2402
2553
|
.ds-247420 input[type="text"]:not(:placeholder-shown) + .input-clear,
|
|
2403
2554
|
.ds-247420 input[type="email"]:not(:placeholder-shown) + .input-clear,
|
|
@@ -2446,9 +2597,10 @@
|
|
|
2446
2597
|
}
|
|
2447
2598
|
.ds-247420 .skip-to-main:focus { top: 10px; }
|
|
2448
2599
|
|
|
2449
|
-
/* Reduced motion preferences
|
|
2600
|
+
/* Reduced motion preferences — scoped to the DS surface so it doesn't reach
|
|
2601
|
+
into and neutralize the host document's own motion. */
|
|
2450
2602
|
@media (prefers-reduced-motion: reduce) {
|
|
2451
|
-
.ds-247420 * {
|
|
2603
|
+
.ds-247420 *, .ds-247420 .app * {
|
|
2452
2604
|
animation-duration: 0.01ms !important;
|
|
2453
2605
|
animation-iteration-count: 1 !important;
|
|
2454
2606
|
transition-duration: 0.01ms !important;
|
|
@@ -2456,17 +2608,14 @@
|
|
|
2456
2608
|
}
|
|
2457
2609
|
|
|
2458
2610
|
/* ────────────────────────────────────────────────────────────
|
|
2459
|
-
Performance
|
|
2611
|
+
Performance
|
|
2460
2612
|
────────────────────────────────────────────────────────────── */
|
|
2461
2613
|
|
|
2462
|
-
/*
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
/* Contain layout repaints on self-contained components */
|
|
2468
|
-
.ds-247420 .panel, .ds-247420 .row, .ds-247420 .chip, .ds-247420 .btn, .ds-247420 button {
|
|
2469
|
-
contain: layout style paint;
|
|
2614
|
+
/* Limit layout/style containment to self-contained components. `paint` is
|
|
2615
|
+
intentionally omitted — it clips focus rings, tooltips and dropdowns that
|
|
2616
|
+
emanate from a contained .row/.btn. */
|
|
2617
|
+
.ds-247420 .panel, .ds-247420 .row {
|
|
2618
|
+
contain: layout style;
|
|
2470
2619
|
}
|
|
2471
2620
|
|
|
2472
2621
|
/* ────────────────────────────────────────────────────────────
|
|
@@ -2475,11 +2624,13 @@
|
|
|
2475
2624
|
|
|
2476
2625
|
@media (hover: none) and (pointer: coarse) {
|
|
2477
2626
|
/* Mobile devices: larger touch targets, faster responses */
|
|
2478
|
-
.ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost, .ds-247420 button, .ds-247420 a.row, .ds-247420[role="button"] {
|
|
2627
|
+
.ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost, .ds-247420 button, .ds-247420 a.row, .ds-247420[role="button"], .ds-247420 .ds-icon-btn, .ds-247420 .composer-btn {
|
|
2479
2628
|
min-height: 48px;
|
|
2480
2629
|
min-width: 48px;
|
|
2481
2630
|
padding: 12px 20px;
|
|
2482
2631
|
}
|
|
2632
|
+
/* Icon buttons stay square — the padding bump above would distort them. */
|
|
2633
|
+
.ds-247420 .ds-icon-btn, .ds-247420 .composer-btn { padding: 0; }
|
|
2483
2634
|
|
|
2484
2635
|
/* Remove hover effects on touch devices (use active instead) */
|
|
2485
2636
|
.ds-247420 .btn:hover, .ds-247420 .btn-primary:hover, .ds-247420 .btn-ghost:hover {
|
|
@@ -2502,12 +2653,9 @@
|
|
|
2502
2653
|
Theme Transition Smoothness
|
|
2503
2654
|
────────────────────────────────────────────────────────────── */
|
|
2504
2655
|
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
}
|
|
2509
|
-
|
|
2510
|
-
.ds-247420 body {
|
|
2656
|
+
/* Scoped to the DS wrapper so the design system never reaches out and
|
|
2657
|
+
animates the host document's html/body. */
|
|
2658
|
+
.ds-247420, .ds-247420 .app {
|
|
2511
2659
|
transition: background-color var(--dur-base) var(--ease),
|
|
2512
2660
|
color var(--dur-base) var(--ease);
|
|
2513
2661
|
}
|
|
@@ -2743,12 +2891,17 @@
|
|
|
2743
2891
|
padding: 10px 12px;
|
|
2744
2892
|
}
|
|
2745
2893
|
.ds-247420 .app-side .group { width: 100%; }
|
|
2746
|
-
|
|
2894
|
+
/* Keep the crumb on mobile — apps mount contextual controls (model picker,
|
|
2895
|
+
actions, live status) in crumb-right, so hiding it strands them. Collapse
|
|
2896
|
+
the breadcrumb trail/leaf instead and let the right cluster wrap. */
|
|
2897
|
+
.ds-247420 .app-crumb { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 8px 12px; }
|
|
2898
|
+
.ds-247420 .app-crumb > .sep, .ds-247420 .app-crumb > span:not(.crumb-right):not(.leaf) { display: none; }
|
|
2899
|
+
.ds-247420 .app-crumb .crumb-right { margin-left: 0; }
|
|
2747
2900
|
.ds-247420 .chat-head { padding: var(--space-2) var(--space-3) var(--space-2); margin-bottom: var(--space-2); }
|
|
2748
2901
|
.ds-247420 .app-main { padding-left: var(--space-3); padding-right: var(--space-3); }
|
|
2749
2902
|
}
|
|
2750
2903
|
|
|
2751
|
-
/* Drawer scrim */
|
|
2904
|
+
/* Drawer scrim — lives inside .app-body, shown when drawer open ≤900px */
|
|
2752
2905
|
.ds-247420 .app-side-scrim {
|
|
2753
2906
|
display: none;
|
|
2754
2907
|
position: fixed; inset: 0;
|
|
@@ -2756,8 +2909,41 @@
|
|
|
2756
2909
|
z-index: 49;
|
|
2757
2910
|
}
|
|
2758
2911
|
@media (max-width: 900px) {
|
|
2759
|
-
.ds-247420 .app-body.side-open
|
|
2760
|
-
|
|
2912
|
+
.ds-247420 .app-body.side-open .app-side-scrim { display: block; }
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
/* Mobile nav toggle (hamburger) — hidden on desktop, shown ≤900px */
|
|
2916
|
+
.ds-247420 .app-side-toggle {
|
|
2917
|
+
display: none;
|
|
2918
|
+
position: fixed; top: calc((var(--app-topbar-h) - 32px) / 2); left: 10px;
|
|
2919
|
+
z-index: 51;
|
|
2920
|
+
width: 36px; height: 36px;
|
|
2921
|
+
align-items: center; justify-content: center;
|
|
2922
|
+
font-size: 18px; line-height: 1;
|
|
2923
|
+
background: var(--bg-2); color: var(--fg);
|
|
2924
|
+
border: 1px solid var(--rule, color-mix(in oklab, var(--fg) 12%, transparent));
|
|
2925
|
+
border-radius: var(--r-1, 6px);
|
|
2926
|
+
cursor: pointer;
|
|
2927
|
+
}
|
|
2928
|
+
.ds-247420 .app-side-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
2929
|
+
@media (max-width: 900px) {
|
|
2930
|
+
.ds-247420 .app-side-toggle { display: inline-flex; }
|
|
2931
|
+
.ds-247420 .app-topbar .brand { margin-left: 44px; }
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
/* Desktop: the app shell is exactly viewport-height and contains its own
|
|
2935
|
+
scroll, so only .app-main (and the side rail) scroll — never the page too.
|
|
2936
|
+
Pinning .app to 100dvh + overflow:hidden is what prevents the double
|
|
2937
|
+
scrollbar that a min-height:100vh shell + inner overflow:auto produces.
|
|
2938
|
+
.app-body fills the gap between topbar/crumb and status via flex:1 rather
|
|
2939
|
+
than a hand-computed calc() that drifts from the real chrome heights. */
|
|
2940
|
+
@media (min-width: 901px) {
|
|
2941
|
+
.ds-247420 .app { height: 100dvh; min-height: 0; overflow: hidden; }
|
|
2942
|
+
/* Embedded shell (freddie WM window) fills its container, not the viewport. */
|
|
2943
|
+
.ds-247420 .fd-root .app { height: 100%; overflow: visible; }
|
|
2944
|
+
.ds-247420 .app-body { min-height: 0; flex: 1 1 auto; }
|
|
2945
|
+
.ds-247420 .app-side-shell { overflow-y: auto; min-height: 0; }
|
|
2946
|
+
.ds-247420 .app-main { overflow-y: auto; min-height: 0; }
|
|
2761
2947
|
}
|
|
2762
2948
|
|
|
2763
2949
|
/* Mobile (≤480) status bar compact; hide tail item */
|
|
@@ -4303,6 +4489,8 @@
|
|
|
4303
4489
|
.ds-247420 .fd-chat { display: flex; flex-direction: column; gap: var(--space-2, 10px); height: 100%; min-height: 0; }
|
|
4304
4490
|
.ds-247420 .fd-chat-thread { flex: 1 1 auto; min-height: 240px; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-2, 10px); padding: var(--space-2, 10px); }
|
|
4305
4491
|
.ds-247420 .fd-page-error { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
4492
|
+
/* Visually-hidden polite live region — announces async busy/done to SR users. */
|
|
4493
|
+
.ds-247420 .fd-sr-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
4306
4494
|
/* page-level responsive: tighten padding on narrow viewports */
|
|
4307
4495
|
@media (max-width: 640px) {
|
|
4308
4496
|
.ds-247420 .fd-page-inner { padding: var(--space-2, 10px); gap: var(--space-2, 10px); }
|