@chenacc/agentbridge 0.1.0 → 0.1.2

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/public/styles.css CHANGED
@@ -1,1073 +1,1073 @@
1
- /* AgentBridge — sx-glass L2 皮肤
2
- 设计参数来源:D:\ocean-glass-ui\sx-glass-component-kit-v2.html
3
- 核心配方:132.39° 白灰渐变玻璃 + blur(13.44px) saturate(135%)
4
- + 8 层拟态阴影 + ::before Rim 描边 + ::after 顶部光环
5
- + Inter 斜体 800 标签 + 胶囊圆角 + Type G 旋钮阴影 */
6
-
7
- :root {
8
- color-scheme: light;
9
- --ink: #2a2a3a;
10
- --ink-2: rgba(0, 0, 0, 0.6);
11
- --ink-3: rgba(0, 0, 0, 0.45);
12
- --line: rgba(0, 0, 0, 0.08);
13
- --accent: rgba(0, 140, 220, 0.9);
14
- --accent-bright: rgba(0, 179, 255, 0.9);
15
- --ok: rgba(0, 170, 140, 0.85);
16
- --warn: rgba(220, 150, 0, 0.85);
17
- --err: rgba(220, 60, 60, 0.85);
18
- --focus: rgba(0, 179, 255, 0.35);
19
-
20
- --halo: linear-gradient(90deg, transparent, rgba(255,255,255,1) 18%, rgba(255,255,255,0.6) 50%, rgba(255,255,255,1) 82%, transparent);
21
- --knob-shadow:
22
- -4px -4px 6px rgba(128,128,128,0.25),
23
- 4px 4px 6px rgba(0,0,0,0.25),
24
- -8px -8px 20px rgba(255,255,255,0.6),
25
- 8px 8px 20px rgba(128,128,128,0.6),
26
- inset 2px 2px 10px rgba(255,255,255,0.25),
27
- inset -2px -2px 10px rgba(0,0,0,0.25);
28
- --knob-glow: radial-gradient(circle at 32% 26%, rgba(255,255,255,0.5), transparent 55%);
29
- --solid-glass: linear-gradient(132.39deg, #FFFFFF 15.21%, #808080 89.39%);
30
-
31
- --glass-bg: linear-gradient(132.39deg, rgba(255,255,255,0.474) 15.21%, rgba(128,128,128,0.412) 89.39%);
32
- --glass-bg-strong: linear-gradient(132.39deg, rgba(255,255,255,0.62) 15.21%, rgba(128,128,128,0.5) 89.39%);
33
- --glass-blur: blur(13.44px) saturate(135%);
34
- --panel-shadow:
35
- -6px -6px 36px rgba(255,255,255,0.96),
36
- 6px 6px 36px rgba(0,0,0,0.39),
37
- inset -9.92px -9.92px 11.33px rgba(255,255,255,0.432),
38
- inset 9.92px 9.92px 11.33px rgba(0,0,0,0.24),
39
- inset 3px 3px 6px rgba(0,0,0,0.12),
40
- inset -3px -3px 6px rgba(255,255,255,0.30),
41
- inset 2px 2px 6px rgba(0,0,0,0.2),
42
- inset -2px -2px 6px rgba(255,255,255,0.5);
43
- --mini-shadow:
44
- -3px -3px 6px rgba(255,255,255,0.6),
45
- 3px 3px 6px rgba(128,128,128,0.4),
46
- inset 3px 3px 6px rgba(0,0,0,0.10),
47
- inset -3px -3px 6px rgba(255,255,255,0.35);
48
- --btn-shadow:
49
- -6px -6px 36px rgba(255,255,255,0.96),
50
- 6px 6px 36px rgba(0,0,0,0.39),
51
- inset -7px -6px 10px rgba(255,255,255,1),
52
- inset 9px 9px 15px rgba(0,0,0,0.38);
53
- --icon-btn-shadow:
54
- -6px -6px 36px rgba(255,255,255,0.96),
55
- 6px 6px 36px rgba(0,0,0,0.39),
56
- inset -4px -4px 8px rgba(255,255,255,0.91),
57
- inset 6px 6px 14px rgba(0,0,0,0.51);
58
- --btn-press-shadow: inset 4px 4px 8px rgba(0,0,0,0.22), inset -4px -4px 8px rgba(255,255,255,0.4);
59
-
60
- --radius: 20px;
61
- font-family: "Inter", "Noto Sans SC", "Microsoft YaHei UI", system-ui, ui-sans-serif, sans-serif;
62
- background: #cfcfcf;
63
- color: var(--ink-2);
64
- }
65
-
66
- * { box-sizing: border-box; }
67
- /* Android / 微信 webview 的"文字自动放大"(text autosizing)会把成块的正文文字放大,
68
- 而本项目大量使用 nowrap 的徽标与标签——文字被放大后比容器还宽,整页就横着顶出屏幕
69
- (真机上标题、模型行、输入框一起被切掉,桌面上永远复现不出来)。这里显式关掉自动放大,
70
- 再配合 `.session-view` 的可收缩网格列兜底。 */
71
- html {
72
- -webkit-text-size-adjust: 100%;
73
- text-size-adjust: 100%;
74
- }
75
- html, body { min-height: 100%; overflow-x: hidden; }
76
- /* 底色放在 html 上、body 保持透明:html 带 overflow:hidden 时 body 的背景不再传播到画布,
77
- 而是被当成普通盒子背景绘制——普通盒子的背景会盖住 z-index 为负的固定层,
78
- 背景照片之前就是被这层灰盖掉的。 */
79
- html { background-color: #cfcfcf; }
80
- body { margin: 0; background: transparent; }
81
-
82
- /* ---------- 全屏背景:照片原样铺满 + 整页"提亮地板"遮罩 ---------- */
83
- /* 照片按 cover 铺满视口——竖屏手机裁掉两侧,横屏桌面裁掉上下——原样呈现,不做 blur:
84
- 此前的 blur(1.5px) 正是"背景像素变低、看不清"的原因。
85
- 遮罩不用半透明白纱(那会把照片整体压平、色度掉一半),而是用 lighten 混合给它一个
86
- "地板色":比地板亮的照片像素**逐像素不动**(纹理、边缘、高光都在),比地板暗的抬到
87
- 地板。于是整页任意位置文字背后的亮度是同一个值,正文对比可以精确算出来。 */
88
- :root {
89
- /* 整页遮罩:一层均匀白纱,α 是唯一参数,没有混合模式、没有蒙版、没有第二种颜色。
90
- 实测(正文最差处,三档视口):α 0.55 → 5.74–6.11:1、**0.58 → 6.28–6.69:1**、0.62 → 7.09–7.46:1。
91
- 取 0.58:正文过 6:1(低于这条线文字会发虚,这是之前实测出来的),同时保住画面。
92
- 它对整幅图均匀生效——雪面也会被冲淡(色度只剩 42%),这就是"简单"换来的代价。 */
93
- --bg-scrim-veil: rgba(255, 255, 255, 0.58);
94
- --bg-scrim-veil-solid: rgba(255, 255, 255, 0.72); /* 减少透明/要求更高对比时更实 */
95
- }
96
- body::before {
97
- content: "";
98
- position: fixed;
99
- inset: 0;
100
- z-index: -2;
101
- background-color: #cfcfcf;
102
- background-image: url("/background.jpg");
103
- background-size: cover;
104
- /* 原图铺满裁切。素材 2048×1152(16:9):竖屏手机和宽屏桌面都是**横向**裁切、纵向正好铺满,
105
- 所以只有横向位置有意义;居中即 `center`。 */
106
- background-position: center;
107
- background-repeat: no-repeat;
108
- }
109
- body::after {
110
- content: "";
111
- position: fixed;
112
- inset: 0;
113
- z-index: -1;
114
- pointer-events: none;
115
- /* 一层白纱,没有混合模式、没有蒙版:照片在下、半透明白在上,整幅均匀压亮。 */
116
- background: var(--bg-scrim-veil);
117
- }
118
- @media (prefers-reduced-transparency: reduce) {
119
- body::after { background: var(--bg-scrim-veil-solid); }
120
- }
121
- @media (prefers-contrast: more) {
122
- body::after { background: var(--bg-scrim-veil-solid); }
123
- }@media (min-width: 781px) {
124
- /* 宽屏只裁掉左右各约一成,取景几乎等于整幅:用同一横向锚点,避免宽窄屏构图跳变。
125
- 纵向没有可裁空间(16:9 铺满 16:10 视口高度),所以不需要第二套纵向值。 */
126
- body::before { background-position: center; }
127
- }
128
-
129
-
130
- button, input, select, textarea { font: inherit; }
131
- button, select { min-height: 44px; }
132
- button { cursor: pointer; }
133
- button:disabled { cursor: not-allowed; opacity: .55; }
134
- button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, a:focus-visible {
135
- outline: 0;
136
- box-shadow: 0 0 0 3px var(--focus), var(--mini-shadow);
137
- }
138
- ::selection { background: var(--accent); color: white; }
139
- ::-webkit-scrollbar { width: 10px; height: 10px; }
140
- ::-webkit-scrollbar-thumb { background: linear-gradient(132.39deg, rgba(255,255,255,0.7), rgba(128,128,128,0.6)); border: 3px solid #cfcfcf; border-radius: 10px; }
141
- svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
142
- .icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
143
- .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
144
- [hidden] { display: none !important; }
145
-
146
- /* ---------- 共享玻璃基底(面板级:Rim + 顶部光环) ---------- */
147
- .pairing-strip, .return-entry, .composer, .toast, .approval-entry, .glass-popover, .drawer-card,
148
- .primary-button, .icon-button, .send-button, .access-form input {
149
- position: relative;
150
- isolation: isolate;
151
- }
152
- .pairing-strip::before, .return-entry::before, .composer::before, .toast::before,
153
- .glass-popover::before, .drawer-card::before,
154
- .primary-button::before, .icon-button::before, .send-button::before {
155
- content: "";
156
- position: absolute;
157
- inset: 0;
158
- border-radius: inherit;
159
- pointer-events: none;
160
- z-index: 5;
161
- box-shadow:
162
- inset 0 1px 0 rgba(255,255,255,1.00),
163
- inset 0 -1px 0 rgba(0,0,0, 0.45),
164
- inset 1px 0 0 rgba(255,255,255,0.36),
165
- inset -1px 0 0 rgba(0,0,0, 0.24);
166
- }
167
- .pairing-strip::after, .return-entry::after, .composer::after,
168
- .glass-popover::after, .drawer-card::after,
169
- .primary-button::after, .icon-button::after, .send-button::after {
170
- content: "";
171
- position: absolute;
172
- top: 3px;
173
- left: 24px;
174
- right: 24px;
175
- height: 2px;
176
- border-radius: 1px;
177
- pointer-events: none;
178
- z-index: 6;
179
- background: var(--halo);
180
- }
181
- .pairing-strip > *, .return-entry > *, .toast > *,
182
- .glass-popover > *, .drawer-card > *,
183
- .primary-button > *, .icon-button > *, .send-button > * { position: relative; z-index: 2; }
184
- /* The composer contains an sr-only label that must stay absolutely positioned;
185
- lifting it into the grid would steal the first cell and shrink the textarea. */
186
- .composer textarea, .composer .send-button { position: relative; z-index: 2; }
187
-
188
- .app-shell { min-height: 100vh; min-height: 100dvh; }
189
-
190
- /* ---------- 顶栏:浮动胶囊玻璃导航 ---------- */
191
- .topbar {
192
- position: sticky;
193
- top: 10px;
194
- z-index: 10;
195
- max-width: 1180px;
196
- margin: 10px auto 0;
197
- min-height: 54px;
198
- display: grid;
199
- grid-template-columns: 1fr auto 1fr;
200
- align-items: center;
201
- gap: 20px;
202
- padding: 6px 12px;
203
- border-radius: 100px;
204
- background: var(--glass-bg);
205
- -webkit-backdrop-filter: var(--glass-blur);
206
- backdrop-filter: var(--glass-blur);
207
- box-shadow: var(--panel-shadow);
208
- }
209
- .brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); text-decoration: none; font-weight: 800; font-style: italic; letter-spacing: -.02em; padding: 4px 10px; }
210
- .brand-mark, .pairing-mark { display: grid; place-items: center; background: var(--solid-glass); color: var(--ink); font-weight: 800; font-style: italic; letter-spacing: -.04em; box-shadow: var(--knob-shadow); }
211
- .brand-mark { width: 34px; height: 34px; border-radius: 12px; font-size: 12px; }
212
- .connection { display: inline-flex; align-items: center; gap: 8px; font-size: 11px; font-style: italic; font-weight: 800; color: var(--ink-2); padding: 6px 14px; border-radius: 100px; background: var(--glass-bg); box-shadow: var(--mini-shadow); font-variant-numeric: tabular-nums; }
213
- .connection-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--warn); }
214
- .connection.online .connection-dot { background: var(--ok); }
215
- .connection.offline .connection-dot { background: var(--err); }
216
- .machine-name { justify-self: end; color: var(--ink-3); font-size: 11px; font-style: italic; font-weight: 800; letter-spacing: .06em; padding-right: 10px; }
217
-
218
- /* ---------- 配对区:sx-glass 主面板 ---------- */
219
- .pairing-strip {
220
- max-width: 1180px;
221
- margin: 26px auto 0;
222
- padding: 24px 28px;
223
- display: flex;
224
- flex-wrap: wrap;
225
- justify-content: space-between;
226
- align-items: center;
227
- gap: 32px;
228
- border-radius: var(--radius);
229
- background: var(--glass-bg);
230
- -webkit-backdrop-filter: var(--glass-blur);
231
- backdrop-filter: var(--glass-blur);
232
- box-shadow: var(--panel-shadow);
233
- color: var(--ink);
234
- overflow: hidden;
235
- }
236
- .pairing-copy { width: 100%; min-width: 0; max-width: 680px; }
237
- .pairing-copy h2 { margin: 0 0 8px; font-size: clamp(22px, 3vw, 34px); letter-spacing: -.035em; font-weight: 800; font-style: italic; color: var(--ink); }
238
- .pairing-copy p { margin: 0 0 14px; color: var(--ink-2); line-height: 1.65; }
239
- .pairing-copy code { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; color: var(--accent); font-size: 12px; white-space: nowrap; }
240
- .pairing-strip img { width: 176px; height: 176px; background: white; padding: 8px; border-radius: 16px; flex: none; box-shadow: var(--mini-shadow); }
241
- .pairing-strip .return-qr-copy { min-width: 190px; }
242
- .return-qr-copy h3 { margin: 0 0 8px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
243
- .return-qr-copy p { margin: 0 0 12px; color: var(--ink-2); font-size: 13px; line-height: 1.55; }
244
- .return-qr-copy code { display: block; max-width: 190px; overflow: hidden; color: var(--accent); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
245
- .device-manager { width: 100%; border-top: 1px solid var(--line); padding-top: 14px; }
246
- .device-manager h3 { margin: 0 0 6px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
247
- .device-manager p { margin: 0 0 10px; color: var(--ink-2); font-size: 13px; }
248
- .device-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
249
- .device-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13px; font-weight: 600; color: var(--ink-2); padding: 9px 14px; border-radius: 100px; background: var(--glass-bg); box-shadow: var(--mini-shadow); }
250
- .device-row .device-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
251
- .device-revoke { padding: 0; min-height: 0; font-size: 12px; font-style: italic; font-weight: 800; color: var(--err); flex: none; white-space: nowrap; border: 0; background: transparent; }
252
- .device-empty { color: var(--ink-3); font-size: 13px; font-style: italic; }
253
- .pairing-strip #return-qr { width: 144px; height: 144px; }
254
- .notify-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
255
- .notify-row h3 { margin: 0 0 4px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
256
- .notify-row p { margin: 0; color: var(--ink-2); font-size: 13px; line-height: 1.5; }
257
- .notify-row button { flex: none; }
258
- @media (max-width: 780px) { .notify-row { flex-direction: column; align-items: stretch; gap: 10px; } }.bridge-shutdown { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; gap: 20px; }
259
- .bridge-shutdown > div { min-width: 0; }
260
- .bridge-shutdown h3 { margin: 0 0 6px; }
261
- .bridge-shutdown p { margin: 0; max-width: 72ch; }
262
- .bridge-shutdown .danger-button { flex: none; min-width: 154px; min-height: 44px; }
263
-
264
- /* ---------- 返回入口卡片 ---------- */
265
- .return-entry { max-width: 1180px; margin: 16px auto 0; padding: 16px 20px; display: flex; justify-content: space-between; align-items: center; gap: 20px; border-radius: var(--radius); background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); box-shadow: var(--panel-shadow); overflow: hidden; }
266
- .return-entry strong { font-size: 15px; font-style: italic; font-weight: 800; color: var(--ink); }
267
- .return-entry p { margin: 4px 0 8px; color: var(--ink-2); font-size: 13px; line-height: 1.5; }
268
- .return-entry code { display: block; max-width: min(700px, 72vw); overflow: hidden; color: var(--accent); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
269
- .text-button { border: 0; min-height: 0; padding: 8px 0 0; background: transparent; color: var(--accent); display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-style: italic; font-weight: 800; }
270
-
271
- /* ---------- 工作区 ---------- */
272
- .workspace { max-width: 1180px; margin: 26px auto; display: grid; grid-template-columns: minmax(250px, 310px) minmax(0, 1fr); min-height: calc(100vh - 120px); min-height: calc(100dvh - 120px); }
273
-
274
- /* 按钮:sx-btn 配方(白→蓝玻璃胶囊 + 拟态阴影 + 灰描边) */
275
- .primary-button, .secondary-button, .danger-button {
276
- border: 1.92px solid rgba(171,171,171,1);
277
- border-radius: 100px;
278
- padding: 0 24px;
279
- min-height: 42px;
280
- font-size: 12px;
281
- font-style: italic;
282
- font-weight: 800;
283
- color: var(--ink);
284
- background: linear-gradient(132deg, rgba(255,255,255,0.48), rgba(0,119,179,0.41));
285
- -webkit-backdrop-filter: blur(13px) saturate(135%);
286
- backdrop-filter: blur(13px) saturate(135%);
287
- box-shadow: var(--btn-shadow);
288
- transition: transform .15s ease, filter .15s ease, box-shadow .2s ease;
289
- display: inline-flex;
290
- gap: 8px;
291
- align-items: center;
292
- justify-content: center;
293
- overflow: hidden;
294
- white-space: nowrap;
295
- }
296
- .primary-button:hover, .secondary-button:hover, .danger-button:hover { transform: translateY(-2px) scale(1.02); filter: brightness(1.05); }
297
- .primary-button:active, .secondary-button:active, .danger-button:active { transform: scale(0.97); box-shadow: var(--btn-press-shadow); }
298
- .primary-button { background: linear-gradient(0deg, rgba(0,179,255,0.25), rgba(0,179,255,0.25)), linear-gradient(132.39deg, rgba(255,255,255,0.6) 15.21%, rgba(128,128,128,0.5) 89.39%); }
299
- .secondary-button { background: rgba(255,255,255,0.22); border-color: transparent; box-shadow: inset 0 0 0 1.5px rgba(255,255,255,0.65), -4px -4px 12px rgba(255,255,255,0.5), 4px 4px 12px rgba(90,100,120,0.18); }
300
- .danger-button { background: linear-gradient(132.39deg, rgba(255,175,175,0.6), rgba(215,110,110,0.45)); color: var(--err); }
301
- .danger-button.confirming { background: linear-gradient(132.39deg, rgba(235,90,90,0.85), rgba(190,40,40,0.85)); color: white; }
302
- .icon-button { width: 44px; min-height: 44px; border: 1.92px solid rgba(177,175,175,1); border-radius: 100px; background: linear-gradient(132deg, rgba(255,255,255,0.48), rgba(0,119,179,0.41)); color: var(--ink); display: grid; place-items: center; box-shadow: var(--icon-btn-shadow); transition: transform .15s ease, filter .15s ease; overflow: hidden; }
303
- .icon-button:hover { transform: translateY(-2px) scale(1.06); }
304
- .icon-button:active { transform: scale(0.94); }
305
- .icon-button svg { width: 18px; height: 18px; }
306
-
307
- /* 表单字段:sx-glass-field 卡片式凸起玻璃 */
308
- select, input, textarea {
309
- width: 100%;
310
- border: 1px solid rgba(171,171,171,0.6);
311
- border-radius: 100px;
312
- background: linear-gradient(132.39deg, rgba(255,255,255,0.62), rgba(128,128,128,0.5));
313
- color: var(--ink);
314
- font-size: 13px;
315
- box-shadow: var(--mini-shadow);
316
- }
317
- select:focus-visible, input:focus-visible, textarea:focus-visible { box-shadow: 0 0 0 3px var(--focus), var(--mini-shadow); }
318
- select, input { height: 46px; padding: 0 16px; }
319
- textarea { border-radius: 18px; }
320
- select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%), linear-gradient(135deg, var(--ink-3) 50%, transparent 50%), linear-gradient(132.39deg, rgba(255,255,255,0.62), rgba(128,128,128,0.5)); background-position: calc(100% - 19px) 50%, calc(100% - 14px) 50%, 0 0; background-size: 5px 5px, 5px 5px, 100% 100%; background-repeat: no-repeat; }
321
- ::placeholder { color: var(--ink-3); font-style: italic; }
322
- .form-note { margin: 0; color: var(--ink-3); font-size: 12px; line-height: 1.5; font-style: italic; }
323
-
324
- /* 会话列表:sx-list 配方 */
325
- .status-mark { width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--ink-3); }
326
- .status-mark.running, .status-mark.starting { background: var(--warn); }
327
- /* 停止中 is still an open turn, only with its end requested: the same warning
328
- family, a step quieter so the two states read differently at a glance. */
329
- .status-mark.stopping { background: var(--warn); opacity: .55; }
330
- .status-mark.ready { background: var(--ok); }
331
- .status-mark.failed, .status-mark.offline { background: var(--err); }
332
-
333
- /* ---------- 会话区 / 事件时间线 ---------- */
334
- .conversation { min-width: 0; }
335
- .empty-state { min-height: 480px; display: grid; place-content: center; justify-items: start; padding: 40px clamp(24px, 8vw, 100px); }
336
- .empty-rule { width: 84px; height: 6px; border-radius: 100px; background: linear-gradient(90deg, var(--accent-bright), var(--accent)); box-shadow: var(--mini-shadow); margin-bottom: 24px; border: 0; }
337
- .empty-state h2 { margin: 0 0 10px; font-size: clamp(28px, 5vw, 54px); letter-spacing: -.04em; font-weight: 800; font-style: italic; color: var(--ink); }
338
- .empty-state p { max-width: 52ch; margin: 0; color: var(--ink-2); line-height: 1.7; }
339
- /* 行号必须钉死。会话视图里有一个"有时才出现"的子元素(加载更早),靠自动放置的话
340
- 它一出现就顶替掉 1fr 那一行:加载条被撑成 320px 的巨型胶囊,日志反而被挤到 auto 行
341
- (撑不到应有的高度)。显式 grid-row 让可选子元素的出现/消失不影响日志拿到 1fr。
342
- 列也必须写成 minmax(0, 1fr):隐式 auto 列的下限是 min-content,头部那串 nowrap 徽标
343
- (DEEPSPEK-HARNESS-DESKTOP + LOCAL-BOUJOY-HARNESS-MAIN-…)会把它顶到 356px,
344
- 于是整个会话视图比手机屏还宽——标题、模型行、输入框一起被切在屏幕外。 */
345
- .session-view { min-height: calc(100vh - 120px); min-height: calc(100dvh - 120px); display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto minmax(320px, 1fr) auto; }
346
- .session-view > .session-header { grid-row: 1; }
347
- .session-view > .history-more { grid-row: 2; }
348
- .session-view > .event-log { grid-row: 3; }
349
- .session-view > .composer { grid-row: 4; }
350
- /* 头部子元素允许收缩:超出的 nowrap 文本由自己裁掉,而不是把整列顶宽。 */
351
- .session-header > * { min-width: 0; }
352
- .session-header { padding: 24px 0 22px 4px; display: flex; justify-content: space-between; gap: 24px; align-items: flex-end; }
353
- .session-header h2 { margin: 5px 0; font-size: clamp(24px, 4vw, 38px); letter-spacing: -.035em; font-weight: 800; font-style: italic; color: var(--ink); }
354
- .session-error { max-width: 720px; margin: 10px 0 0; padding: 12px 14px; border-radius: 18px; background: linear-gradient(176deg, rgba(255,255,255,0.55), rgba(215,120,120,0.4)); box-shadow: var(--mini-shadow); border: 1px solid rgba(220,60,60,0.35); color: var(--err); font-size: 13px; line-height: 1.55; overflow-wrap: anywhere; }
355
- /* "桌面端没连上"不是已经执行失败,只是还没接上:同一条消息槽,换成中性玻璃卡片,
356
- 红色警报留给真正失败的东西。 */
357
- .session-error.hint { background: var(--glass-bg-strong); border: 1.92px solid rgba(171, 171, 171, .8); box-shadow: var(--panel-shadow); color: var(--ink); }
358
- .session-meta { display: flex; gap: 8px; color: var(--accent); font-size: 10px; font-weight: 800; font-style: italic; letter-spacing: .1em; text-transform: uppercase; }
359
- #control-status { margin: 0; color: var(--ink-3); font-size: 12px; font-style: italic; font-weight: 600; }
360
- .session-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
361
- .model-control { display: grid; grid-template-columns: minmax(150px, 220px) minmax(112px, 150px) auto; gap: 10px; align-items: end; }
362
- .model-control label { display: grid; gap: 4px; color: var(--ink-3); font-size: 10px; font-weight: 800; font-style: italic; letter-spacing: .08em; text-transform: uppercase; }
363
- .model-control select { min-width: 0; }
364
- .model-control small { grid-column: 1 / -1; color: var(--ink-3); font-size: 11px; line-height: 1.4; font-style: italic; }
365
-
366
- .event-log { min-height: 320px; max-height: calc(100vh - 290px); max-height: calc(100dvh - 290px); overflow-y: auto; padding: 24px 0 40px 4px; }
367
- .event-entry { display: grid; grid-template-columns: 74px minmax(0, 1fr); gap: 16px; padding: 9px 0; align-items: start; }
368
- .event-time { color: var(--ink-2); font-size: 11px; font-weight: 700; letter-spacing: .06em; font-variant-numeric: tabular-nums; padding-top: 4px; }
369
- .event-body { max-width: 72ch; line-height: 1.62; overflow-wrap: anywhere; color: var(--ink-2); }
370
- .event-body p { margin: 0; white-space: pre-wrap; }
371
- .event-body strong { display: block; margin-bottom: 3px; font-size: 11px; font-weight: 800; font-style: italic; letter-spacing: .06em; color: var(--accent); }
372
- .message-markdown { min-width: 0; color: inherit; }
373
- .message-markdown > :first-child { margin-top: 0; }
374
- .message-markdown > :last-child { margin-bottom: 0; }
375
- .message-markdown p { margin: 0 0 10px; white-space: normal; }
376
- .message-markdown h1, .message-markdown h2, .message-markdown h3 { margin: 16px 0 8px; color: var(--ink); line-height: 1.25; letter-spacing: -.02em; font-style: italic; }
377
- .message-markdown h1 { font-size: 22px; }
378
- .message-markdown h2 { font-size: 19px; }
379
- .message-markdown h3 { font-size: 16px; }
380
- .message-markdown ul, .message-markdown ol { margin: 8px 0 12px; padding-left: 1.35em; }
381
- .message-markdown li + li { margin-top: 4px; }
382
- .message-markdown code { padding: 2px 8px; border-radius: 100px; background: linear-gradient(132.39deg, rgba(150,210,255,0.5), rgba(80,150,220,0.35)); color: #0a3a66; font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; font-size: .9em; }
383
- .message-markdown pre { margin: 12px 0; padding: 14px 16px; overflow-x: auto; border-radius: 16px; background: linear-gradient(132.39deg, #3a4150, #23272f); color: #f5f1e8; line-height: 1.55; white-space: pre; box-shadow: var(--mini-shadow); }
384
- .message-markdown pre code { padding: 0; background: transparent; color: inherit; font-size: 12px; }
385
- .message-markdown blockquote { margin: 10px 0; padding: 8px 14px; border-radius: 12px; background: rgba(255,255,255,0.4); box-shadow: inset 2px 2px 4px rgba(0,0,0,0.08), inset -2px -2px 4px rgba(255,255,255,0.5); color: var(--ink-2); }
386
- .message-markdown hr { margin: 16px 0; border: 0; border-top: 1.5px solid rgba(120,130,140,0.35); }
387
-
388
- /* 代码块:独立卡片,语言标记 + 复制,横向滚动不撑破页面 */
389
- .md-code { margin: 12px 0; border-radius: 16px; overflow: hidden; background: linear-gradient(132.39deg, #333a47, #1f232a); box-shadow: var(--mini-shadow); }
390
- .md-code-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 8px 6px 12px; background: rgba(255,255,255,0.06); }
391
- .md-code-lang { font-size: 10px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: rgba(245,241,232,0.72); font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; }
392
- .md-code-copy { min-height: 28px; padding: 0 12px; border-radius: 100px; border: 1px solid rgba(245,241,232,0.28); background: rgba(255,255,255,0.08); color: rgba(245,241,232,0.88); font-size: 11px; font-weight: 700; }
393
- .md-code-copy:active { transform: scale(0.96); }
394
- .md-code pre { margin: 0; border-radius: 0; box-shadow: none; background: transparent; padding: 12px 14px; }
395
-
396
- /* 表格:真实表格 + 自身横向滚动,数值列按对齐规则 */
397
- .md-table-wrap { margin: 12px 0; overflow-x: auto; border-radius: 14px; border: 1.4px solid rgba(150,160,170,0.35); background: rgba(255,255,255,0.55); -webkit-overflow-scrolling: touch; }
398
- .md-table { width: 100%; border-collapse: collapse; font-size: 12.5px; line-height: 1.45; }
399
- .md-table th, .md-table td { padding: 8px 10px; text-align: left; vertical-align: top; border-bottom: 1px solid rgba(150,160,170,0.28); }
400
- .md-table th { background: rgba(80,150,220,0.16); color: var(--ink); font-weight: 800; white-space: nowrap; }
401
- .md-table tbody tr:nth-child(even) { background: rgba(255,255,255,0.42); }
402
- .md-table tbody tr:last-child td { border-bottom: 0; }
403
- .md-table code { font-size: 11.5px; }
404
-
405
- /* 公式:行内跟随文字,块级单独居中且可横向滚动 */
406
- .message-markdown .math-tex { font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; }
407
- .md-math { margin: 12px 0; padding: 10px 12px; overflow-x: auto; border-radius: 14px; background: rgba(255,255,255,0.5); box-shadow: inset 0 1px 2px rgba(0,0,0,0.06); text-align: center; }
408
- .md-math .katex-display { margin: 0; }
409
- .md-math .katex { font-size: 1.05em; }
410
- .message-markdown .katex { font-size: 1.02em; }
411
- .event-entry.user .event-body { color: #0a3a66; font-weight: 650; }
412
- .event-entry.tool .event-body { color: var(--ink-2); font-size: 13px; } /* 底板是浅色玻璃,次级文字不能再用 45% 黑 */
413
- .event-entry.error .event-body { color: var(--err); }
414
-
415
- /* ---------- 无底板可读性:给字形描边,而不是给文字垫一层遮罩 ---------- */
416
- /* 文字层底板保持透明(用户要求),可读性全部来自整页遮罩的地板——**不再给字形描边**:
417
- 之前那圈 1px + 2px 的白色 text-shadow 会把每个字的边缘糊掉,这正是"文字很模糊"的来源。
418
- 地板亮度 0.321,下列颜色对它的实测对比都在 AA 之上,主文还过了 AAA——
419
- #14141c 6.47:1、#2b3038 4.69:1、#0a2f4d 4.9:1、#0d3049 4.84:1、#5f120f 4.65:1。
420
- 地板是浅灰蓝,彩色文字(原来的 accent 蓝、err 红)在上面只有 1.0–1.2:1,
421
- 所以色相只留一点,层次靠字重、字号与斜体。 */
422
- :root {
423
- --on-photo-ink: #14141c; /* 正文 */
424
- --on-photo-soft: #2b3038; /* 次级:时间列、工具输出、状态、空态说明 */
425
- --on-photo-label: #0d3049; /* 斜体标签 */
426
- --on-photo-user: #0a2f4d; /* 用户消息 */
427
- --on-photo-error: #5f120f; /* 异常行 */
428
- }
429
- .event-entry .event-body,
430
- .message-markdown h1,
431
- .message-markdown h2,
432
- .message-markdown h3,
433
- .session-header h2,
434
- .empty-state h2 { color: var(--on-photo-ink); }
435
- .event-entry.user .event-body { color: var(--on-photo-user); }
436
- .event-entry.tool .event-body,
437
- .event-time,
438
- .session-meta,
439
- #control-status,
440
- .empty-state p { color: var(--on-photo-soft); }
441
- .event-body strong { color: var(--on-photo-label); }
442
- .event-entry.error .event-body { color: var(--on-photo-error); }
443
-
444
- /* ------------------------------------------------------------------
445
- 弹层组件词表:所有"点开才出现"的浮层共用同一套配方
446
- — 132.39deg 玻璃底 + blur(13.44px) saturate(135%) + 1.92px 灰边框
447
- — panel-shadow、顶部光带、内描边(见文件开头的 .glass-popover::before/::after)
448
- 小标题统一为 11px / 800 / 斜体 / .06em 大写的 ink-3,与 .create-form label 一致。
449
- ------------------------------------------------------------------ */
450
- .glass-popover {
451
- /* 定位交给 JS:absolute 会把"很窄的触发按钮"当成包含块(手机端 .auto-approve 只有
452
- 按钮那么宽),面板于是整块向左溢出屏幕。fixed + 打开时按视口计算坐标,才能保证
453
- 永远落在手机框内,并且在下方放不下时翻到上方。 */
454
- position: fixed;
455
- z-index: 30;
456
- display: grid;
457
- gap: 10px;
458
- padding: 14px;
459
- border-radius: 20px;
460
- /* 兜底:即使脚本没跑或内容异常长,也不允许越过视口 */
461
- max-width: calc(100vw - 16px);
462
- max-height: calc(100dvh - 16px);
463
- overflow: auto;
464
- /* 与 .create-sheet 同一套:同样的玻璃底、同样的 blur(20px) saturate(140%)、
465
- 同样的 1.92px 灰边框 —— "点开才出现"的面板共用一种材质。 */
466
- background: var(--glass-bg-strong);
467
- -webkit-backdrop-filter: blur(20px) saturate(140%);
468
- backdrop-filter: blur(20px) saturate(140%);
469
- border: 1.92px solid rgba(171, 171, 171, .8);
470
- box-shadow: var(--panel-shadow);
471
- }
472
- .glass-popover[hidden] { display: none; }
473
-
474
- .field { display: grid; gap: 6px; }
475
- .field-label {
476
- color: var(--ink-3);
477
- font-size: 11px;
478
- font-weight: 800;
479
- font-style: italic;
480
- letter-spacing: .06em;
481
- text-transform: uppercase;
482
- }
483
-
484
- /* 分段控件:原生 radio 保留语义与键盘操作,视觉上换成玻璃胶囊 */
485
- .segmented {
486
- display: flex;
487
- gap: 4px;
488
- padding: 3px;
489
- border-radius: 100px;
490
- background: rgba(255, 255, 255, 0.34);
491
- box-shadow: inset 2px 2px 6px rgba(0, 0, 0, 0.10), inset -2px -2px 6px rgba(255, 255, 255, 0.55);
492
- }
493
- .segment { flex: 1; min-width: 0; position: relative; }
494
- .segment input { position: absolute; inset: 0; opacity: 0; margin: 0; pointer-events: none; }
495
- .segment span {
496
- display: grid;
497
- place-items: center;
498
- min-height: 34px;
499
- padding: 0 8px;
500
- border-radius: 100px;
501
- font-size: 12px;
502
- font-weight: 800;
503
- font-style: italic;
504
- color: var(--ink-2);
505
- transition: background .16s ease, color .16s ease, box-shadow .16s ease;
506
- }
507
- .segment input:checked + span {
508
- background: linear-gradient(0deg, rgba(0, 179, 255, 0.25), rgba(0, 179, 255, 0.25)),
509
- linear-gradient(132.39deg, rgba(255, 255, 255, 0.95) 15.21%, rgba(128, 128, 128, 0.55) 89.39%);
510
- color: var(--ink);
511
- box-shadow: inset 0 0 0 1.4px rgba(255, 255, 255, 0.85), 0 2px 6px rgba(0, 0, 0, 0.12);
512
- }
513
- .segment input:focus-visible + span { box-shadow: 0 0 0 3px var(--focus); }
514
-
515
- /* 开关:同样是"原生 checkbox + 玻璃轨道" */
516
- .switch { display: flex; align-items: center; gap: 10px; cursor: pointer; }
517
- .switch input { position: absolute; opacity: 0; pointer-events: none; }
518
- .switch-track {
519
- flex: none;
520
- position: relative;
521
- width: 44px;
522
- height: 26px;
523
- border-radius: 100px;
524
- background: rgba(255, 255, 255, 0.42);
525
- box-shadow: inset 2px 2px 6px rgba(0, 0, 0, 0.16), inset -2px -2px 6px rgba(255, 255, 255, 0.6);
526
- transition: background .18s ease;
527
- }
528
- .switch-knob {
529
- position: absolute;
530
- top: 3px;
531
- left: 3px;
532
- width: 20px;
533
- height: 20px;
534
- border-radius: 50%;
535
- background: var(--solid-glass);
536
- box-shadow: var(--knob-shadow);
537
- transition: transform .18s ease;
538
- }
539
- .switch input:checked + .switch-track { background: linear-gradient(0deg, rgba(0, 179, 255, 0.35), rgba(0, 179, 255, 0.35)), rgba(255, 255, 255, 0.5); }
540
- .switch input:checked + .switch-track .switch-knob { transform: translateX(18px); }
541
- .switch input:focus-visible + .switch-track { box-shadow: 0 0 0 3px var(--focus); }
542
- .switch-text { color: var(--ink-2); font-size: 12px; line-height: 1.45; }
543
-
544
- /* 选择器:隐藏原生 select(它仍是唯一的状态来源),点击弹出玻璃列表 */
545
- /* 轨道必须写成 minmax(0, 1fr):`auto` 轨道的下限是 min-content,模型名一长
546
- (DeepSeek · DeepSeek-V4-Flash-Vision-Exp 这类)就会把轨道顶到 358px,
547
- width:100% 的触发按钮跟着溢出自己的格子,直接盖住右边的推理强度与切换按钮。 */
548
- .picker { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; min-width: 0; }
549
- .picker-native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
550
- .picker-trigger {
551
- display: flex;
552
- align-items: center;
553
- justify-content: space-between;
554
- gap: 8px;
555
- width: 100%;
556
- min-width: 0;
557
- overflow: hidden;
558
- min-height: 40px;
559
- padding: 0 12px;
560
- border-radius: 14px;
561
- border: 1.4px solid rgba(171, 171, 171, .8);
562
- background: rgba(255, 255, 255, .6);
563
- color: var(--ink);
564
- font-size: 13px;
565
- font-weight: 700;
566
- text-align: left;
567
- }
568
- .picker-trigger:disabled { opacity: .55; }
569
- .picker-trigger[aria-expanded="true"] { box-shadow: 0 0 0 3px var(--focus); }
570
- .picker-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
571
- .picker-chevron { flex: none; width: 14px; height: 14px; color: var(--ink-3); transition: transform .16s ease; }
572
- .picker-trigger[aria-expanded="true"] .picker-chevron { transform: rotate(180deg); }
573
- .picker-panel { width: min(320px, calc(100vw - 16px)); max-height: min(60dvh, 320px); }
574
- .picker-search {
575
- width: 100%;
576
- height: 34px;
577
- min-height: 34px;
578
- padding: 0 12px;
579
- border-radius: 100px;
580
- border: 1.4px solid rgba(171, 171, 171, .7);
581
- background: rgba(255, 255, 255, .66);
582
- font-size: 12px;
583
- color: var(--ink);
584
- }
585
- .picker-options { display: grid; gap: 2px; overflow-y: auto; max-height: min(45dvh, 240px); padding-right: 2px; }
586
- .picker-option {
587
- display: grid;
588
- grid-template-columns: minmax(0, 1fr);
589
- min-height: 38px;
590
- padding: 8px 10px;
591
- border: 0;
592
- border-radius: 12px;
593
- background: transparent;
594
- color: var(--ink-2);
595
- font-size: 12.5px;
596
- font-weight: 600;
597
- text-align: left;
598
- }
599
- .picker-option:hover { background: rgba(255, 255, 255, .42); }
600
- .picker-option[aria-selected="true"] {
601
- background: var(--glass-bg);
602
- box-shadow: inset 0 0 0 1.6px rgba(0, 179, 255, .28);
603
- color: var(--ink);
604
- font-weight: 750;
605
- }
606
- .picker-empty { padding: 10px; color: var(--ink-3); font-size: 12px; font-style: italic; }
607
-
608
- /* 自动放行:与弹层词表共用配方,按钮沿用系统既有按钮 */
609
- .auto-approve { position: relative; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
610
- .auto-approve-panel { width: min(320px, calc(100vw - 16px)); }
611
- .auto-approve-lede, .auto-approve-note { margin: 0; color: var(--ink-2); font-size: 12px; line-height: 1.5; }
612
- .auto-approve-note { color: var(--ink-3); font-size: 11px; font-style: italic; }
613
- .auto-approve-panel .primary-button { width: 100%; justify-content: center; }
614
- .auto-approve-pill {
615
- display: inline-flex;
616
- align-items: center;
617
- gap: 8px;
618
- min-height: 34px;
619
- padding: 0 14px;
620
- border-radius: 100px;
621
- border: 1.6px solid rgba(177, 175, 175, 1);
622
- background: var(--glass-bg-strong);
623
- -webkit-backdrop-filter: var(--glass-blur);
624
- backdrop-filter: var(--glass-blur);
625
- box-shadow: var(--mini-shadow);
626
- color: var(--ink);
627
- font-size: 12px;
628
- font-weight: 800;
629
- font-style: italic;
630
- font-variant-numeric: tabular-nums;
631
- }
632
- .auto-approve-pill::before {
633
- content: "";
634
- width: 7px;
635
- height: 7px;
636
- border-radius: 50%;
637
- background: var(--ok);
638
- box-shadow: 0 0 0 3px rgba(0, 170, 140, .2);
639
- }
640
- .auto-approve-pill[hidden] { display: none; }
641
- /* 批准请求:sx-alert 配方 */
642
- .approval-entry {
643
- padding: 14px;
644
- border-radius: 25px;
645
- background: linear-gradient(176deg, rgba(255,255,255,0.55), rgba(189,197,127,0.35));
646
- box-shadow: -6px -6px 36px rgba(255,255,255,0.96), 6px 6px 36px rgba(0,0,0,0.25), inset -11px -11px 12px rgba(255,255,255,0.8), inset 11px 15px 8px rgba(0,0,0,0.12);
647
- border: 1.92px solid rgba(184,184,184,1);
648
- -webkit-backdrop-filter: blur(13px) saturate(135%);
649
- backdrop-filter: blur(13px) saturate(135%);
650
- color: var(--ink);
651
- }
652
- .approval-entry strong { color: var(--warn); }
653
- .approval-actions { display: flex; gap: 10px; margin-top: 12px; }
654
- .approval-actions button { border: 1.92px solid rgba(171,171,171,1); border-radius: 100px; padding: 0 18px; min-height: 40px; font-size: 12px; font-weight: 800; font-style: italic; }
655
- .approve { background: linear-gradient(0deg, rgba(0,179,255,0.25), rgba(0,179,255,0.25)), linear-gradient(132.39deg, rgba(255,255,255,0.6) 15.21%, rgba(128,128,128,0.5) 89.39%); color: var(--ink); box-shadow: var(--mini-shadow); }
656
- .deny { background: linear-gradient(132.39deg, rgba(255,175,175,0.6), rgba(215,110,110,0.45)); color: var(--err); box-shadow: var(--mini-shadow); }
657
-
658
- /* Agent 提问:与批准同一种玻璃卡片,内部是可直接点选的真实表单 */
659
- .input-entry {
660
- padding: 14px;
661
- border-radius: 25px;
662
- background: linear-gradient(176deg, rgba(255,255,255,0.55), rgba(189,197,127,0.35));
663
- box-shadow: -6px -6px 36px rgba(255,255,255,0.96), 6px 6px 36px rgba(0,0,0,0.25), inset -11px -11px 12px rgba(255,255,255,0.8), inset 11px 15px 8px rgba(0,0,0,0.12);
664
- border: 1.92px solid rgba(184,184,184,1);
665
- -webkit-backdrop-filter: blur(13px) saturate(135%);
666
- backdrop-filter: blur(13px) saturate(135%);
667
- color: var(--ink);
668
- }
669
- .input-entry strong { color: var(--warn); }
670
- .input-question { margin-top: 12px; }
671
- .input-header { margin: 0 0 4px; font-size: 11px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
672
- .input-prompt { margin: 0 0 10px; font-size: 14px; line-height: 1.5; }
673
- .input-options { display: grid; gap: 8px; }
674
- .input-option { display: flex; gap: 8px; align-items: flex-start; padding: 10px 12px; border-radius: 18px; border: 1.4px solid rgba(171,171,171,0.7); background: rgba(255,255,255,0.45); font-size: 13px; cursor: pointer; }
675
- .input-option input { margin: 2px 0 0; accent-color: rgba(0,119,179,0.9); }
676
- .input-option-note { display: block; margin-top: 2px; color: var(--ink-3); font-size: 11px; line-height: 1.4; }
677
- .input-custom { margin-top: 10px; width: 100%; min-height: 42px; border-radius: 100px; padding: 0 14px; border: 1.4px solid rgba(171,171,171,0.8); background: var(--glass-bg-strong); color: var(--ink); font-size: 13px; }
678
- .input-custom:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus); }
679
- /* 已作答的提问卡:保留问题与选项文本(读者需要知道当时问了什么),但不再有任何可点控件,
680
- 并在末尾写明结局。以前答完卡片仍带着按钮,刷新后按钮还能点,一点必然 409。 */
681
- .input-entry.is-settled { opacity: .84; }
682
- .input-entry.is-settled strong { color: var(--ink-3); }
683
- .input-settled { margin: 10px 0 0; color: #0b5f47; font-size: 11.5px; font-weight: 800; font-style: italic; letter-spacing: .04em; }
684
- .input-option.settled { cursor: default; color: var(--ink-2); }
685
- .input-option.settled::before { content: "·"; margin-right: 6px; color: var(--ink-3); }
686
-
687
- /* 输入区:sx-glass-field 容器 */
688
- /* 只有一列:真正的布局在 .composer-row(附件 + 文本 + 发送)。这里原来还留着
689
- `1fr 48px` 两列——那是"文本在左、发送键在右列"的老结构,DOM 改成单行 flex 后
690
- 第二列就永远空着,于是发送键右侧多出 69px 空隙(48 列 + 10 gap + 10 padding + 描边)。 */
691
- .composer { margin: 0 0 18px 4px; padding: 10px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-items: end; background: var(--glass-bg-strong); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); border: 1.92px solid rgba(171,171,171,0.8); border-radius: var(--radius); box-shadow: var(--panel-shadow); overflow: hidden; }
692
- .composer:focus-within { box-shadow: var(--panel-shadow), 0 0 0 3px var(--focus); }
693
- /* 一行高就够:输入多行时由 app.js 按 scrollHeight 长到 max-height。96px 的最小高度
694
- 会让空输入框在宽屏上变成一个巨大的空盒子(文字顶对齐、按钮底对齐)。 */
695
- .composer textarea { min-height: 48px; max-height: min(320px, 45vh); resize: none; padding: 12px 14px; border: 0; background: transparent; line-height: 1.5; box-shadow: none; color: var(--ink); }
696
- .composer textarea:focus-visible { outline: 0; box-shadow: none; }
697
- .send-button { width: 48px; height: 48px; min-height: 48px; border: 1.92px solid rgba(177,175,175,1); border-radius: 100px; background: linear-gradient(132deg, rgba(255,255,255,0.48), rgba(0,119,179,0.41)); color: var(--ink); display: grid; place-items: center; box-shadow: var(--icon-btn-shadow); transition: transform .15s ease; overflow: hidden; }
698
- .send-button:hover { transform: translateY(-2px) scale(1.06); }
699
- .send-button:active { transform: scale(0.94); }
700
-
701
- /* ---------- 配对 / 密钥全屏页 ---------- */
702
- .pairing-screen { min-height: 100vh; min-height: 100dvh; padding: 28px; display: grid; place-content: center; justify-items: start; }
703
- .pairing-screen > * { position: relative; }
704
- /* 背景图之后,配对/密钥页直接用正文浮在遮罩上:加一层柔和底板保证可读 */
705
- .pairing-screen::before { content: ""; position: fixed; inset: 0; z-index: -1; background: radial-gradient(120% 80% at 30% 20%, rgba(255,255,255,0.55), rgba(255,255,255,0.15) 70%); }
706
- .pairing-mark { width: 68px; height: 68px; border-radius: 50%; margin-bottom: 28px; font-size: 20px; position: relative; }
707
- .pairing-mark::before { content: ""; position: absolute; inset: 2px; border-radius: 50%; background: var(--knob-glow); pointer-events: none; }
708
- .pairing-screen h1 { margin: 0 0 12px; font-size: clamp(34px, 9vw, 64px); letter-spacing: -.04em; font-weight: 800; font-style: italic; color: var(--ink); }
709
- .pairing-screen p { margin: 0; color: var(--ink-2); font-size: 17px; }
710
- .access-form { display: flex; gap: 10px; margin-top: 24px; width: min(420px, 100%); }
711
- .access-form input { flex: 1; min-width: 0; height: 50px; border: 1.92px solid rgba(171,171,171,1); border-radius: 100px; padding: 0 18px; font-size: 14px; background: var(--glass-bg-strong); box-shadow: var(--mini-shadow); color: var(--ink); }
712
-
713
- /* 加载条:sx-progress 药丸 */
714
- .loader { width: min(320px, 70vw); height: 18px; margin-top: 32px; border-radius: 100px; background: linear-gradient(132.15deg, rgba(128,128,128,0.55) 18.15%, rgba(255,255,255,0.55) 82.6%); box-shadow: -6px -6px 14px rgba(255,255,255,0.6), 6px 6px 14px rgba(128,128,128,0.5), inset 2px 2px 4px rgba(0,0,0,0.18), inset -2px -2px 4px rgba(255,255,255,0.4); overflow: hidden; }
715
- .loader::after { content: ""; display: block; width: 36%; height: 100%; border-radius: 100px; background: linear-gradient(115.41deg, rgba(0,200,255,0.55), rgba(0,140,220,0.55)); box-shadow: inset 2px 2px 3px rgba(255,255,255,0.3); animation: load 1.2s cubic-bezier(.2,.8,.2,1) infinite; }
716
- @keyframes load { from { transform: translateX(-100%); } to { transform: translateX(380%); } }
717
-
718
- /* Toast:sx-toast 浅色玻璃 */
719
- .toast { position: fixed; left: 50%; bottom: max(24px, env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 30; max-width: min(520px, calc(100vw - 32px)); padding: 16px 20px; border-radius: 20px; background: var(--glass-bg-strong); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); border: 1px solid rgba(255,255,255,0.65); color: var(--ink-2); font-size: 13px; font-weight: 600; box-shadow: var(--panel-shadow); overflow: hidden; }
720
-
721
- /* ---------- 移动端 ---------- */
722
- @media (max-width: 780px) {
723
- /* 顶栏一行:品牌(可压缩)+ 连接状态。抽屉开关是固定在左上的浮层,用左内边距让位。 */
724
- .topbar { grid-template-columns: minmax(0, 1fr) auto; gap: 8px; min-height: 44px; padding: 4px 10px 4px 58px; margin: max(6px, env(safe-area-inset-top)) 10px 0; top: max(6px, env(safe-area-inset-top)); border-radius: 16px; }
725
- .connection { grid-column: auto; padding: 4px 10px; font-size: 10.5px; gap: 6px; }
726
- .machine-name { display: none; }
727
- .brand { min-width: 0; gap: 8px; padding: 2px 0; font-size: 13px; }
728
- .brand-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
729
- .brand-mark { width: 28px; height: 28px; border-radius: 10px; font-size: 11px; }
730
- .pairing-strip { margin: 14px 10px; flex-direction: column; align-items: flex-start; padding: 20px; }
731
- /* 手机端"下次从这里继续"折叠成一行,把竖向空间还给对话 */
732
- .return-entry { margin: 10px 10px 0; padding: 10px 12px; align-items: center; flex-direction: row; gap: 10px; }
733
- .return-entry > div:first-child { min-width: 0; }
734
- .return-entry strong { font-size: 13px; }
735
- #return-details { display: none; }
736
- .return-entry.expanded { flex-direction: column; align-items: stretch; }
737
- .return-entry.expanded #return-details { display: block; }
738
- #return-details p { display: none; }
739
- #return-details code { display: block; margin-top: 6px; max-width: calc(100vw - 60px); white-space: normal; overflow-wrap: anywhere; }
740
- .return-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
741
- .return-actions .secondary-button { min-height: 34px; padding: 0 12px; font-size: 12px; }
742
- .return-actions .text-button { padding: 0; font-size: 12px; }
743
- .pairing-copy code { white-space: normal; overflow-wrap: anywhere; }
744
- .notify-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
745
- .notify-row h3 { margin: 0 0 4px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
746
- .notify-row p { margin: 0; color: var(--ink-2); font-size: 13px; line-height: 1.5; }
747
- .notify-row button { flex: none; }
748
- @media (max-width: 780px) { .notify-row { flex-direction: column; align-items: stretch; gap: 10px; } }.bridge-shutdown { align-items: stretch; flex-direction: column; }
749
- .bridge-shutdown .danger-button { width: 100%; }
750
- .workspace { margin: 0; display: block; }
751
- .conversation { border-top: 0; }
752
- .empty-state { min-height: 340px; }
753
- .session-view { min-height: calc(100vh - 132px); min-height: calc(100dvh - 132px); }
754
- /* 会话头压缩:标题最多两行、meta 单行省略,把首屏让给对话 */
755
- .session-header { padding: 12px 14px 10px; align-items: flex-start; flex-direction: column; gap: 10px; }
756
- /* 纵向堆叠时 align-items:flex-start 会让子块按"内容宽度"布局,而头部的项目徽标是
757
- nowrap 的(DEEPSPEK-HARNESS-DESKTOP + LOCAL-BOUJOY-HARNESS-MAIN-…),内容宽度
758
- 328px > 手机可用宽度,整块就顶出屏幕。让子块撑满并允许收缩,徽标自己省略。 */
759
- .session-header > * { width: 100%; min-width: 0; }
760
- .session-header h2 { margin: 2px 0; font-size: 19px; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
761
- .session-meta { flex-wrap: nowrap; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
762
- .session-meta span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
763
- .session-actions { width: 100%; justify-content: flex-start; gap: 8px; }
764
- /* 模型选择与「切换模型」并排一行,按钮缩成次要动作 */
765
- .model-control { width: 100%; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto; gap: 8px; }
766
- .model-control #apply-model { grid-column: auto; min-height: 38px; padding: 0 12px; font-size: 11px; }
767
- .model-control small { grid-column: 1 / -1; }
768
- .event-log { max-height: none; min-height: 340px; padding: 14px 14px 32px; }
769
- .event-entry { grid-template-columns: 52px minmax(0, 1fr); gap: 10px; }
770
- .composer { position: sticky; bottom: 10px; margin: 0 10px; z-index: 6; padding: 10px; }
771
- }
772
-
773
- /* 窄屏(≤480px):模型名经常很长(DeepSeek · DeepSeek-V4-Flash-Vision-Exp),三个控件
774
- 挤一行只能靠省略号,能读到的信息太少。让模型选择独占第一行,推理强度与「切换模型」
775
- 并排第二行——多花约一行高度,换回一个看得清的模型名。 */
776
- @media (max-width: 480px) {
777
- .model-control { grid-template-columns: minmax(0, 1fr) auto; }
778
- #model-picker { grid-column: 1 / -1; }
779
- #reasoning-control { grid-column: 1; }
780
- .model-control #apply-model { grid-column: 2; }
781
- }
782
-
783
- /* 极窄屏(≤360px):只留 AB 方块和状态圆点,保证三者在同一行 */
784
- @media (max-width: 360px) {
785
- .brand-text { display: none; }
786
- #connection-status span:last-child { display: none; }
787
- .topbar { padding-right: 8px; }
788
- #connection-status { padding: 4px 8px; }
789
- }
790
- /* ---------- 动效与透明度回退 ---------- */
791
- @media (prefers-reduced-motion: reduce) {
792
- .loader::after { animation: none; width: 100%; }
793
- .primary-button, .secondary-button, .danger-button, .icon-button, .send-button, .drawer-agent, .drawer-session { transition: none; }
794
- .primary-button:hover, .secondary-button:hover, .danger-button:hover, .icon-button:hover, .send-button:hover { transform: none; }
795
- }
796
-
797
- @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
798
- .topbar, .pairing-strip, .return-entry, .composer, .toast, .glass-popover, .drawer-card { background: #eceef1; }
799
- .approval-entry, .input-entry { background: #f0ead8; }
800
- }
801
-
802
- @media (prefers-reduced-transparency: reduce) {
803
- .topbar, .pairing-strip, .return-entry, .composer, .toast, .approval-entry, .input-entry, .agent-drawer, .create-sheet, .glass-popover, .drawer-card,
804
- .primary-button, .secondary-button, .danger-button, .icon-button, .send-button, select, input {
805
- -webkit-backdrop-filter: none;
806
- backdrop-filter: none;
807
- background: #eceef1;
808
- }
809
- .approval-entry, .input-entry { background: #f0ead8; }
810
- }
811
-
812
- /* ---------- 抽屉:Agent → 项目 → 会话 ---------- */
813
- /* 手机上是覆盖层,桌面沿用左侧常驻栏;同一个 DOM,两套呈现。 */
814
- .drawer-toggle { display: none; width: 40px; height: 40px; min-height: 40px; padding: 0; border: 1.92px solid rgba(177,175,175,0.9); border-radius: 14px; background: var(--glass-bg-strong); color: var(--ink); place-items: center; box-shadow: var(--mini-shadow); }
815
- .drawer-toggle:active { transform: scale(.95); }
816
- @media (max-width: 780px) {
817
- /* 固定在视口左上角:对话滚到任何位置都能一键回到 Agent / 项目切换。
818
- 它必须位于顶栏之外——顶栏的 backdrop-filter 会成为 fixed 子元素的包含块。 */
819
- .drawer-toggle {
820
- display: grid;
821
- position: fixed;
822
- left: max(8px, env(safe-area-inset-left));
823
- top: max(6px, env(safe-area-inset-top));
824
- z-index: 20;
825
- width: 44px;
826
- height: 44px;
827
- min-height: 44px;
828
- -webkit-backdrop-filter: var(--glass-blur);
829
- backdrop-filter: var(--glass-blur);
830
- }
831
- /* 抽屉打开后由抽屉自己的 ✕ / 左滑关闭,避免两个关闭入口叠在一起。 */
832
- .drawer-toggle[aria-expanded="true"] { opacity: 0; pointer-events: none; }
833
- }
834
- .preview-banner { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; margin: 10px 10px 0; padding: 10px 14px; border-radius: 16px; background: linear-gradient(176deg, rgba(255,255,255,.62), rgba(189,197,127,.32)); border: 1.4px solid rgba(171,171,171,.7); box-shadow: var(--mini-shadow); font-size: 12px; color: var(--ink-2); }
835
- .preview-banner strong { color: var(--want, var(--ink)); font-style: italic; font-weight: 800; }
836
-
837
- .drawer-mask { position: fixed; inset: 0; z-index: 40; background: rgba(24,28,34,.32); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); opacity: 0; transition: opacity .2s ease; }
838
- .drawer-mask.open { opacity: 1; }
839
-
840
- .agent-drawer { position: fixed; top: 0; bottom: 0; left: 0; z-index: 41; width: min(88vw, 380px); display: flex; flex-direction: column; min-height: 0; padding: 14px 12px calc(12px + env(safe-area-inset-bottom)); background: var(--glass-bg-strong); -webkit-backdrop-filter: blur(20px) saturate(140%); backdrop-filter: blur(20px) saturate(140%); border-right: 1.92px solid rgba(171,171,171,.75); box-shadow: 18px 0 48px rgba(20,24,30,.22); transform: translateX(-102%); transition: transform .24s cubic-bezier(.22,.68,.24,1); visibility: hidden; }
841
- .agent-drawer.open { transform: none; visibility: visible; }
842
- @media (prefers-reduced-motion: reduce) { .agent-drawer { transition: none; } }
843
-
844
- .drawer-head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 2px 2px 12px; }
845
- .drawer-close { width: 36px; height: 36px; min-height: 36px; }
846
- .drawer-heading { min-width: 0; }
847
- .drawer-heading h2 { margin: 0; font-size: 17px; font-style: italic; font-weight: 800; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
848
- .drawer-heading p { margin: 2px 0 0; font-size: 11px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
849
- .drawer-connection { font-size: 10px; padding: 4px 10px; border-radius: 100px; background: var(--glass-bg); box-shadow: inset 0 0 0 1.2px rgba(255,255,255,.6); }
850
- .drawer-connection:not(.online):not(.offline) { color: var(--ink-3); }
851
-
852
- .drawer-search { position: relative; display: flex; align-items: center; margin-bottom: 10px; }
853
- .drawer-search-icon { position: absolute; left: 12px; width: 16px; height: 16px; color: var(--ink-3); pointer-events: none; }
854
- .drawer-search input { width: 100%; height: 40px; padding: 0 12px 0 36px; border-radius: 100px; border: 1.4px solid rgba(171,171,171,.8); background: rgba(255,255,255,.55); color: var(--ink); font-size: 13px; box-shadow: var(--mini-shadow); }
855
- .drawer-search input:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus); }
856
-
857
- .drawer-tree { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; display: grid; align-content: start; gap: 2px; padding-bottom: 8px; }
858
-
859
- .drawer-agent { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto auto; gap: 8px; align-items: center; width: 100%; min-height: 46px; padding: 8px 10px; border: 0; border-radius: 14px; background: transparent; color: var(--ink); text-align: left; font: inherit; }
860
- .drawer-agent:active { transform: scale(.99); }
861
- .drawer-agent:hover { background: rgba(255,255,255,.38); }
862
- .drawer-agent[aria-expanded="true"] { background: var(--glass-bg); box-shadow: inset 0 0 0 1.6px rgba(0,179,255,.22); }
863
- .drawer-agent-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 800; font-style: italic; }
864
- .drawer-agent-badge { font-size: 9.5px; font-weight: 800; letter-spacing: .04em; padding: 3px 7px; border-radius: 100px; background: rgba(0,179,255,.18); color: #0a3a66; white-space: nowrap; }
865
- .drawer-agent-badge.attach { background: rgba(214,164,60,.22); color: #6b4a06; }
866
- .drawer-agent-badge.unavailable { background: rgba(150,150,150,.2); color: var(--ink-3); }
867
- .drawer-agent-count { min-width: 22px; font-size: 11px; font-weight: 800; color: var(--ink-3); text-align: right; font-variant-numeric: tabular-nums; }
868
- .drawer-chevron { width: 16px; height: 16px; color: var(--ink-3); transition: transform .16s ease; }
869
- .drawer-agent[aria-expanded="true"] .drawer-chevron { transform: rotate(90deg); }
870
- .drawer-agent[aria-expanded="false"] .drawer-agent-badge { opacity: .75; }
871
-
872
- .drawer-projects { display: grid; gap: 1px; padding: 2px 0 6px 8px; }
873
- .drawer-project { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: center; width: 100%; min-height: 34px; padding: 4px 10px; border: 0; border-radius: 10px; background: transparent; color: var(--ink-2); text-align: left; font: inherit; }
874
- .drawer-project-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11.5px; font-weight: 800; letter-spacing: .04em; }
875
- .drawer-project-count { font-size: 10.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
876
- .drawer-project .drawer-chevron { width: 13px; height: 13px; }
877
- .drawer-project[aria-expanded="true"] .drawer-chevron { transform: rotate(90deg); }
878
-
879
- .drawer-sessions { display: grid; gap: 2px; padding: 2px 0 4px 14px; }
880
- .drawer-session { display: grid; grid-template-columns: 12px minmax(0, 1fr); gap: 8px; align-items: start; width: 100%; min-height: 46px; padding: 8px 10px; border: 0; border-radius: 14px; background: transparent; color: var(--ink); text-align: left; font: inherit; }
881
- .drawer-session:hover { background: rgba(255,255,255,.38); }
882
- .drawer-session:active { transform: scale(.99); }
883
- .drawer-session.active { background: var(--glass-bg); box-shadow: inset 0 0 0 1.6px rgba(0,179,255,.28), var(--mini-shadow); }
884
- .drawer-session-body { min-width: 0; }
885
- .drawer-session-title { display: block; font-size: 12.5px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
886
- .drawer-session-meta { display: block; margin-top: 2px; font-size: 10.5px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
887
- .drawer-session .status-mark { margin-top: 5px; }
888
-
889
- .drawer-empty { padding: 14px 12px; font-size: 12px; color: var(--ink-3); }
890
- .drawer-foot { display: flex; gap: 8px; padding-top: 10px; border-top: 1px solid rgba(171,171,171,.35); }
891
- .drawer-foot .primary-button, .drawer-foot .secondary-button { flex: 1 1 0; min-width: 0; min-height: 44px; padding: 0 12px; }
892
- .drawer-foot .primary-button svg, .drawer-foot .secondary-button svg { width: 16px; height: 16px; flex: none; }
893
-
894
- /* ---------- 抽屉即导航 ---------- */
895
- /* 手机:覆盖层 + 遮罩;宽屏:常驻侧栏,内容整体右移。 */
896
- .workspace { display: block; margin: 26px auto; }
897
- @media (min-width: 781px) {
898
- .agent-drawer {
899
- display: flex;
900
- transform: none;
901
- visibility: visible;
902
- width: 320px;
903
- box-shadow: 1px 0 0 rgba(171,171,171,.55);
904
- border-right: 0;
905
- }
906
- .drawer-mask { display: none !important; }
907
- .drawer-toggle, .drawer-close { display: none; }
908
- .drawer-head { grid-template-columns: minmax(0, 1fr) auto auto; }
909
- body.has-drawer { padding-left: 320px; }
910
- }
911
-
912
- /* The hamburger belongs to the drawer mode only, so the shipped console keeps its
913
- existing two-rail layout until 方案 A is approved. */
914
- @media (max-width: 780px) {
915
- .agent-drawer { width: min(90vw, 400px); }
916
- }
917
- @media (min-width: 781px) {
918
- .drawer-mask { display: none; }
919
- }
920
-
921
- /* ---------- 新建会话底部抽屉 ---------- */
922
- .drawer-create { width: 34px; height: 34px; min-height: 34px; padding: 0; }
923
- .drawer-head { grid-template-columns: auto minmax(0, 1fr) auto auto; gap: 8px; }
924
- .create-mask { position: fixed; inset: 0; z-index: 42; background: rgba(24,28,34,.36); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
925
- .create-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 43; max-height: 82dvh; overflow-y: auto; padding: 16px 16px calc(18px + env(safe-area-inset-bottom)); border-radius: 24px 24px 0 0; background: var(--glass-bg-strong); -webkit-backdrop-filter: blur(20px) saturate(140%); backdrop-filter: blur(20px) saturate(140%); border-top: 1.92px solid rgba(171,171,171,.8); box-shadow: 0 -18px 48px rgba(20,24,30,.24); transform: translateY(102%); transition: transform .24s cubic-bezier(.22,.68,.24,1); visibility: hidden; }
926
- .create-sheet.open { transform: none; visibility: visible; }
927
- @media (prefers-reduced-motion: reduce) { .create-sheet { transition: none; } }
928
- .create-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: start; margin-bottom: 12px; }
929
- .create-head h2 { margin: 0; font-size: 18px; font-style: italic; font-weight: 800; color: var(--ink); }
930
- .create-head p { margin: 4px 0 0; font-size: 12px; color: var(--ink-3); }
931
- .create-form { display: grid; gap: 10px; }
932
- .create-form label { display: grid; gap: 6px; font-size: 11px; font-weight: 800; letter-spacing: .06em; color: var(--ink-3); text-transform: uppercase; }
933
- .create-form select, .create-form input { height: 44px; border-radius: 14px; border: 1.4px solid rgba(171,171,171,.8); background: rgba(255,255,255,.6); color: var(--ink); font-size: 13.5px; padding: 0 12px; text-transform: none; letter-spacing: 0; font-weight: 600; }
934
- .create-form .primary-button { width: 100%; justify-content: center; margin-top: 2px; }
935
-
936
- /* 加载更早:位于日志之上,翻页不会把它挤走 */
937
- /* align-items 必须写:flex 默认 stretch,会把按钮拉成和整行一样高(100px 圆角就成了
938
- 巨型胶囊)。这一行只该有一行按钮那么高。 */
939
- .history-more { display: flex; justify-content: center; align-items: center; min-height: 0; padding: 4px 0 8px; }
940
- .history-more .secondary-button { min-height: 36px; font-size: 12px; }
941
-
942
- /* 快捷导航(置顶 ⇧ / 置底 ⇩):悬浮在视口右侧,滚动到对应端时自动淡出。
943
- 与 .icon-button 共用一套玻璃配方(Rim 高光 + 拟态阴影 + glass-blur),
944
- 圆角 14px 与抽屉行一致,按钮 44px 满足触控热区。两个按钮叠成一列,靠右侧
945
- 留出安全边距,垂直居中在视口,避免被 composer 的 sticky 底栏挡住。 */
946
- .quick-nav {
947
- position: fixed;
948
- right: max(12px, calc(env(safe-area-inset-right) + 12px));
949
- top: 50%;
950
- transform: translateY(-50%);
951
- z-index: 15;
952
- display: grid;
953
- gap: 8px;
954
- padding: 6px;
955
- border-radius: 20px;
956
- background: var(--glass-bg-strong);
957
- -webkit-backdrop-filter: var(--glass-blur);
958
- backdrop-filter: var(--glass-blur);
959
- border: 1.92px solid rgba(171, 171, 171, .8);
960
- box-shadow: var(--panel-shadow);
961
- }
962
- .quick-nav[hidden] { display: none; }
963
- .quick-nav-btn {
964
- position: relative;
965
- isolation: isolate;
966
- width: 44px;
967
- min-height: 44px;
968
- padding: 0;
969
- border: 1.92px solid rgba(177, 175, 175, 1);
970
- border-radius: 14px;
971
- background: linear-gradient(132deg, rgba(255, 255, 255, 0.48), rgba(0, 119, 179, 0.41));
972
- -webkit-backdrop-filter: var(--glass-blur);
973
- backdrop-filter: var(--glass-blur);
974
- box-shadow: var(--icon-btn-shadow);
975
- color: var(--ink);
976
- display: grid;
977
- place-items: center;
978
- transition: transform .15s ease, filter .15s ease, opacity .2s ease;
979
- overflow: hidden;
980
- }
981
- .quick-nav-btn svg { width: 20px; height: 20px; position: relative; z-index: 2; }
982
- .quick-nav-btn::before {
983
- content: "";
984
- position: absolute;
985
- inset: 0;
986
- border-radius: inherit;
987
- pointer-events: none;
988
- z-index: 5;
989
- box-shadow:
990
- inset 0 1px 0 rgba(255,255,255,1.00),
991
- inset 0 -1px 0 rgba(0,0,0, 0.45),
992
- inset 1px 0 0 rgba(255,255,255,0.36),
993
- inset -1px 0 0 rgba(0,0,0, 0.24);
994
- }
995
- .quick-nav-btn:hover { transform: translateY(-2px) scale(1.06); filter: brightness(1.05); }
996
- .quick-nav-btn:active { transform: scale(0.94); box-shadow: var(--btn-press-shadow); }
997
- /* 到端点只是提示:调低不透明度但**不拦点击**——"始终可点"是这个组件的契约,
998
- 而且内容随时会因为新消息变长,做成死键反而更让人困惑。 */
999
- .quick-nav-btn.is-idle { opacity: .55; }
1000
-
1001
- /* 代码着色:深色卡片上的四种记号,保持对比度 */
1002
- .md-code .tok-comment { color: #8d9682; font-style: italic; }
1003
- .md-code .tok-string { color: #b8e08c; }
1004
- .md-code .tok-number { color: #f0b978; }
1005
- .md-code .tok-keyword { color: #86c5ff; font-weight: 700; }
1006
- /* 抽屉里的"在所有会话中搜索"结果 */
1007
- .drawer-deep { display: grid; gap: 6px; margin: 8px 0 0; padding: 10px 2px 4px; border-top: 1px solid var(--line); }
1008
- .drawer-deep[hidden] { display: none; }
1009
- .drawer-deep-head, .drawer-deep-status { margin: 0 8px 4px; color: var(--ink-3); font-size: 11px; font-weight: 800; font-style: italic; letter-spacing: .06em; }
1010
- .drawer-deep-hit { display: grid; gap: 3px; width: 100%; min-height: 46px; padding: 8px 10px; border: 0; border-radius: 14px; background: transparent; color: var(--ink); text-align: left; }
1011
- .drawer-deep-hit:hover { background: rgba(255,255,255,.38); }
1012
- .drawer-deep-hit:active { transform: scale(.99); }
1013
- .drawer-deep-title { display: flex; align-items: baseline; gap: 8px; color: var(--ink); font-size: 13px; font-weight: 750; font-style: italic; }
1014
- .drawer-deep-title em { color: var(--ink-3); font-size: 10px; font-weight: 700; font-style: normal; }
1015
- .drawer-deep-snippet { color: var(--ink-2); font-size: 12px; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
1016
- /* 附件:输入框上方的待发列表 + 对话里的缩略图 */
1017
- .composer-row { display: flex; align-items: flex-end; gap: 8px; }
1018
- .composer-row textarea { flex: 1; min-width: 0; }
1019
- .attach-input { position: absolute; width: 1px; height: 1px; padding: 0; border: 0; opacity: 0; pointer-events: none; }.attach-button { flex: none; width: 40px; height: 40px; min-height: 40px; padding: 0; display: grid; place-items: center; border-radius: 100px; border: 1.6px solid rgba(171,171,171,.8); background: var(--glass-bg); box-shadow: var(--mini-shadow); color: var(--ink-2); }
1020
- .attach-button svg { width: 18px; height: 18px; }
1021
- .attach-button:disabled { opacity: .5; }
1022
- .composer-attachments { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 2px 8px; }
1023
- .composer-attachments[hidden] { display: none; }
1024
- .attachment-chip { display: inline-flex; align-items: center; gap: 8px; max-width: 240px; padding: 5px 8px; border-radius: 100px; background: rgba(255,255,255,.58); border: 1px solid rgba(255,255,255,.7); box-shadow: var(--mini-shadow); }
1025
- .attachment-chip img { width: 26px; height: 26px; border-radius: 8px; object-fit: cover; }
1026
- .attachment-chip-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 700; color: var(--ink-2); }
1027
- .attachment-chip-remove { min-height: 0; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 100px; background: rgba(0,0,0,.12); color: var(--ink); font-size: 13px; line-height: 1; }
1028
- .message-attachments { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
1029
- .attachment-thumb { display: grid; gap: 4px; max-width: 168px; text-decoration: none; }
1030
- .attachment-thumb img { width: 168px; height: 112px; object-fit: cover; border-radius: 12px; border: 1px solid rgba(255,255,255,.7); box-shadow: var(--mini-shadow); }
1031
- .attachment-caption { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; font-weight: 700; color: #2b3038; }
1032
- .attachment-file { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 100px; background: rgba(255,255,255,.55); border: 1px solid rgba(255,255,255,.7); box-shadow: var(--mini-shadow); color: #14141c; font-size: 12px; font-weight: 700; text-decoration: none; }
1033
- /* 排队中的消息 */
1034
- .composer-queue { display: grid; gap: 6px; padding: 0 2px 8px; }
1035
- .composer-queue[hidden] { display: none; }
1036
- .queue-item { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 12px; background: rgba(255,255,255,.5); border: 1px solid rgba(255,255,255,.66); }
1037
- .queue-item span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: #2b3038; }
1038
- .queue-item button { flex: none; min-height: 0; padding: 2px 8px; border-radius: 100px; border: 0; background: rgba(0,0,0,.1); font-size: 11px; font-weight: 700; color: #14141c; }
1039
- .voice-button[aria-pressed="true"] { background: rgba(0,170,140,.22); border-color: rgba(0,170,140,.6); color: #0b3b32; }
1040
- /* 工具输出:可折叠 + 可复制 */
1041
- .tool-copy { margin: 0 0 6px; min-height: 26px; padding: 0 10px; border-radius: 100px; border: 1px solid rgba(171,171,171,.7); background: rgba(255,255,255,.6); font-size: 11px; font-weight: 700; color: #2b3038; }
1042
- .tool-output { margin: 0; }
1043
- .tool-output summary { cursor: pointer; font-size: 12px; font-weight: 700; color: #0d3049; }
1044
- .tool-output pre { margin: 6px 0 0; padding: 10px 12px; border-radius: 12px; background: rgba(255,255,255,.5); font-size: 12px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; max-height: 340px; overflow: auto; }
1045
- .usage-line { margin: 4px 0 0; color: #16191f; font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
1046
- .usage-line[hidden] { display: none; }
1047
- /* 抽屉"卡片"区块:与弹层 / 底部面板同一套材质(玻璃底 + blur + 1.92px 灰边 + panel-shadow) */
1048
- .drawer-card {
1049
- display: flex;
1050
- align-items: center;
1051
- justify-content: space-between;
1052
- gap: 12px;
1053
- margin: 6px 0 10px;
1054
- padding: 12px 14px;
1055
- border-radius: 20px;
1056
- background: var(--glass-bg-strong);
1057
- -webkit-backdrop-filter: blur(20px) saturate(140%);
1058
- backdrop-filter: blur(20px) saturate(140%);
1059
- border: 1.92px solid rgba(171, 171, 171, .8);
1060
- box-shadow: var(--panel-shadow);
1061
- }
1062
- .drawer-card[hidden] { display: none; }
1063
- .drawer-card-body { display: grid; gap: 2px; min-width: 0; }
1064
- .drawer-card-title { font-size: 12px; font-weight: 800; font-style: italic; color: var(--ink); }
1065
- .drawer-card-note { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--ink-2); }
1066
- /* 开关本身就是一个 secondary-button:高度、背景、内描边、阴影全部继承,
1067
- 只在按下(静音中)时多加一层琥珀提示。 */
1068
- .notify-switch { flex: none; padding: 0 14px; }
1069
- .notify-switch[aria-pressed="true"] {
1070
- background: linear-gradient(0deg, rgba(220, 150, 0, .22), rgba(220, 150, 0, .22)), rgba(255, 255, 255, .5);
1071
- color: #3b2a00;
1072
- }
1073
- .notify-switch[hidden] { display: none; }
1
+ /* AgentBridge — sx-glass L2 皮肤
2
+ 设计参数来源:D:\ocean-glass-ui\sx-glass-component-kit-v2.html
3
+ 核心配方:132.39° 白灰渐变玻璃 + blur(13.44px) saturate(135%)
4
+ + 8 层拟态阴影 + ::before Rim 描边 + ::after 顶部光环
5
+ + Inter 斜体 800 标签 + 胶囊圆角 + Type G 旋钮阴影 */
6
+
7
+ :root {
8
+ color-scheme: light;
9
+ --ink: #2a2a3a;
10
+ --ink-2: rgba(0, 0, 0, 0.6);
11
+ --ink-3: rgba(0, 0, 0, 0.45);
12
+ --line: rgba(0, 0, 0, 0.08);
13
+ --accent: rgba(0, 140, 220, 0.9);
14
+ --accent-bright: rgba(0, 179, 255, 0.9);
15
+ --ok: rgba(0, 170, 140, 0.85);
16
+ --warn: rgba(220, 150, 0, 0.85);
17
+ --err: rgba(220, 60, 60, 0.85);
18
+ --focus: rgba(0, 179, 255, 0.35);
19
+
20
+ --halo: linear-gradient(90deg, transparent, rgba(255,255,255,1) 18%, rgba(255,255,255,0.6) 50%, rgba(255,255,255,1) 82%, transparent);
21
+ --knob-shadow:
22
+ -4px -4px 6px rgba(128,128,128,0.25),
23
+ 4px 4px 6px rgba(0,0,0,0.25),
24
+ -8px -8px 20px rgba(255,255,255,0.6),
25
+ 8px 8px 20px rgba(128,128,128,0.6),
26
+ inset 2px 2px 10px rgba(255,255,255,0.25),
27
+ inset -2px -2px 10px rgba(0,0,0,0.25);
28
+ --knob-glow: radial-gradient(circle at 32% 26%, rgba(255,255,255,0.5), transparent 55%);
29
+ --solid-glass: linear-gradient(132.39deg, #FFFFFF 15.21%, #808080 89.39%);
30
+
31
+ --glass-bg: linear-gradient(132.39deg, rgba(255,255,255,0.474) 15.21%, rgba(128,128,128,0.412) 89.39%);
32
+ --glass-bg-strong: linear-gradient(132.39deg, rgba(255,255,255,0.62) 15.21%, rgba(128,128,128,0.5) 89.39%);
33
+ --glass-blur: blur(13.44px) saturate(135%);
34
+ --panel-shadow:
35
+ -6px -6px 36px rgba(255,255,255,0.96),
36
+ 6px 6px 36px rgba(0,0,0,0.39),
37
+ inset -9.92px -9.92px 11.33px rgba(255,255,255,0.432),
38
+ inset 9.92px 9.92px 11.33px rgba(0,0,0,0.24),
39
+ inset 3px 3px 6px rgba(0,0,0,0.12),
40
+ inset -3px -3px 6px rgba(255,255,255,0.30),
41
+ inset 2px 2px 6px rgba(0,0,0,0.2),
42
+ inset -2px -2px 6px rgba(255,255,255,0.5);
43
+ --mini-shadow:
44
+ -3px -3px 6px rgba(255,255,255,0.6),
45
+ 3px 3px 6px rgba(128,128,128,0.4),
46
+ inset 3px 3px 6px rgba(0,0,0,0.10),
47
+ inset -3px -3px 6px rgba(255,255,255,0.35);
48
+ --btn-shadow:
49
+ -6px -6px 36px rgba(255,255,255,0.96),
50
+ 6px 6px 36px rgba(0,0,0,0.39),
51
+ inset -7px -6px 10px rgba(255,255,255,1),
52
+ inset 9px 9px 15px rgba(0,0,0,0.38);
53
+ --icon-btn-shadow:
54
+ -6px -6px 36px rgba(255,255,255,0.96),
55
+ 6px 6px 36px rgba(0,0,0,0.39),
56
+ inset -4px -4px 8px rgba(255,255,255,0.91),
57
+ inset 6px 6px 14px rgba(0,0,0,0.51);
58
+ --btn-press-shadow: inset 4px 4px 8px rgba(0,0,0,0.22), inset -4px -4px 8px rgba(255,255,255,0.4);
59
+
60
+ --radius: 20px;
61
+ font-family: "Inter", "Noto Sans SC", "Microsoft YaHei UI", system-ui, ui-sans-serif, sans-serif;
62
+ background: #cfcfcf;
63
+ color: var(--ink-2);
64
+ }
65
+
66
+ * { box-sizing: border-box; }
67
+ /* Android / 微信 webview 的"文字自动放大"(text autosizing)会把成块的正文文字放大,
68
+ 而本项目大量使用 nowrap 的徽标与标签——文字被放大后比容器还宽,整页就横着顶出屏幕
69
+ (真机上标题、模型行、输入框一起被切掉,桌面上永远复现不出来)。这里显式关掉自动放大,
70
+ 再配合 `.session-view` 的可收缩网格列兜底。 */
71
+ html {
72
+ -webkit-text-size-adjust: 100%;
73
+ text-size-adjust: 100%;
74
+ }
75
+ html, body { min-height: 100%; overflow-x: hidden; }
76
+ /* 底色放在 html 上、body 保持透明:html 带 overflow:hidden 时 body 的背景不再传播到画布,
77
+ 而是被当成普通盒子背景绘制——普通盒子的背景会盖住 z-index 为负的固定层,
78
+ 背景照片之前就是被这层灰盖掉的。 */
79
+ html { background-color: #cfcfcf; }
80
+ body { margin: 0; background: transparent; }
81
+
82
+ /* ---------- 全屏背景:照片原样铺满 + 整页"提亮地板"遮罩 ---------- */
83
+ /* 照片按 cover 铺满视口——竖屏手机裁掉两侧,横屏桌面裁掉上下——原样呈现,不做 blur:
84
+ 此前的 blur(1.5px) 正是"背景像素变低、看不清"的原因。
85
+ 遮罩不用半透明白纱(那会把照片整体压平、色度掉一半),而是用 lighten 混合给它一个
86
+ "地板色":比地板亮的照片像素**逐像素不动**(纹理、边缘、高光都在),比地板暗的抬到
87
+ 地板。于是整页任意位置文字背后的亮度是同一个值,正文对比可以精确算出来。 */
88
+ :root {
89
+ /* 整页遮罩:一层均匀白纱,α 是唯一参数,没有混合模式、没有蒙版、没有第二种颜色。
90
+ 实测(正文最差处,三档视口):α 0.55 → 5.74–6.11:1、**0.58 → 6.28–6.69:1**、0.62 → 7.09–7.46:1。
91
+ 取 0.58:正文过 6:1(低于这条线文字会发虚,这是之前实测出来的),同时保住画面。
92
+ 它对整幅图均匀生效——雪面也会被冲淡(色度只剩 42%),这就是"简单"换来的代价。 */
93
+ --bg-scrim-veil: rgba(255, 255, 255, 0.58);
94
+ --bg-scrim-veil-solid: rgba(255, 255, 255, 0.72); /* 减少透明/要求更高对比时更实 */
95
+ }
96
+ body::before {
97
+ content: "";
98
+ position: fixed;
99
+ inset: 0;
100
+ z-index: -2;
101
+ background-color: #cfcfcf;
102
+ background-image: url("/background.jpg");
103
+ background-size: cover;
104
+ /* 原图铺满裁切。素材 2048×1152(16:9):竖屏手机和宽屏桌面都是**横向**裁切、纵向正好铺满,
105
+ 所以只有横向位置有意义;居中即 `center`。 */
106
+ background-position: center;
107
+ background-repeat: no-repeat;
108
+ }
109
+ body::after {
110
+ content: "";
111
+ position: fixed;
112
+ inset: 0;
113
+ z-index: -1;
114
+ pointer-events: none;
115
+ /* 一层白纱,没有混合模式、没有蒙版:照片在下、半透明白在上,整幅均匀压亮。 */
116
+ background: var(--bg-scrim-veil);
117
+ }
118
+ @media (prefers-reduced-transparency: reduce) {
119
+ body::after { background: var(--bg-scrim-veil-solid); }
120
+ }
121
+ @media (prefers-contrast: more) {
122
+ body::after { background: var(--bg-scrim-veil-solid); }
123
+ }@media (min-width: 781px) {
124
+ /* 宽屏只裁掉左右各约一成,取景几乎等于整幅:用同一横向锚点,避免宽窄屏构图跳变。
125
+ 纵向没有可裁空间(16:9 铺满 16:10 视口高度),所以不需要第二套纵向值。 */
126
+ body::before { background-position: center; }
127
+ }
128
+
129
+
130
+ button, input, select, textarea { font: inherit; }
131
+ button, select { min-height: 44px; }
132
+ button { cursor: pointer; }
133
+ button:disabled { cursor: not-allowed; opacity: .55; }
134
+ button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, a:focus-visible {
135
+ outline: 0;
136
+ box-shadow: 0 0 0 3px var(--focus), var(--mini-shadow);
137
+ }
138
+ ::selection { background: var(--accent); color: white; }
139
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
140
+ ::-webkit-scrollbar-thumb { background: linear-gradient(132.39deg, rgba(255,255,255,0.7), rgba(128,128,128,0.6)); border: 3px solid #cfcfcf; border-radius: 10px; }
141
+ svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
142
+ .icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
143
+ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
144
+ [hidden] { display: none !important; }
145
+
146
+ /* ---------- 共享玻璃基底(面板级:Rim + 顶部光环) ---------- */
147
+ .pairing-strip, .return-entry, .composer, .toast, .approval-entry, .glass-popover, .drawer-card,
148
+ .primary-button, .icon-button, .send-button, .access-form input {
149
+ position: relative;
150
+ isolation: isolate;
151
+ }
152
+ .pairing-strip::before, .return-entry::before, .composer::before, .toast::before,
153
+ .glass-popover::before, .drawer-card::before,
154
+ .primary-button::before, .icon-button::before, .send-button::before {
155
+ content: "";
156
+ position: absolute;
157
+ inset: 0;
158
+ border-radius: inherit;
159
+ pointer-events: none;
160
+ z-index: 5;
161
+ box-shadow:
162
+ inset 0 1px 0 rgba(255,255,255,1.00),
163
+ inset 0 -1px 0 rgba(0,0,0, 0.45),
164
+ inset 1px 0 0 rgba(255,255,255,0.36),
165
+ inset -1px 0 0 rgba(0,0,0, 0.24);
166
+ }
167
+ .pairing-strip::after, .return-entry::after, .composer::after,
168
+ .glass-popover::after, .drawer-card::after,
169
+ .primary-button::after, .icon-button::after, .send-button::after {
170
+ content: "";
171
+ position: absolute;
172
+ top: 3px;
173
+ left: 24px;
174
+ right: 24px;
175
+ height: 2px;
176
+ border-radius: 1px;
177
+ pointer-events: none;
178
+ z-index: 6;
179
+ background: var(--halo);
180
+ }
181
+ .pairing-strip > *, .return-entry > *, .toast > *,
182
+ .glass-popover > *, .drawer-card > *,
183
+ .primary-button > *, .icon-button > *, .send-button > * { position: relative; z-index: 2; }
184
+ /* The composer contains an sr-only label that must stay absolutely positioned;
185
+ lifting it into the grid would steal the first cell and shrink the textarea. */
186
+ .composer textarea, .composer .send-button { position: relative; z-index: 2; }
187
+
188
+ .app-shell { min-height: 100vh; min-height: 100dvh; }
189
+
190
+ /* ---------- 顶栏:浮动胶囊玻璃导航 ---------- */
191
+ .topbar {
192
+ position: sticky;
193
+ top: 10px;
194
+ z-index: 10;
195
+ max-width: 1180px;
196
+ margin: 10px auto 0;
197
+ min-height: 54px;
198
+ display: grid;
199
+ grid-template-columns: 1fr auto 1fr;
200
+ align-items: center;
201
+ gap: 20px;
202
+ padding: 6px 12px;
203
+ border-radius: 100px;
204
+ background: var(--glass-bg);
205
+ -webkit-backdrop-filter: var(--glass-blur);
206
+ backdrop-filter: var(--glass-blur);
207
+ box-shadow: var(--panel-shadow);
208
+ }
209
+ .brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); text-decoration: none; font-weight: 800; font-style: italic; letter-spacing: -.02em; padding: 4px 10px; }
210
+ .brand-mark, .pairing-mark { display: grid; place-items: center; background: var(--solid-glass); color: var(--ink); font-weight: 800; font-style: italic; letter-spacing: -.04em; box-shadow: var(--knob-shadow); }
211
+ .brand-mark { width: 34px; height: 34px; border-radius: 12px; font-size: 12px; }
212
+ .connection { display: inline-flex; align-items: center; gap: 8px; font-size: 11px; font-style: italic; font-weight: 800; color: var(--ink-2); padding: 6px 14px; border-radius: 100px; background: var(--glass-bg); box-shadow: var(--mini-shadow); font-variant-numeric: tabular-nums; }
213
+ .connection-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--warn); }
214
+ .connection.online .connection-dot { background: var(--ok); }
215
+ .connection.offline .connection-dot { background: var(--err); }
216
+ .machine-name { justify-self: end; color: var(--ink-3); font-size: 11px; font-style: italic; font-weight: 800; letter-spacing: .06em; padding-right: 10px; }
217
+
218
+ /* ---------- 配对区:sx-glass 主面板 ---------- */
219
+ .pairing-strip {
220
+ max-width: 1180px;
221
+ margin: 26px auto 0;
222
+ padding: 24px 28px;
223
+ display: flex;
224
+ flex-wrap: wrap;
225
+ justify-content: space-between;
226
+ align-items: center;
227
+ gap: 32px;
228
+ border-radius: var(--radius);
229
+ background: var(--glass-bg);
230
+ -webkit-backdrop-filter: var(--glass-blur);
231
+ backdrop-filter: var(--glass-blur);
232
+ box-shadow: var(--panel-shadow);
233
+ color: var(--ink);
234
+ overflow: hidden;
235
+ }
236
+ .pairing-copy { width: 100%; min-width: 0; max-width: 680px; }
237
+ .pairing-copy h2 { margin: 0 0 8px; font-size: clamp(22px, 3vw, 34px); letter-spacing: -.035em; font-weight: 800; font-style: italic; color: var(--ink); }
238
+ .pairing-copy p { margin: 0 0 14px; color: var(--ink-2); line-height: 1.65; }
239
+ .pairing-copy code { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; color: var(--accent); font-size: 12px; white-space: nowrap; }
240
+ .pairing-strip img { width: 176px; height: 176px; background: white; padding: 8px; border-radius: 16px; flex: none; box-shadow: var(--mini-shadow); }
241
+ .pairing-strip .return-qr-copy { min-width: 190px; }
242
+ .return-qr-copy h3 { margin: 0 0 8px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
243
+ .return-qr-copy p { margin: 0 0 12px; color: var(--ink-2); font-size: 13px; line-height: 1.55; }
244
+ .return-qr-copy code { display: block; max-width: 190px; overflow: hidden; color: var(--accent); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
245
+ .device-manager { width: 100%; border-top: 1px solid var(--line); padding-top: 14px; }
246
+ .device-manager h3 { margin: 0 0 6px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
247
+ .device-manager p { margin: 0 0 10px; color: var(--ink-2); font-size: 13px; }
248
+ .device-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
249
+ .device-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13px; font-weight: 600; color: var(--ink-2); padding: 9px 14px; border-radius: 100px; background: var(--glass-bg); box-shadow: var(--mini-shadow); }
250
+ .device-row .device-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
251
+ .device-revoke { padding: 0; min-height: 0; font-size: 12px; font-style: italic; font-weight: 800; color: var(--err); flex: none; white-space: nowrap; border: 0; background: transparent; }
252
+ .device-empty { color: var(--ink-3); font-size: 13px; font-style: italic; }
253
+ .pairing-strip #return-qr { width: 144px; height: 144px; }
254
+ .notify-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
255
+ .notify-row h3 { margin: 0 0 4px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
256
+ .notify-row p { margin: 0; color: var(--ink-2); font-size: 13px; line-height: 1.5; }
257
+ .notify-row button { flex: none; }
258
+ @media (max-width: 780px) { .notify-row { flex-direction: column; align-items: stretch; gap: 10px; } }.bridge-shutdown { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; gap: 20px; }
259
+ .bridge-shutdown > div { min-width: 0; }
260
+ .bridge-shutdown h3 { margin: 0 0 6px; }
261
+ .bridge-shutdown p { margin: 0; max-width: 72ch; }
262
+ .bridge-shutdown .danger-button { flex: none; min-width: 154px; min-height: 44px; }
263
+
264
+ /* ---------- 返回入口卡片 ---------- */
265
+ .return-entry { max-width: 1180px; margin: 16px auto 0; padding: 16px 20px; display: flex; justify-content: space-between; align-items: center; gap: 20px; border-radius: var(--radius); background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); box-shadow: var(--panel-shadow); overflow: hidden; }
266
+ .return-entry strong { font-size: 15px; font-style: italic; font-weight: 800; color: var(--ink); }
267
+ .return-entry p { margin: 4px 0 8px; color: var(--ink-2); font-size: 13px; line-height: 1.5; }
268
+ .return-entry code { display: block; max-width: min(700px, 72vw); overflow: hidden; color: var(--accent); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
269
+ .text-button { border: 0; min-height: 0; padding: 8px 0 0; background: transparent; color: var(--accent); display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-style: italic; font-weight: 800; }
270
+
271
+ /* ---------- 工作区 ---------- */
272
+ .workspace { max-width: 1180px; margin: 26px auto; display: grid; grid-template-columns: minmax(250px, 310px) minmax(0, 1fr); min-height: calc(100vh - 120px); min-height: calc(100dvh - 120px); }
273
+
274
+ /* 按钮:sx-btn 配方(白→蓝玻璃胶囊 + 拟态阴影 + 灰描边) */
275
+ .primary-button, .secondary-button, .danger-button {
276
+ border: 1.92px solid rgba(171,171,171,1);
277
+ border-radius: 100px;
278
+ padding: 0 24px;
279
+ min-height: 42px;
280
+ font-size: 12px;
281
+ font-style: italic;
282
+ font-weight: 800;
283
+ color: var(--ink);
284
+ background: linear-gradient(132deg, rgba(255,255,255,0.48), rgba(0,119,179,0.41));
285
+ -webkit-backdrop-filter: blur(13px) saturate(135%);
286
+ backdrop-filter: blur(13px) saturate(135%);
287
+ box-shadow: var(--btn-shadow);
288
+ transition: transform .15s ease, filter .15s ease, box-shadow .2s ease;
289
+ display: inline-flex;
290
+ gap: 8px;
291
+ align-items: center;
292
+ justify-content: center;
293
+ overflow: hidden;
294
+ white-space: nowrap;
295
+ }
296
+ .primary-button:hover, .secondary-button:hover, .danger-button:hover { transform: translateY(-2px) scale(1.02); filter: brightness(1.05); }
297
+ .primary-button:active, .secondary-button:active, .danger-button:active { transform: scale(0.97); box-shadow: var(--btn-press-shadow); }
298
+ .primary-button { background: linear-gradient(0deg, rgba(0,179,255,0.25), rgba(0,179,255,0.25)), linear-gradient(132.39deg, rgba(255,255,255,0.6) 15.21%, rgba(128,128,128,0.5) 89.39%); }
299
+ .secondary-button { background: rgba(255,255,255,0.22); border-color: transparent; box-shadow: inset 0 0 0 1.5px rgba(255,255,255,0.65), -4px -4px 12px rgba(255,255,255,0.5), 4px 4px 12px rgba(90,100,120,0.18); }
300
+ .danger-button { background: linear-gradient(132.39deg, rgba(255,175,175,0.6), rgba(215,110,110,0.45)); color: var(--err); }
301
+ .danger-button.confirming { background: linear-gradient(132.39deg, rgba(235,90,90,0.85), rgba(190,40,40,0.85)); color: white; }
302
+ .icon-button { width: 44px; min-height: 44px; border: 1.92px solid rgba(177,175,175,1); border-radius: 100px; background: linear-gradient(132deg, rgba(255,255,255,0.48), rgba(0,119,179,0.41)); color: var(--ink); display: grid; place-items: center; box-shadow: var(--icon-btn-shadow); transition: transform .15s ease, filter .15s ease; overflow: hidden; }
303
+ .icon-button:hover { transform: translateY(-2px) scale(1.06); }
304
+ .icon-button:active { transform: scale(0.94); }
305
+ .icon-button svg { width: 18px; height: 18px; }
306
+
307
+ /* 表单字段:sx-glass-field 卡片式凸起玻璃 */
308
+ select, input, textarea {
309
+ width: 100%;
310
+ border: 1px solid rgba(171,171,171,0.6);
311
+ border-radius: 100px;
312
+ background: linear-gradient(132.39deg, rgba(255,255,255,0.62), rgba(128,128,128,0.5));
313
+ color: var(--ink);
314
+ font-size: 13px;
315
+ box-shadow: var(--mini-shadow);
316
+ }
317
+ select:focus-visible, input:focus-visible, textarea:focus-visible { box-shadow: 0 0 0 3px var(--focus), var(--mini-shadow); }
318
+ select, input { height: 46px; padding: 0 16px; }
319
+ textarea { border-radius: 18px; }
320
+ select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%), linear-gradient(135deg, var(--ink-3) 50%, transparent 50%), linear-gradient(132.39deg, rgba(255,255,255,0.62), rgba(128,128,128,0.5)); background-position: calc(100% - 19px) 50%, calc(100% - 14px) 50%, 0 0; background-size: 5px 5px, 5px 5px, 100% 100%; background-repeat: no-repeat; }
321
+ ::placeholder { color: var(--ink-3); font-style: italic; }
322
+ .form-note { margin: 0; color: var(--ink-3); font-size: 12px; line-height: 1.5; font-style: italic; }
323
+
324
+ /* 会话列表:sx-list 配方 */
325
+ .status-mark { width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--ink-3); }
326
+ .status-mark.running, .status-mark.starting { background: var(--warn); }
327
+ /* 停止中 is still an open turn, only with its end requested: the same warning
328
+ family, a step quieter so the two states read differently at a glance. */
329
+ .status-mark.stopping { background: var(--warn); opacity: .55; }
330
+ .status-mark.ready { background: var(--ok); }
331
+ .status-mark.failed, .status-mark.offline { background: var(--err); }
332
+
333
+ /* ---------- 会话区 / 事件时间线 ---------- */
334
+ .conversation { min-width: 0; }
335
+ .empty-state { min-height: 480px; display: grid; place-content: center; justify-items: start; padding: 40px clamp(24px, 8vw, 100px); }
336
+ .empty-rule { width: 84px; height: 6px; border-radius: 100px; background: linear-gradient(90deg, var(--accent-bright), var(--accent)); box-shadow: var(--mini-shadow); margin-bottom: 24px; border: 0; }
337
+ .empty-state h2 { margin: 0 0 10px; font-size: clamp(28px, 5vw, 54px); letter-spacing: -.04em; font-weight: 800; font-style: italic; color: var(--ink); }
338
+ .empty-state p { max-width: 52ch; margin: 0; color: var(--ink-2); line-height: 1.7; }
339
+ /* 行号必须钉死。会话视图里有一个"有时才出现"的子元素(加载更早),靠自动放置的话
340
+ 它一出现就顶替掉 1fr 那一行:加载条被撑成 320px 的巨型胶囊,日志反而被挤到 auto 行
341
+ (撑不到应有的高度)。显式 grid-row 让可选子元素的出现/消失不影响日志拿到 1fr。
342
+ 列也必须写成 minmax(0, 1fr):隐式 auto 列的下限是 min-content,头部那串 nowrap 徽标
343
+ (DEEPSPEK-HARNESS-DESKTOP + LOCAL-BOUJOY-HARNESS-MAIN-…)会把它顶到 356px,
344
+ 于是整个会话视图比手机屏还宽——标题、模型行、输入框一起被切在屏幕外。 */
345
+ .session-view { min-height: calc(100vh - 120px); min-height: calc(100dvh - 120px); display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto minmax(320px, 1fr) auto; }
346
+ .session-view > .session-header { grid-row: 1; }
347
+ .session-view > .history-more { grid-row: 2; }
348
+ .session-view > .event-log { grid-row: 3; }
349
+ .session-view > .composer { grid-row: 4; }
350
+ /* 头部子元素允许收缩:超出的 nowrap 文本由自己裁掉,而不是把整列顶宽。 */
351
+ .session-header > * { min-width: 0; }
352
+ .session-header { padding: 24px 0 22px 4px; display: flex; justify-content: space-between; gap: 24px; align-items: flex-end; }
353
+ .session-header h2 { margin: 5px 0; font-size: clamp(24px, 4vw, 38px); letter-spacing: -.035em; font-weight: 800; font-style: italic; color: var(--ink); }
354
+ .session-error { max-width: 720px; margin: 10px 0 0; padding: 12px 14px; border-radius: 18px; background: linear-gradient(176deg, rgba(255,255,255,0.55), rgba(215,120,120,0.4)); box-shadow: var(--mini-shadow); border: 1px solid rgba(220,60,60,0.35); color: var(--err); font-size: 13px; line-height: 1.55; overflow-wrap: anywhere; }
355
+ /* "桌面端没连上"不是已经执行失败,只是还没接上:同一条消息槽,换成中性玻璃卡片,
356
+ 红色警报留给真正失败的东西。 */
357
+ .session-error.hint { background: var(--glass-bg-strong); border: 1.92px solid rgba(171, 171, 171, .8); box-shadow: var(--panel-shadow); color: var(--ink); }
358
+ .session-meta { display: flex; gap: 8px; color: var(--accent); font-size: 10px; font-weight: 800; font-style: italic; letter-spacing: .1em; text-transform: uppercase; }
359
+ #control-status { margin: 0; color: var(--ink-3); font-size: 12px; font-style: italic; font-weight: 600; }
360
+ .session-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
361
+ .model-control { display: grid; grid-template-columns: minmax(150px, 220px) minmax(112px, 150px) auto; gap: 10px; align-items: end; }
362
+ .model-control label { display: grid; gap: 4px; color: var(--ink-3); font-size: 10px; font-weight: 800; font-style: italic; letter-spacing: .08em; text-transform: uppercase; }
363
+ .model-control select { min-width: 0; }
364
+ .model-control small { grid-column: 1 / -1; color: var(--ink-3); font-size: 11px; line-height: 1.4; font-style: italic; }
365
+
366
+ .event-log { min-height: 320px; max-height: calc(100vh - 290px); max-height: calc(100dvh - 290px); overflow-y: auto; padding: 24px 0 40px 4px; }
367
+ .event-entry { display: grid; grid-template-columns: 74px minmax(0, 1fr); gap: 16px; padding: 9px 0; align-items: start; }
368
+ .event-time { color: var(--ink-2); font-size: 11px; font-weight: 700; letter-spacing: .06em; font-variant-numeric: tabular-nums; padding-top: 4px; }
369
+ .event-body { max-width: 72ch; line-height: 1.62; overflow-wrap: anywhere; color: var(--ink-2); }
370
+ .event-body p { margin: 0; white-space: pre-wrap; }
371
+ .event-body strong { display: block; margin-bottom: 3px; font-size: 11px; font-weight: 800; font-style: italic; letter-spacing: .06em; color: var(--accent); }
372
+ .message-markdown { min-width: 0; color: inherit; }
373
+ .message-markdown > :first-child { margin-top: 0; }
374
+ .message-markdown > :last-child { margin-bottom: 0; }
375
+ .message-markdown p { margin: 0 0 10px; white-space: normal; }
376
+ .message-markdown h1, .message-markdown h2, .message-markdown h3 { margin: 16px 0 8px; color: var(--ink); line-height: 1.25; letter-spacing: -.02em; font-style: italic; }
377
+ .message-markdown h1 { font-size: 22px; }
378
+ .message-markdown h2 { font-size: 19px; }
379
+ .message-markdown h3 { font-size: 16px; }
380
+ .message-markdown ul, .message-markdown ol { margin: 8px 0 12px; padding-left: 1.35em; }
381
+ .message-markdown li + li { margin-top: 4px; }
382
+ .message-markdown code { padding: 2px 8px; border-radius: 100px; background: linear-gradient(132.39deg, rgba(150,210,255,0.5), rgba(80,150,220,0.35)); color: #0a3a66; font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; font-size: .9em; }
383
+ .message-markdown pre { margin: 12px 0; padding: 14px 16px; overflow-x: auto; border-radius: 16px; background: linear-gradient(132.39deg, #3a4150, #23272f); color: #f5f1e8; line-height: 1.55; white-space: pre; box-shadow: var(--mini-shadow); }
384
+ .message-markdown pre code { padding: 0; background: transparent; color: inherit; font-size: 12px; }
385
+ .message-markdown blockquote { margin: 10px 0; padding: 8px 14px; border-radius: 12px; background: rgba(255,255,255,0.4); box-shadow: inset 2px 2px 4px rgba(0,0,0,0.08), inset -2px -2px 4px rgba(255,255,255,0.5); color: var(--ink-2); }
386
+ .message-markdown hr { margin: 16px 0; border: 0; border-top: 1.5px solid rgba(120,130,140,0.35); }
387
+
388
+ /* 代码块:独立卡片,语言标记 + 复制,横向滚动不撑破页面 */
389
+ .md-code { margin: 12px 0; border-radius: 16px; overflow: hidden; background: linear-gradient(132.39deg, #333a47, #1f232a); box-shadow: var(--mini-shadow); }
390
+ .md-code-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 8px 6px 12px; background: rgba(255,255,255,0.06); }
391
+ .md-code-lang { font-size: 10px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: rgba(245,241,232,0.72); font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; }
392
+ .md-code-copy { min-height: 28px; padding: 0 12px; border-radius: 100px; border: 1px solid rgba(245,241,232,0.28); background: rgba(255,255,255,0.08); color: rgba(245,241,232,0.88); font-size: 11px; font-weight: 700; }
393
+ .md-code-copy:active { transform: scale(0.96); }
394
+ .md-code pre { margin: 0; border-radius: 0; box-shadow: none; background: transparent; padding: 12px 14px; }
395
+
396
+ /* 表格:真实表格 + 自身横向滚动,数值列按对齐规则 */
397
+ .md-table-wrap { margin: 12px 0; overflow-x: auto; border-radius: 14px; border: 1.4px solid rgba(150,160,170,0.35); background: rgba(255,255,255,0.55); -webkit-overflow-scrolling: touch; }
398
+ .md-table { width: 100%; border-collapse: collapse; font-size: 12.5px; line-height: 1.45; }
399
+ .md-table th, .md-table td { padding: 8px 10px; text-align: left; vertical-align: top; border-bottom: 1px solid rgba(150,160,170,0.28); }
400
+ .md-table th { background: rgba(80,150,220,0.16); color: var(--ink); font-weight: 800; white-space: nowrap; }
401
+ .md-table tbody tr:nth-child(even) { background: rgba(255,255,255,0.42); }
402
+ .md-table tbody tr:last-child td { border-bottom: 0; }
403
+ .md-table code { font-size: 11.5px; }
404
+
405
+ /* 公式:行内跟随文字,块级单独居中且可横向滚动 */
406
+ .message-markdown .math-tex { font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; }
407
+ .md-math { margin: 12px 0; padding: 10px 12px; overflow-x: auto; border-radius: 14px; background: rgba(255,255,255,0.5); box-shadow: inset 0 1px 2px rgba(0,0,0,0.06); text-align: center; }
408
+ .md-math .katex-display { margin: 0; }
409
+ .md-math .katex { font-size: 1.05em; }
410
+ .message-markdown .katex { font-size: 1.02em; }
411
+ .event-entry.user .event-body { color: #0a3a66; font-weight: 650; }
412
+ .event-entry.tool .event-body { color: var(--ink-2); font-size: 13px; } /* 底板是浅色玻璃,次级文字不能再用 45% 黑 */
413
+ .event-entry.error .event-body { color: var(--err); }
414
+
415
+ /* ---------- 无底板可读性:给字形描边,而不是给文字垫一层遮罩 ---------- */
416
+ /* 文字层底板保持透明(用户要求),可读性全部来自整页遮罩的地板——**不再给字形描边**:
417
+ 之前那圈 1px + 2px 的白色 text-shadow 会把每个字的边缘糊掉,这正是"文字很模糊"的来源。
418
+ 地板亮度 0.321,下列颜色对它的实测对比都在 AA 之上,主文还过了 AAA——
419
+ #14141c 6.47:1、#2b3038 4.69:1、#0a2f4d 4.9:1、#0d3049 4.84:1、#5f120f 4.65:1。
420
+ 地板是浅灰蓝,彩色文字(原来的 accent 蓝、err 红)在上面只有 1.0–1.2:1,
421
+ 所以色相只留一点,层次靠字重、字号与斜体。 */
422
+ :root {
423
+ --on-photo-ink: #14141c; /* 正文 */
424
+ --on-photo-soft: #2b3038; /* 次级:时间列、工具输出、状态、空态说明 */
425
+ --on-photo-label: #0d3049; /* 斜体标签 */
426
+ --on-photo-user: #0a2f4d; /* 用户消息 */
427
+ --on-photo-error: #5f120f; /* 异常行 */
428
+ }
429
+ .event-entry .event-body,
430
+ .message-markdown h1,
431
+ .message-markdown h2,
432
+ .message-markdown h3,
433
+ .session-header h2,
434
+ .empty-state h2 { color: var(--on-photo-ink); }
435
+ .event-entry.user .event-body { color: var(--on-photo-user); }
436
+ .event-entry.tool .event-body,
437
+ .event-time,
438
+ .session-meta,
439
+ #control-status,
440
+ .empty-state p { color: var(--on-photo-soft); }
441
+ .event-body strong { color: var(--on-photo-label); }
442
+ .event-entry.error .event-body { color: var(--on-photo-error); }
443
+
444
+ /* ------------------------------------------------------------------
445
+ 弹层组件词表:所有"点开才出现"的浮层共用同一套配方
446
+ — 132.39deg 玻璃底 + blur(13.44px) saturate(135%) + 1.92px 灰边框
447
+ — panel-shadow、顶部光带、内描边(见文件开头的 .glass-popover::before/::after)
448
+ 小标题统一为 11px / 800 / 斜体 / .06em 大写的 ink-3,与 .create-form label 一致。
449
+ ------------------------------------------------------------------ */
450
+ .glass-popover {
451
+ /* 定位交给 JS:absolute 会把"很窄的触发按钮"当成包含块(手机端 .auto-approve 只有
452
+ 按钮那么宽),面板于是整块向左溢出屏幕。fixed + 打开时按视口计算坐标,才能保证
453
+ 永远落在手机框内,并且在下方放不下时翻到上方。 */
454
+ position: fixed;
455
+ z-index: 30;
456
+ display: grid;
457
+ gap: 10px;
458
+ padding: 14px;
459
+ border-radius: 20px;
460
+ /* 兜底:即使脚本没跑或内容异常长,也不允许越过视口 */
461
+ max-width: calc(100vw - 16px);
462
+ max-height: calc(100dvh - 16px);
463
+ overflow: auto;
464
+ /* 与 .create-sheet 同一套:同样的玻璃底、同样的 blur(20px) saturate(140%)、
465
+ 同样的 1.92px 灰边框 —— "点开才出现"的面板共用一种材质。 */
466
+ background: var(--glass-bg-strong);
467
+ -webkit-backdrop-filter: blur(20px) saturate(140%);
468
+ backdrop-filter: blur(20px) saturate(140%);
469
+ border: 1.92px solid rgba(171, 171, 171, .8);
470
+ box-shadow: var(--panel-shadow);
471
+ }
472
+ .glass-popover[hidden] { display: none; }
473
+
474
+ .field { display: grid; gap: 6px; }
475
+ .field-label {
476
+ color: var(--ink-3);
477
+ font-size: 11px;
478
+ font-weight: 800;
479
+ font-style: italic;
480
+ letter-spacing: .06em;
481
+ text-transform: uppercase;
482
+ }
483
+
484
+ /* 分段控件:原生 radio 保留语义与键盘操作,视觉上换成玻璃胶囊 */
485
+ .segmented {
486
+ display: flex;
487
+ gap: 4px;
488
+ padding: 3px;
489
+ border-radius: 100px;
490
+ background: rgba(255, 255, 255, 0.34);
491
+ box-shadow: inset 2px 2px 6px rgba(0, 0, 0, 0.10), inset -2px -2px 6px rgba(255, 255, 255, 0.55);
492
+ }
493
+ .segment { flex: 1; min-width: 0; position: relative; }
494
+ .segment input { position: absolute; inset: 0; opacity: 0; margin: 0; pointer-events: none; }
495
+ .segment span {
496
+ display: grid;
497
+ place-items: center;
498
+ min-height: 34px;
499
+ padding: 0 8px;
500
+ border-radius: 100px;
501
+ font-size: 12px;
502
+ font-weight: 800;
503
+ font-style: italic;
504
+ color: var(--ink-2);
505
+ transition: background .16s ease, color .16s ease, box-shadow .16s ease;
506
+ }
507
+ .segment input:checked + span {
508
+ background: linear-gradient(0deg, rgba(0, 179, 255, 0.25), rgba(0, 179, 255, 0.25)),
509
+ linear-gradient(132.39deg, rgba(255, 255, 255, 0.95) 15.21%, rgba(128, 128, 128, 0.55) 89.39%);
510
+ color: var(--ink);
511
+ box-shadow: inset 0 0 0 1.4px rgba(255, 255, 255, 0.85), 0 2px 6px rgba(0, 0, 0, 0.12);
512
+ }
513
+ .segment input:focus-visible + span { box-shadow: 0 0 0 3px var(--focus); }
514
+
515
+ /* 开关:同样是"原生 checkbox + 玻璃轨道" */
516
+ .switch { display: flex; align-items: center; gap: 10px; cursor: pointer; }
517
+ .switch input { position: absolute; opacity: 0; pointer-events: none; }
518
+ .switch-track {
519
+ flex: none;
520
+ position: relative;
521
+ width: 44px;
522
+ height: 26px;
523
+ border-radius: 100px;
524
+ background: rgba(255, 255, 255, 0.42);
525
+ box-shadow: inset 2px 2px 6px rgba(0, 0, 0, 0.16), inset -2px -2px 6px rgba(255, 255, 255, 0.6);
526
+ transition: background .18s ease;
527
+ }
528
+ .switch-knob {
529
+ position: absolute;
530
+ top: 3px;
531
+ left: 3px;
532
+ width: 20px;
533
+ height: 20px;
534
+ border-radius: 50%;
535
+ background: var(--solid-glass);
536
+ box-shadow: var(--knob-shadow);
537
+ transition: transform .18s ease;
538
+ }
539
+ .switch input:checked + .switch-track { background: linear-gradient(0deg, rgba(0, 179, 255, 0.35), rgba(0, 179, 255, 0.35)), rgba(255, 255, 255, 0.5); }
540
+ .switch input:checked + .switch-track .switch-knob { transform: translateX(18px); }
541
+ .switch input:focus-visible + .switch-track { box-shadow: 0 0 0 3px var(--focus); }
542
+ .switch-text { color: var(--ink-2); font-size: 12px; line-height: 1.45; }
543
+
544
+ /* 选择器:隐藏原生 select(它仍是唯一的状态来源),点击弹出玻璃列表 */
545
+ /* 轨道必须写成 minmax(0, 1fr):`auto` 轨道的下限是 min-content,模型名一长
546
+ (DeepSeek · DeepSeek-V4-Flash-Vision-Exp 这类)就会把轨道顶到 358px,
547
+ width:100% 的触发按钮跟着溢出自己的格子,直接盖住右边的推理强度与切换按钮。 */
548
+ .picker { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; min-width: 0; }
549
+ .picker-native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
550
+ .picker-trigger {
551
+ display: flex;
552
+ align-items: center;
553
+ justify-content: space-between;
554
+ gap: 8px;
555
+ width: 100%;
556
+ min-width: 0;
557
+ overflow: hidden;
558
+ min-height: 40px;
559
+ padding: 0 12px;
560
+ border-radius: 14px;
561
+ border: 1.4px solid rgba(171, 171, 171, .8);
562
+ background: rgba(255, 255, 255, .6);
563
+ color: var(--ink);
564
+ font-size: 13px;
565
+ font-weight: 700;
566
+ text-align: left;
567
+ }
568
+ .picker-trigger:disabled { opacity: .55; }
569
+ .picker-trigger[aria-expanded="true"] { box-shadow: 0 0 0 3px var(--focus); }
570
+ .picker-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
571
+ .picker-chevron { flex: none; width: 14px; height: 14px; color: var(--ink-3); transition: transform .16s ease; }
572
+ .picker-trigger[aria-expanded="true"] .picker-chevron { transform: rotate(180deg); }
573
+ .picker-panel { width: min(320px, calc(100vw - 16px)); max-height: min(60dvh, 320px); }
574
+ .picker-search {
575
+ width: 100%;
576
+ height: 34px;
577
+ min-height: 34px;
578
+ padding: 0 12px;
579
+ border-radius: 100px;
580
+ border: 1.4px solid rgba(171, 171, 171, .7);
581
+ background: rgba(255, 255, 255, .66);
582
+ font-size: 12px;
583
+ color: var(--ink);
584
+ }
585
+ .picker-options { display: grid; gap: 2px; overflow-y: auto; max-height: min(45dvh, 240px); padding-right: 2px; }
586
+ .picker-option {
587
+ display: grid;
588
+ grid-template-columns: minmax(0, 1fr);
589
+ min-height: 38px;
590
+ padding: 8px 10px;
591
+ border: 0;
592
+ border-radius: 12px;
593
+ background: transparent;
594
+ color: var(--ink-2);
595
+ font-size: 12.5px;
596
+ font-weight: 600;
597
+ text-align: left;
598
+ }
599
+ .picker-option:hover { background: rgba(255, 255, 255, .42); }
600
+ .picker-option[aria-selected="true"] {
601
+ background: var(--glass-bg);
602
+ box-shadow: inset 0 0 0 1.6px rgba(0, 179, 255, .28);
603
+ color: var(--ink);
604
+ font-weight: 750;
605
+ }
606
+ .picker-empty { padding: 10px; color: var(--ink-3); font-size: 12px; font-style: italic; }
607
+
608
+ /* 自动放行:与弹层词表共用配方,按钮沿用系统既有按钮 */
609
+ .auto-approve { position: relative; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
610
+ .auto-approve-panel { width: min(320px, calc(100vw - 16px)); }
611
+ .auto-approve-lede, .auto-approve-note { margin: 0; color: var(--ink-2); font-size: 12px; line-height: 1.5; }
612
+ .auto-approve-note { color: var(--ink-3); font-size: 11px; font-style: italic; }
613
+ .auto-approve-panel .primary-button { width: 100%; justify-content: center; }
614
+ .auto-approve-pill {
615
+ display: inline-flex;
616
+ align-items: center;
617
+ gap: 8px;
618
+ min-height: 34px;
619
+ padding: 0 14px;
620
+ border-radius: 100px;
621
+ border: 1.6px solid rgba(177, 175, 175, 1);
622
+ background: var(--glass-bg-strong);
623
+ -webkit-backdrop-filter: var(--glass-blur);
624
+ backdrop-filter: var(--glass-blur);
625
+ box-shadow: var(--mini-shadow);
626
+ color: var(--ink);
627
+ font-size: 12px;
628
+ font-weight: 800;
629
+ font-style: italic;
630
+ font-variant-numeric: tabular-nums;
631
+ }
632
+ .auto-approve-pill::before {
633
+ content: "";
634
+ width: 7px;
635
+ height: 7px;
636
+ border-radius: 50%;
637
+ background: var(--ok);
638
+ box-shadow: 0 0 0 3px rgba(0, 170, 140, .2);
639
+ }
640
+ .auto-approve-pill[hidden] { display: none; }
641
+ /* 批准请求:sx-alert 配方 */
642
+ .approval-entry {
643
+ padding: 14px;
644
+ border-radius: 25px;
645
+ background: linear-gradient(176deg, rgba(255,255,255,0.55), rgba(189,197,127,0.35));
646
+ box-shadow: -6px -6px 36px rgba(255,255,255,0.96), 6px 6px 36px rgba(0,0,0,0.25), inset -11px -11px 12px rgba(255,255,255,0.8), inset 11px 15px 8px rgba(0,0,0,0.12);
647
+ border: 1.92px solid rgba(184,184,184,1);
648
+ -webkit-backdrop-filter: blur(13px) saturate(135%);
649
+ backdrop-filter: blur(13px) saturate(135%);
650
+ color: var(--ink);
651
+ }
652
+ .approval-entry strong { color: var(--warn); }
653
+ .approval-actions { display: flex; gap: 10px; margin-top: 12px; }
654
+ .approval-actions button { border: 1.92px solid rgba(171,171,171,1); border-radius: 100px; padding: 0 18px; min-height: 40px; font-size: 12px; font-weight: 800; font-style: italic; }
655
+ .approve { background: linear-gradient(0deg, rgba(0,179,255,0.25), rgba(0,179,255,0.25)), linear-gradient(132.39deg, rgba(255,255,255,0.6) 15.21%, rgba(128,128,128,0.5) 89.39%); color: var(--ink); box-shadow: var(--mini-shadow); }
656
+ .deny { background: linear-gradient(132.39deg, rgba(255,175,175,0.6), rgba(215,110,110,0.45)); color: var(--err); box-shadow: var(--mini-shadow); }
657
+
658
+ /* Agent 提问:与批准同一种玻璃卡片,内部是可直接点选的真实表单 */
659
+ .input-entry {
660
+ padding: 14px;
661
+ border-radius: 25px;
662
+ background: linear-gradient(176deg, rgba(255,255,255,0.55), rgba(189,197,127,0.35));
663
+ box-shadow: -6px -6px 36px rgba(255,255,255,0.96), 6px 6px 36px rgba(0,0,0,0.25), inset -11px -11px 12px rgba(255,255,255,0.8), inset 11px 15px 8px rgba(0,0,0,0.12);
664
+ border: 1.92px solid rgba(184,184,184,1);
665
+ -webkit-backdrop-filter: blur(13px) saturate(135%);
666
+ backdrop-filter: blur(13px) saturate(135%);
667
+ color: var(--ink);
668
+ }
669
+ .input-entry strong { color: var(--warn); }
670
+ .input-question { margin-top: 12px; }
671
+ .input-header { margin: 0 0 4px; font-size: 11px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
672
+ .input-prompt { margin: 0 0 10px; font-size: 14px; line-height: 1.5; }
673
+ .input-options { display: grid; gap: 8px; }
674
+ .input-option { display: flex; gap: 8px; align-items: flex-start; padding: 10px 12px; border-radius: 18px; border: 1.4px solid rgba(171,171,171,0.7); background: rgba(255,255,255,0.45); font-size: 13px; cursor: pointer; }
675
+ .input-option input { margin: 2px 0 0; accent-color: rgba(0,119,179,0.9); }
676
+ .input-option-note { display: block; margin-top: 2px; color: var(--ink-3); font-size: 11px; line-height: 1.4; }
677
+ .input-custom { margin-top: 10px; width: 100%; min-height: 42px; border-radius: 100px; padding: 0 14px; border: 1.4px solid rgba(171,171,171,0.8); background: var(--glass-bg-strong); color: var(--ink); font-size: 13px; }
678
+ .input-custom:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus); }
679
+ /* 已作答的提问卡:保留问题与选项文本(读者需要知道当时问了什么),但不再有任何可点控件,
680
+ 并在末尾写明结局。以前答完卡片仍带着按钮,刷新后按钮还能点,一点必然 409。 */
681
+ .input-entry.is-settled { opacity: .84; }
682
+ .input-entry.is-settled strong { color: var(--ink-3); }
683
+ .input-settled { margin: 10px 0 0; color: #0b5f47; font-size: 11.5px; font-weight: 800; font-style: italic; letter-spacing: .04em; }
684
+ .input-option.settled { cursor: default; color: var(--ink-2); }
685
+ .input-option.settled::before { content: "·"; margin-right: 6px; color: var(--ink-3); }
686
+
687
+ /* 输入区:sx-glass-field 容器 */
688
+ /* 只有一列:真正的布局在 .composer-row(附件 + 文本 + 发送)。这里原来还留着
689
+ `1fr 48px` 两列——那是"文本在左、发送键在右列"的老结构,DOM 改成单行 flex 后
690
+ 第二列就永远空着,于是发送键右侧多出 69px 空隙(48 列 + 10 gap + 10 padding + 描边)。 */
691
+ .composer { margin: 0 0 18px 4px; padding: 10px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-items: end; background: var(--glass-bg-strong); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); border: 1.92px solid rgba(171,171,171,0.8); border-radius: var(--radius); box-shadow: var(--panel-shadow); overflow: hidden; }
692
+ .composer:focus-within { box-shadow: var(--panel-shadow), 0 0 0 3px var(--focus); }
693
+ /* 一行高就够:输入多行时由 app.js 按 scrollHeight 长到 max-height。96px 的最小高度
694
+ 会让空输入框在宽屏上变成一个巨大的空盒子(文字顶对齐、按钮底对齐)。 */
695
+ .composer textarea { min-height: 48px; max-height: min(320px, 45vh); resize: none; padding: 12px 14px; border: 0; background: transparent; line-height: 1.5; box-shadow: none; color: var(--ink); }
696
+ .composer textarea:focus-visible { outline: 0; box-shadow: none; }
697
+ .send-button { width: 48px; height: 48px; min-height: 48px; border: 1.92px solid rgba(177,175,175,1); border-radius: 100px; background: linear-gradient(132deg, rgba(255,255,255,0.48), rgba(0,119,179,0.41)); color: var(--ink); display: grid; place-items: center; box-shadow: var(--icon-btn-shadow); transition: transform .15s ease; overflow: hidden; }
698
+ .send-button:hover { transform: translateY(-2px) scale(1.06); }
699
+ .send-button:active { transform: scale(0.94); }
700
+
701
+ /* ---------- 配对 / 密钥全屏页 ---------- */
702
+ .pairing-screen { min-height: 100vh; min-height: 100dvh; padding: 28px; display: grid; place-content: center; justify-items: start; }
703
+ .pairing-screen > * { position: relative; }
704
+ /* 背景图之后,配对/密钥页直接用正文浮在遮罩上:加一层柔和底板保证可读 */
705
+ .pairing-screen::before { content: ""; position: fixed; inset: 0; z-index: -1; background: radial-gradient(120% 80% at 30% 20%, rgba(255,255,255,0.55), rgba(255,255,255,0.15) 70%); }
706
+ .pairing-mark { width: 68px; height: 68px; border-radius: 50%; margin-bottom: 28px; font-size: 20px; position: relative; }
707
+ .pairing-mark::before { content: ""; position: absolute; inset: 2px; border-radius: 50%; background: var(--knob-glow); pointer-events: none; }
708
+ .pairing-screen h1 { margin: 0 0 12px; font-size: clamp(34px, 9vw, 64px); letter-spacing: -.04em; font-weight: 800; font-style: italic; color: var(--ink); }
709
+ .pairing-screen p { margin: 0; color: var(--ink-2); font-size: 17px; }
710
+ .access-form { display: flex; gap: 10px; margin-top: 24px; width: min(420px, 100%); }
711
+ .access-form input { flex: 1; min-width: 0; height: 50px; border: 1.92px solid rgba(171,171,171,1); border-radius: 100px; padding: 0 18px; font-size: 14px; background: var(--glass-bg-strong); box-shadow: var(--mini-shadow); color: var(--ink); }
712
+
713
+ /* 加载条:sx-progress 药丸 */
714
+ .loader { width: min(320px, 70vw); height: 18px; margin-top: 32px; border-radius: 100px; background: linear-gradient(132.15deg, rgba(128,128,128,0.55) 18.15%, rgba(255,255,255,0.55) 82.6%); box-shadow: -6px -6px 14px rgba(255,255,255,0.6), 6px 6px 14px rgba(128,128,128,0.5), inset 2px 2px 4px rgba(0,0,0,0.18), inset -2px -2px 4px rgba(255,255,255,0.4); overflow: hidden; }
715
+ .loader::after { content: ""; display: block; width: 36%; height: 100%; border-radius: 100px; background: linear-gradient(115.41deg, rgba(0,200,255,0.55), rgba(0,140,220,0.55)); box-shadow: inset 2px 2px 3px rgba(255,255,255,0.3); animation: load 1.2s cubic-bezier(.2,.8,.2,1) infinite; }
716
+ @keyframes load { from { transform: translateX(-100%); } to { transform: translateX(380%); } }
717
+
718
+ /* Toast:sx-toast 浅色玻璃 */
719
+ .toast { position: fixed; left: 50%; bottom: max(24px, env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 30; max-width: min(520px, calc(100vw - 32px)); padding: 16px 20px; border-radius: 20px; background: var(--glass-bg-strong); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); border: 1px solid rgba(255,255,255,0.65); color: var(--ink-2); font-size: 13px; font-weight: 600; box-shadow: var(--panel-shadow); overflow: hidden; }
720
+
721
+ /* ---------- 移动端 ---------- */
722
+ @media (max-width: 780px) {
723
+ /* 顶栏一行:品牌(可压缩)+ 连接状态。抽屉开关是固定在左上的浮层,用左内边距让位。 */
724
+ .topbar { grid-template-columns: minmax(0, 1fr) auto; gap: 8px; min-height: 44px; padding: 4px 10px 4px 58px; margin: max(6px, env(safe-area-inset-top)) 10px 0; top: max(6px, env(safe-area-inset-top)); border-radius: 16px; }
725
+ .connection { grid-column: auto; padding: 4px 10px; font-size: 10.5px; gap: 6px; }
726
+ .machine-name { display: none; }
727
+ .brand { min-width: 0; gap: 8px; padding: 2px 0; font-size: 13px; }
728
+ .brand-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
729
+ .brand-mark { width: 28px; height: 28px; border-radius: 10px; font-size: 11px; }
730
+ .pairing-strip { margin: 14px 10px; flex-direction: column; align-items: flex-start; padding: 20px; }
731
+ /* 手机端"下次从这里继续"折叠成一行,把竖向空间还给对话 */
732
+ .return-entry { margin: 10px 10px 0; padding: 10px 12px; align-items: center; flex-direction: row; gap: 10px; }
733
+ .return-entry > div:first-child { min-width: 0; }
734
+ .return-entry strong { font-size: 13px; }
735
+ #return-details { display: none; }
736
+ .return-entry.expanded { flex-direction: column; align-items: stretch; }
737
+ .return-entry.expanded #return-details { display: block; }
738
+ #return-details p { display: none; }
739
+ #return-details code { display: block; margin-top: 6px; max-width: calc(100vw - 60px); white-space: normal; overflow-wrap: anywhere; }
740
+ .return-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
741
+ .return-actions .secondary-button { min-height: 34px; padding: 0 12px; font-size: 12px; }
742
+ .return-actions .text-button { padding: 0; font-size: 12px; }
743
+ .pairing-copy code { white-space: normal; overflow-wrap: anywhere; }
744
+ .notify-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
745
+ .notify-row h3 { margin: 0 0 4px; font-size: 15px; font-weight: 800; font-style: italic; color: var(--ink); }
746
+ .notify-row p { margin: 0; color: var(--ink-2); font-size: 13px; line-height: 1.5; }
747
+ .notify-row button { flex: none; }
748
+ @media (max-width: 780px) { .notify-row { flex-direction: column; align-items: stretch; gap: 10px; } }.bridge-shutdown { align-items: stretch; flex-direction: column; }
749
+ .bridge-shutdown .danger-button { width: 100%; }
750
+ .workspace { margin: 0; display: block; }
751
+ .conversation { border-top: 0; }
752
+ .empty-state { min-height: 340px; }
753
+ .session-view { min-height: calc(100vh - 132px); min-height: calc(100dvh - 132px); }
754
+ /* 会话头压缩:标题最多两行、meta 单行省略,把首屏让给对话 */
755
+ .session-header { padding: 12px 14px 10px; align-items: flex-start; flex-direction: column; gap: 10px; }
756
+ /* 纵向堆叠时 align-items:flex-start 会让子块按"内容宽度"布局,而头部的项目徽标是
757
+ nowrap 的(DEEPSPEK-HARNESS-DESKTOP + LOCAL-BOUJOY-HARNESS-MAIN-…),内容宽度
758
+ 328px > 手机可用宽度,整块就顶出屏幕。让子块撑满并允许收缩,徽标自己省略。 */
759
+ .session-header > * { width: 100%; min-width: 0; }
760
+ .session-header h2 { margin: 2px 0; font-size: 19px; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
761
+ .session-meta { flex-wrap: nowrap; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
762
+ .session-meta span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
763
+ .session-actions { width: 100%; justify-content: flex-start; gap: 8px; }
764
+ /* 模型选择与「切换模型」并排一行,按钮缩成次要动作 */
765
+ .model-control { width: 100%; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto; gap: 8px; }
766
+ .model-control #apply-model { grid-column: auto; min-height: 38px; padding: 0 12px; font-size: 11px; }
767
+ .model-control small { grid-column: 1 / -1; }
768
+ .event-log { max-height: none; min-height: 340px; padding: 14px 14px 32px; }
769
+ .event-entry { grid-template-columns: 52px minmax(0, 1fr); gap: 10px; }
770
+ .composer { position: sticky; bottom: 10px; margin: 0 10px; z-index: 6; padding: 10px; }
771
+ }
772
+
773
+ /* 窄屏(≤480px):模型名经常很长(DeepSeek · DeepSeek-V4-Flash-Vision-Exp),三个控件
774
+ 挤一行只能靠省略号,能读到的信息太少。让模型选择独占第一行,推理强度与「切换模型」
775
+ 并排第二行——多花约一行高度,换回一个看得清的模型名。 */
776
+ @media (max-width: 480px) {
777
+ .model-control { grid-template-columns: minmax(0, 1fr) auto; }
778
+ #model-picker { grid-column: 1 / -1; }
779
+ #reasoning-control { grid-column: 1; }
780
+ .model-control #apply-model { grid-column: 2; }
781
+ }
782
+
783
+ /* 极窄屏(≤360px):只留 AB 方块和状态圆点,保证三者在同一行 */
784
+ @media (max-width: 360px) {
785
+ .brand-text { display: none; }
786
+ #connection-status span:last-child { display: none; }
787
+ .topbar { padding-right: 8px; }
788
+ #connection-status { padding: 4px 8px; }
789
+ }
790
+ /* ---------- 动效与透明度回退 ---------- */
791
+ @media (prefers-reduced-motion: reduce) {
792
+ .loader::after { animation: none; width: 100%; }
793
+ .primary-button, .secondary-button, .danger-button, .icon-button, .send-button, .drawer-agent, .drawer-session { transition: none; }
794
+ .primary-button:hover, .secondary-button:hover, .danger-button:hover, .icon-button:hover, .send-button:hover { transform: none; }
795
+ }
796
+
797
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
798
+ .topbar, .pairing-strip, .return-entry, .composer, .toast, .glass-popover, .drawer-card { background: #eceef1; }
799
+ .approval-entry, .input-entry { background: #f0ead8; }
800
+ }
801
+
802
+ @media (prefers-reduced-transparency: reduce) {
803
+ .topbar, .pairing-strip, .return-entry, .composer, .toast, .approval-entry, .input-entry, .agent-drawer, .create-sheet, .glass-popover, .drawer-card,
804
+ .primary-button, .secondary-button, .danger-button, .icon-button, .send-button, select, input {
805
+ -webkit-backdrop-filter: none;
806
+ backdrop-filter: none;
807
+ background: #eceef1;
808
+ }
809
+ .approval-entry, .input-entry { background: #f0ead8; }
810
+ }
811
+
812
+ /* ---------- 抽屉:Agent → 项目 → 会话 ---------- */
813
+ /* 手机上是覆盖层,桌面沿用左侧常驻栏;同一个 DOM,两套呈现。 */
814
+ .drawer-toggle { display: none; width: 40px; height: 40px; min-height: 40px; padding: 0; border: 1.92px solid rgba(177,175,175,0.9); border-radius: 14px; background: var(--glass-bg-strong); color: var(--ink); place-items: center; box-shadow: var(--mini-shadow); }
815
+ .drawer-toggle:active { transform: scale(.95); }
816
+ @media (max-width: 780px) {
817
+ /* 固定在视口左上角:对话滚到任何位置都能一键回到 Agent / 项目切换。
818
+ 它必须位于顶栏之外——顶栏的 backdrop-filter 会成为 fixed 子元素的包含块。 */
819
+ .drawer-toggle {
820
+ display: grid;
821
+ position: fixed;
822
+ left: max(8px, env(safe-area-inset-left));
823
+ top: max(6px, env(safe-area-inset-top));
824
+ z-index: 20;
825
+ width: 44px;
826
+ height: 44px;
827
+ min-height: 44px;
828
+ -webkit-backdrop-filter: var(--glass-blur);
829
+ backdrop-filter: var(--glass-blur);
830
+ }
831
+ /* 抽屉打开后由抽屉自己的 ✕ / 左滑关闭,避免两个关闭入口叠在一起。 */
832
+ .drawer-toggle[aria-expanded="true"] { opacity: 0; pointer-events: none; }
833
+ }
834
+ .preview-banner { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; margin: 10px 10px 0; padding: 10px 14px; border-radius: 16px; background: linear-gradient(176deg, rgba(255,255,255,.62), rgba(189,197,127,.32)); border: 1.4px solid rgba(171,171,171,.7); box-shadow: var(--mini-shadow); font-size: 12px; color: var(--ink-2); }
835
+ .preview-banner strong { color: var(--want, var(--ink)); font-style: italic; font-weight: 800; }
836
+
837
+ .drawer-mask { position: fixed; inset: 0; z-index: 40; background: rgba(24,28,34,.32); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); opacity: 0; transition: opacity .2s ease; }
838
+ .drawer-mask.open { opacity: 1; }
839
+
840
+ .agent-drawer { position: fixed; top: 0; bottom: 0; left: 0; z-index: 41; width: min(88vw, 380px); display: flex; flex-direction: column; min-height: 0; padding: 14px 12px calc(12px + env(safe-area-inset-bottom)); background: var(--glass-bg-strong); -webkit-backdrop-filter: blur(20px) saturate(140%); backdrop-filter: blur(20px) saturate(140%); border-right: 1.92px solid rgba(171,171,171,.75); box-shadow: 18px 0 48px rgba(20,24,30,.22); transform: translateX(-102%); transition: transform .24s cubic-bezier(.22,.68,.24,1); visibility: hidden; }
841
+ .agent-drawer.open { transform: none; visibility: visible; }
842
+ @media (prefers-reduced-motion: reduce) { .agent-drawer { transition: none; } }
843
+
844
+ .drawer-head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 2px 2px 12px; }
845
+ .drawer-close { width: 36px; height: 36px; min-height: 36px; }
846
+ .drawer-heading { min-width: 0; }
847
+ .drawer-heading h2 { margin: 0; font-size: 17px; font-style: italic; font-weight: 800; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
848
+ .drawer-heading p { margin: 2px 0 0; font-size: 11px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
849
+ .drawer-connection { font-size: 10px; padding: 4px 10px; border-radius: 100px; background: var(--glass-bg); box-shadow: inset 0 0 0 1.2px rgba(255,255,255,.6); }
850
+ .drawer-connection:not(.online):not(.offline) { color: var(--ink-3); }
851
+
852
+ .drawer-search { position: relative; display: flex; align-items: center; margin-bottom: 10px; }
853
+ .drawer-search-icon { position: absolute; left: 12px; width: 16px; height: 16px; color: var(--ink-3); pointer-events: none; }
854
+ .drawer-search input { width: 100%; height: 40px; padding: 0 12px 0 36px; border-radius: 100px; border: 1.4px solid rgba(171,171,171,.8); background: rgba(255,255,255,.55); color: var(--ink); font-size: 13px; box-shadow: var(--mini-shadow); }
855
+ .drawer-search input:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus); }
856
+
857
+ .drawer-tree { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; display: grid; align-content: start; gap: 2px; padding-bottom: 8px; }
858
+
859
+ .drawer-agent { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto auto; gap: 8px; align-items: center; width: 100%; min-height: 46px; padding: 8px 10px; border: 0; border-radius: 14px; background: transparent; color: var(--ink); text-align: left; font: inherit; }
860
+ .drawer-agent:active { transform: scale(.99); }
861
+ .drawer-agent:hover { background: rgba(255,255,255,.38); }
862
+ .drawer-agent[aria-expanded="true"] { background: var(--glass-bg); box-shadow: inset 0 0 0 1.6px rgba(0,179,255,.22); }
863
+ .drawer-agent-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 800; font-style: italic; }
864
+ .drawer-agent-badge { font-size: 9.5px; font-weight: 800; letter-spacing: .04em; padding: 3px 7px; border-radius: 100px; background: rgba(0,179,255,.18); color: #0a3a66; white-space: nowrap; }
865
+ .drawer-agent-badge.attach { background: rgba(214,164,60,.22); color: #6b4a06; }
866
+ .drawer-agent-badge.unavailable { background: rgba(150,150,150,.2); color: var(--ink-3); }
867
+ .drawer-agent-count { min-width: 22px; font-size: 11px; font-weight: 800; color: var(--ink-3); text-align: right; font-variant-numeric: tabular-nums; }
868
+ .drawer-chevron { width: 16px; height: 16px; color: var(--ink-3); transition: transform .16s ease; }
869
+ .drawer-agent[aria-expanded="true"] .drawer-chevron { transform: rotate(90deg); }
870
+ .drawer-agent[aria-expanded="false"] .drawer-agent-badge { opacity: .75; }
871
+
872
+ .drawer-projects { display: grid; gap: 1px; padding: 2px 0 6px 8px; }
873
+ .drawer-project { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: center; width: 100%; min-height: 34px; padding: 4px 10px; border: 0; border-radius: 10px; background: transparent; color: var(--ink-2); text-align: left; font: inherit; }
874
+ .drawer-project-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11.5px; font-weight: 800; letter-spacing: .04em; }
875
+ .drawer-project-count { font-size: 10.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
876
+ .drawer-project .drawer-chevron { width: 13px; height: 13px; }
877
+ .drawer-project[aria-expanded="true"] .drawer-chevron { transform: rotate(90deg); }
878
+
879
+ .drawer-sessions { display: grid; gap: 2px; padding: 2px 0 4px 14px; }
880
+ .drawer-session { display: grid; grid-template-columns: 12px minmax(0, 1fr); gap: 8px; align-items: start; width: 100%; min-height: 46px; padding: 8px 10px; border: 0; border-radius: 14px; background: transparent; color: var(--ink); text-align: left; font: inherit; }
881
+ .drawer-session:hover { background: rgba(255,255,255,.38); }
882
+ .drawer-session:active { transform: scale(.99); }
883
+ .drawer-session.active { background: var(--glass-bg); box-shadow: inset 0 0 0 1.6px rgba(0,179,255,.28), var(--mini-shadow); }
884
+ .drawer-session-body { min-width: 0; }
885
+ .drawer-session-title { display: block; font-size: 12.5px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
886
+ .drawer-session-meta { display: block; margin-top: 2px; font-size: 10.5px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
887
+ .drawer-session .status-mark { margin-top: 5px; }
888
+
889
+ .drawer-empty { padding: 14px 12px; font-size: 12px; color: var(--ink-3); }
890
+ .drawer-foot { display: flex; gap: 8px; padding-top: 10px; border-top: 1px solid rgba(171,171,171,.35); }
891
+ .drawer-foot .primary-button, .drawer-foot .secondary-button { flex: 1 1 0; min-width: 0; min-height: 44px; padding: 0 12px; }
892
+ .drawer-foot .primary-button svg, .drawer-foot .secondary-button svg { width: 16px; height: 16px; flex: none; }
893
+
894
+ /* ---------- 抽屉即导航 ---------- */
895
+ /* 手机:覆盖层 + 遮罩;宽屏:常驻侧栏,内容整体右移。 */
896
+ .workspace { display: block; margin: 26px auto; }
897
+ @media (min-width: 781px) {
898
+ .agent-drawer {
899
+ display: flex;
900
+ transform: none;
901
+ visibility: visible;
902
+ width: 320px;
903
+ box-shadow: 1px 0 0 rgba(171,171,171,.55);
904
+ border-right: 0;
905
+ }
906
+ .drawer-mask { display: none !important; }
907
+ .drawer-toggle, .drawer-close { display: none; }
908
+ .drawer-head { grid-template-columns: minmax(0, 1fr) auto auto; }
909
+ body.has-drawer { padding-left: 320px; }
910
+ }
911
+
912
+ /* The hamburger belongs to the drawer mode only, so the shipped console keeps its
913
+ existing two-rail layout until 方案 A is approved. */
914
+ @media (max-width: 780px) {
915
+ .agent-drawer { width: min(90vw, 400px); }
916
+ }
917
+ @media (min-width: 781px) {
918
+ .drawer-mask { display: none; }
919
+ }
920
+
921
+ /* ---------- 新建会话底部抽屉 ---------- */
922
+ .drawer-create { width: 34px; height: 34px; min-height: 34px; padding: 0; }
923
+ .drawer-head { grid-template-columns: auto minmax(0, 1fr) auto auto; gap: 8px; }
924
+ .create-mask { position: fixed; inset: 0; z-index: 42; background: rgba(24,28,34,.36); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
925
+ .create-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 43; max-height: 82dvh; overflow-y: auto; padding: 16px 16px calc(18px + env(safe-area-inset-bottom)); border-radius: 24px 24px 0 0; background: var(--glass-bg-strong); -webkit-backdrop-filter: blur(20px) saturate(140%); backdrop-filter: blur(20px) saturate(140%); border-top: 1.92px solid rgba(171,171,171,.8); box-shadow: 0 -18px 48px rgba(20,24,30,.24); transform: translateY(102%); transition: transform .24s cubic-bezier(.22,.68,.24,1); visibility: hidden; }
926
+ .create-sheet.open { transform: none; visibility: visible; }
927
+ @media (prefers-reduced-motion: reduce) { .create-sheet { transition: none; } }
928
+ .create-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: start; margin-bottom: 12px; }
929
+ .create-head h2 { margin: 0; font-size: 18px; font-style: italic; font-weight: 800; color: var(--ink); }
930
+ .create-head p { margin: 4px 0 0; font-size: 12px; color: var(--ink-3); }
931
+ .create-form { display: grid; gap: 10px; }
932
+ .create-form label { display: grid; gap: 6px; font-size: 11px; font-weight: 800; letter-spacing: .06em; color: var(--ink-3); text-transform: uppercase; }
933
+ .create-form select, .create-form input { height: 44px; border-radius: 14px; border: 1.4px solid rgba(171,171,171,.8); background: rgba(255,255,255,.6); color: var(--ink); font-size: 13.5px; padding: 0 12px; text-transform: none; letter-spacing: 0; font-weight: 600; }
934
+ .create-form .primary-button { width: 100%; justify-content: center; margin-top: 2px; }
935
+
936
+ /* 加载更早:位于日志之上,翻页不会把它挤走 */
937
+ /* align-items 必须写:flex 默认 stretch,会把按钮拉成和整行一样高(100px 圆角就成了
938
+ 巨型胶囊)。这一行只该有一行按钮那么高。 */
939
+ .history-more { display: flex; justify-content: center; align-items: center; min-height: 0; padding: 4px 0 8px; }
940
+ .history-more .secondary-button { min-height: 36px; font-size: 12px; }
941
+
942
+ /* 快捷导航(置顶 ⇧ / 置底 ⇩):悬浮在视口右侧,滚动到对应端时自动淡出。
943
+ 与 .icon-button 共用一套玻璃配方(Rim 高光 + 拟态阴影 + glass-blur),
944
+ 圆角 14px 与抽屉行一致,按钮 44px 满足触控热区。两个按钮叠成一列,靠右侧
945
+ 留出安全边距,垂直居中在视口,避免被 composer 的 sticky 底栏挡住。 */
946
+ .quick-nav {
947
+ position: fixed;
948
+ right: max(12px, calc(env(safe-area-inset-right) + 12px));
949
+ top: 50%;
950
+ transform: translateY(-50%);
951
+ z-index: 15;
952
+ display: grid;
953
+ gap: 8px;
954
+ padding: 6px;
955
+ border-radius: 20px;
956
+ background: var(--glass-bg-strong);
957
+ -webkit-backdrop-filter: var(--glass-blur);
958
+ backdrop-filter: var(--glass-blur);
959
+ border: 1.92px solid rgba(171, 171, 171, .8);
960
+ box-shadow: var(--panel-shadow);
961
+ }
962
+ .quick-nav[hidden] { display: none; }
963
+ .quick-nav-btn {
964
+ position: relative;
965
+ isolation: isolate;
966
+ width: 44px;
967
+ min-height: 44px;
968
+ padding: 0;
969
+ border: 1.92px solid rgba(177, 175, 175, 1);
970
+ border-radius: 14px;
971
+ background: linear-gradient(132deg, rgba(255, 255, 255, 0.48), rgba(0, 119, 179, 0.41));
972
+ -webkit-backdrop-filter: var(--glass-blur);
973
+ backdrop-filter: var(--glass-blur);
974
+ box-shadow: var(--icon-btn-shadow);
975
+ color: var(--ink);
976
+ display: grid;
977
+ place-items: center;
978
+ transition: transform .15s ease, filter .15s ease, opacity .2s ease;
979
+ overflow: hidden;
980
+ }
981
+ .quick-nav-btn svg { width: 20px; height: 20px; position: relative; z-index: 2; }
982
+ .quick-nav-btn::before {
983
+ content: "";
984
+ position: absolute;
985
+ inset: 0;
986
+ border-radius: inherit;
987
+ pointer-events: none;
988
+ z-index: 5;
989
+ box-shadow:
990
+ inset 0 1px 0 rgba(255,255,255,1.00),
991
+ inset 0 -1px 0 rgba(0,0,0, 0.45),
992
+ inset 1px 0 0 rgba(255,255,255,0.36),
993
+ inset -1px 0 0 rgba(0,0,0, 0.24);
994
+ }
995
+ .quick-nav-btn:hover { transform: translateY(-2px) scale(1.06); filter: brightness(1.05); }
996
+ .quick-nav-btn:active { transform: scale(0.94); box-shadow: var(--btn-press-shadow); }
997
+ /* 到端点只是提示:调低不透明度但**不拦点击**——"始终可点"是这个组件的契约,
998
+ 而且内容随时会因为新消息变长,做成死键反而更让人困惑。 */
999
+ .quick-nav-btn.is-idle { opacity: .55; }
1000
+
1001
+ /* 代码着色:深色卡片上的四种记号,保持对比度 */
1002
+ .md-code .tok-comment { color: #8d9682; font-style: italic; }
1003
+ .md-code .tok-string { color: #b8e08c; }
1004
+ .md-code .tok-number { color: #f0b978; }
1005
+ .md-code .tok-keyword { color: #86c5ff; font-weight: 700; }
1006
+ /* 抽屉里的"在所有会话中搜索"结果 */
1007
+ .drawer-deep { display: grid; gap: 6px; margin: 8px 0 0; padding: 10px 2px 4px; border-top: 1px solid var(--line); }
1008
+ .drawer-deep[hidden] { display: none; }
1009
+ .drawer-deep-head, .drawer-deep-status { margin: 0 8px 4px; color: var(--ink-3); font-size: 11px; font-weight: 800; font-style: italic; letter-spacing: .06em; }
1010
+ .drawer-deep-hit { display: grid; gap: 3px; width: 100%; min-height: 46px; padding: 8px 10px; border: 0; border-radius: 14px; background: transparent; color: var(--ink); text-align: left; }
1011
+ .drawer-deep-hit:hover { background: rgba(255,255,255,.38); }
1012
+ .drawer-deep-hit:active { transform: scale(.99); }
1013
+ .drawer-deep-title { display: flex; align-items: baseline; gap: 8px; color: var(--ink); font-size: 13px; font-weight: 750; font-style: italic; }
1014
+ .drawer-deep-title em { color: var(--ink-3); font-size: 10px; font-weight: 700; font-style: normal; }
1015
+ .drawer-deep-snippet { color: var(--ink-2); font-size: 12px; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
1016
+ /* 附件:输入框上方的待发列表 + 对话里的缩略图 */
1017
+ .composer-row { display: flex; align-items: flex-end; gap: 8px; }
1018
+ .composer-row textarea { flex: 1; min-width: 0; }
1019
+ .attach-input { position: absolute; width: 1px; height: 1px; padding: 0; border: 0; opacity: 0; pointer-events: none; }.attach-button { flex: none; width: 40px; height: 40px; min-height: 40px; padding: 0; display: grid; place-items: center; border-radius: 100px; border: 1.6px solid rgba(171,171,171,.8); background: var(--glass-bg); box-shadow: var(--mini-shadow); color: var(--ink-2); }
1020
+ .attach-button svg { width: 18px; height: 18px; }
1021
+ .attach-button:disabled { opacity: .5; }
1022
+ .composer-attachments { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 2px 8px; }
1023
+ .composer-attachments[hidden] { display: none; }
1024
+ .attachment-chip { display: inline-flex; align-items: center; gap: 8px; max-width: 240px; padding: 5px 8px; border-radius: 100px; background: rgba(255,255,255,.58); border: 1px solid rgba(255,255,255,.7); box-shadow: var(--mini-shadow); }
1025
+ .attachment-chip img { width: 26px; height: 26px; border-radius: 8px; object-fit: cover; }
1026
+ .attachment-chip-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 700; color: var(--ink-2); }
1027
+ .attachment-chip-remove { min-height: 0; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 100px; background: rgba(0,0,0,.12); color: var(--ink); font-size: 13px; line-height: 1; }
1028
+ .message-attachments { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
1029
+ .attachment-thumb { display: grid; gap: 4px; max-width: 168px; text-decoration: none; }
1030
+ .attachment-thumb img { width: 168px; height: 112px; object-fit: cover; border-radius: 12px; border: 1px solid rgba(255,255,255,.7); box-shadow: var(--mini-shadow); }
1031
+ .attachment-caption { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; font-weight: 700; color: #2b3038; }
1032
+ .attachment-file { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 100px; background: rgba(255,255,255,.55); border: 1px solid rgba(255,255,255,.7); box-shadow: var(--mini-shadow); color: #14141c; font-size: 12px; font-weight: 700; text-decoration: none; }
1033
+ /* 排队中的消息 */
1034
+ .composer-queue { display: grid; gap: 6px; padding: 0 2px 8px; }
1035
+ .composer-queue[hidden] { display: none; }
1036
+ .queue-item { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 12px; background: rgba(255,255,255,.5); border: 1px solid rgba(255,255,255,.66); }
1037
+ .queue-item span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: #2b3038; }
1038
+ .queue-item button { flex: none; min-height: 0; padding: 2px 8px; border-radius: 100px; border: 0; background: rgba(0,0,0,.1); font-size: 11px; font-weight: 700; color: #14141c; }
1039
+ .voice-button[aria-pressed="true"] { background: rgba(0,170,140,.22); border-color: rgba(0,170,140,.6); color: #0b3b32; }
1040
+ /* 工具输出:可折叠 + 可复制 */
1041
+ .tool-copy { margin: 0 0 6px; min-height: 26px; padding: 0 10px; border-radius: 100px; border: 1px solid rgba(171,171,171,.7); background: rgba(255,255,255,.6); font-size: 11px; font-weight: 700; color: #2b3038; }
1042
+ .tool-output { margin: 0; }
1043
+ .tool-output summary { cursor: pointer; font-size: 12px; font-weight: 700; color: #0d3049; }
1044
+ .tool-output pre { margin: 6px 0 0; padding: 10px 12px; border-radius: 12px; background: rgba(255,255,255,.5); font-size: 12px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; max-height: 340px; overflow: auto; }
1045
+ .usage-line { margin: 4px 0 0; color: #16191f; font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
1046
+ .usage-line[hidden] { display: none; }
1047
+ /* 抽屉"卡片"区块:与弹层 / 底部面板同一套材质(玻璃底 + blur + 1.92px 灰边 + panel-shadow) */
1048
+ .drawer-card {
1049
+ display: flex;
1050
+ align-items: center;
1051
+ justify-content: space-between;
1052
+ gap: 12px;
1053
+ margin: 6px 0 10px;
1054
+ padding: 12px 14px;
1055
+ border-radius: 20px;
1056
+ background: var(--glass-bg-strong);
1057
+ -webkit-backdrop-filter: blur(20px) saturate(140%);
1058
+ backdrop-filter: blur(20px) saturate(140%);
1059
+ border: 1.92px solid rgba(171, 171, 171, .8);
1060
+ box-shadow: var(--panel-shadow);
1061
+ }
1062
+ .drawer-card[hidden] { display: none; }
1063
+ .drawer-card-body { display: grid; gap: 2px; min-width: 0; }
1064
+ .drawer-card-title { font-size: 12px; font-weight: 800; font-style: italic; color: var(--ink); }
1065
+ .drawer-card-note { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--ink-2); }
1066
+ /* 开关本身就是一个 secondary-button:高度、背景、内描边、阴影全部继承,
1067
+ 只在按下(静音中)时多加一层琥珀提示。 */
1068
+ .notify-switch { flex: none; padding: 0 14px; }
1069
+ .notify-switch[aria-pressed="true"] {
1070
+ background: linear-gradient(0deg, rgba(220, 150, 0, .22), rgba(220, 150, 0, .22)), rgba(255, 255, 255, .5);
1071
+ color: #3b2a00;
1072
+ }
1073
+ .notify-switch[hidden] { display: none; }