akhaliq HF Staff Claude commited on
Commit
59ea233
·
1 Parent(s): c17d477

Modernize chat UI (Claude-style) and fix smushed logo

Browse files

- Warm canvas + centered narrow conversation column; assistant turns
render as plain text (no bubble), user turns as soft pills.
- Floating centered composer pill with gradient fade so messages scroll
under it; up-arrow send icon.
- Fix the Tencent/Hy3 wordmark being squashed into a square: size the
logo by height with natural aspect ratio (object-fit: contain), in
both the header and the empty-state hero.
- Refined sidebar (lighter fields, hairline accordion), slim scrollbars,
softer shadows, larger rounded radii, warmer dark theme.
- Collapse the sidebar by default; the header toggle opens/closes it on
both desktop and mobile via a single sidebar-closed class.

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (1) hide show
  1. static/index.html +207 -148
static/index.html CHANGED
@@ -36,45 +36,56 @@
36
  --tc-red: #E53935;
37
  --tc-teal: #00A98F;
38
 
39
- --bg: #ffffff;
40
- --bg-soft: #f7f9fc;
41
- --bg-muted: #f0f3f9;
 
42
  --sidebar-bg: #ffffff;
43
- --text: #1d2129;
44
- --text-strong: #0f1115;
45
- --text-muted: #6b7785;
46
- --border: #e5e8ee;
47
- --border-strong: #d3d8e0;
48
- --shadow-sm: 0 1px 3px rgba(15, 17, 21, 0.06);
49
- --shadow-md: 0 4px 16px rgba(15, 17, 21, 0.08);
50
- --shadow-lg: 0 12px 40px rgba(15, 17, 21, 0.16);
 
 
 
51
 
52
  --radius-sm: 8px;
53
- --radius: 12px;
54
- --radius-lg: 18px;
 
55
 
56
- --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text",
57
- "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
58
- "Helvetica Neue", Helvetica, Arial, sans-serif;
 
 
59
  --font-mono: "SF Mono", "JetBrains Mono", "Fira Code", Consolas, Monaco, monospace;
60
  }
61
 
62
  html.dark {
63
- --bg: #0f1115;
64
- --bg-soft: #161a21;
65
- --bg-muted: #1c2129;
66
- --sidebar-bg: #131820;
67
- --text: #dfe3ea;
 
68
  --text-strong: #ffffff;
69
- --text-muted: #8b95a3;
70
- --border: #2a313b;
71
- --border-strong: #3a434f;
 
 
72
  --tc-blue-soft: rgba(0, 82, 217, 0.16);
73
  --tc-blue-060: rgba(0, 82, 217, 0.12);
74
- --tc-blue-120: rgba(0, 82, 217, 0.22);
75
- --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
76
- --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.5);
77
- --shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.6);
 
78
  }
79
 
80
  * { box-sizing: border-box; }
@@ -86,51 +97,60 @@ html, body {
86
  }
87
  button, input, textarea, select { font-family: inherit; }
88
 
89
- /* ── Layout shell ─────────────────────────────────────────────────────── */
 
 
 
 
90
  #app {
91
  display: grid;
92
- grid-template-columns: 320px 1fr;
93
- grid-template-rows: 56px 1fr 84px;
94
  grid-template-areas:
95
  "header header"
96
- "sidebar main"
97
- "sidebar composer";
98
  height: 100vh; width: 100vw;
99
  }
100
  #app.sidebar-closed { grid-template-columns: 0 1fr; }
101
  #app.sidebar-closed #sidebar { transform: translateX(-100%); }
102
 
103
- /* ── Header / brand bar ──────────────────────────────────────────────── */
 
 
104
  #header {
105
  grid-area: header;
106
  display: flex; align-items: center; gap: 12px;
107
- padding: 0 18px;
108
- background: var(--bg);
109
  border-bottom: 1px solid var(--border);
110
  position: relative; z-index: 20;
111
  }
112
- .brand { display: flex; align-items: center; gap: 10px; cursor: default; }
 
 
 
113
  .brand-logo {
114
- width: 30px; height: 30px; border-radius: 7px;
115
  object-fit: contain;
116
- background: var(--bg-muted);
 
117
  }
118
- .brand-name { font-size: 17px; font-weight: 700; color: var(--text-strong); letter-spacing: -0.01em; }
119
  .brand-sep { color: var(--border-strong); font-weight: 300; }
120
  .brand-tag { font-size: 13px; color: var(--text-muted); font-weight: 500; }
121
  .brand-badge {
122
- margin-left: 6px; font-size: 11px; font-weight: 600;
123
  color: var(--tc-blue); background: var(--tc-blue-soft);
124
- padding: 2px 8px; border-radius: 999px; letter-spacing: 0.02em;
125
  }
126
  .header-spacer { flex: 1; }
127
  .icon-btn {
128
- width: 36px; height: 36px; border-radius: 8px;
129
- border: 1px solid var(--border); background: var(--bg); color: var(--text-muted);
130
  display: inline-flex; align-items: center; justify-content: center;
131
- cursor: pointer; transition: all 0.15s ease; padding: 0;
132
  }
133
- .icon-btn:hover { background: var(--bg-muted); color: var(--text); border-color: var(--border-strong); }
134
  .icon-btn svg { width: 18px; height: 18px; }
135
 
136
  /* ── Sidebar ──────────────────────────────────────────────────────────── */
@@ -140,47 +160,47 @@ button, input, textarea, select { font-family: inherit; }
140
  border-right: 1px solid var(--border);
141
  overflow-y: auto; overflow-x: hidden;
142
  transition: transform 0.22s ease;
143
- padding: 14px 16px 24px;
144
- display: flex; flex-direction: column; gap: 14px;
145
  }
146
  .sidebar-notice {
147
- font-size: 12px; line-height: 1.5; color: var(--text-muted);
148
- background: var(--tc-blue-060); border: 1px solid var(--tc-blue-120);
149
- border-radius: var(--radius-sm); padding: 10px 12px;
150
  }
151
- .field { display: flex; flex-direction: column; gap: 6px; }
152
  .field > label {
153
- font-size: 12px; font-weight: 600; color: var(--text);
 
154
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
155
  }
156
  .field .info {
157
  font-size: 11px; font-weight: 400; color: var(--text-muted);
158
- margin-top: -2px; line-height: 1.4;
159
  }
160
  .field input[type="text"], .field textarea, .field select {
161
  width: 100%; padding: 9px 12px;
162
  border: 1px solid var(--border); border-radius: var(--radius-sm);
163
- background: var(--bg); color: var(--text); font-size: 14px;
164
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
165
  }
166
  .field textarea { resize: vertical; min-height: 64px; font-family: inherit; line-height: 1.5; }
167
  .field input:focus, .field textarea:focus, .field select:focus {
168
- outline: none; border-color: var(--tc-blue);
169
- box-shadow: 0 0 0 3px var(--tc-blue-120);
170
  }
171
  .field select { appearance: none; cursor: pointer;
172
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7785' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
173
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 32px;
174
  }
175
  .range-row { display: flex; align-items: center; gap: 10px; }
176
  .range-row input[type="range"] { flex: 1; accent-color: var(--tc-blue); }
177
  .range-num {
178
  width: 58px; padding: 5px 8px; text-align: center;
179
- border: 1px solid var(--border); border-radius: 6px;
180
- background: var(--bg); color: var(--text); font-size: 12px;
181
  font-variant-numeric: tabular-nums;
182
  }
183
- .range-num:focus { outline: none; border-color: var(--tc-blue); box-shadow: 0 0 0 3px var(--tc-blue-120); }
184
  .range-row input[type="range"] { -webkit-appearance: none; appearance: none; height: 4px; background: var(--border); border-radius: 2px; }
185
  .range-row input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--tc-blue); cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
186
  .range-row input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border: none; border-radius: 50%; background: var(--tc-blue); cursor: pointer; }
@@ -190,21 +210,20 @@ button, input, textarea, select { font-family: inherit; }
190
  }
191
  .check-row input { accent-color: var(--tc-blue); width: 14px; height: 14px; }
192
 
193
- .accordion { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
194
  .accordion > summary {
195
- list-style: none; cursor: pointer; padding: 10px 12px;
196
  font-size: 13px; font-weight: 600; color: var(--text);
197
  display: flex; align-items: center; justify-content: space-between;
198
- background: var(--bg-soft);
199
  }
200
  .accordion > summary::-webkit-details-marker { display: none; }
201
  .accordion > summary::after { content: "⌄"; color: var(--text-muted); transition: transform 0.15s ease; }
202
  .accordion[open] > summary::after { transform: rotate(180deg); }
203
- .accordion > .accordion-body { padding: 12px; display: flex; flex-direction: column; gap: 10px; }
204
  .accordion textarea { width: 100%; min-height: 180px; font-family: var(--font-mono); font-size: 12px; line-height: 1.5; resize: vertical; }
205
  .tiny-btn {
206
- align-self: flex-start; padding: 6px 14px; font-size: 12px; font-weight: 500;
207
- border: 1px solid var(--border); border-radius: 6px; background: var(--bg);
208
  color: var(--text); cursor: pointer; transition: all 0.15s ease;
209
  }
210
  .tiny-btn:hover { border-color: var(--tc-blue); color: var(--tc-blue); background: var(--tc-blue-060); }
@@ -212,52 +231,61 @@ button, input, textarea, select { font-family: inherit; }
212
  .fn-msg.ok { color: var(--tc-teal); }
213
  .fn-msg.err { color: var(--tc-red); }
214
 
215
- /* ── Main chat surface ────────────────────────────────────────────────── */
 
 
 
 
216
  #main {
217
  grid-area: main; position: relative; background: var(--bg);
218
  overflow: hidden; display: flex; flex-direction: column;
219
  }
220
  #chat {
221
  flex: 1; overflow-y: auto; overflow-x: hidden;
222
- padding: 24px clamp(16px, 5vw, 64px) 32px;
223
  scroll-behavior: auto;
224
  }
225
- .message-row { display: block; width: 100%; margin: 0 0 4px; }
226
- .message-row.user-row { display: flex; justify-content: flex-end; margin: 14px 0 8px; }
227
- .message-row.bot-row { margin: 0 0 22px; }
228
- .message { max-width: 95%; }
 
 
 
229
  .message.user {
230
- background: var(--tc-blue); color: #fff;
231
- border-radius: var(--radius-lg); padding: 10px 18px;
232
- max-width: min(720px, 78%); box-shadow: var(--shadow-sm);
 
 
233
  }
234
- .message.user .hy-user-text { font-size: 15px; line-height: 1.7; white-space: pre-wrap; word-break: break-word; }
235
- .message.bot { background: transparent; padding: 2px 0; max-width: 100%; }
236
- .message.bot .markdown { font-size: 15px; line-height: 1.8; color: var(--text); letter-spacing: 0.01em; }
237
- .message.bot p { margin: 0.6em 0; }
238
  .message.bot p:first-child { margin-top: 0; }
239
  .message.bot p:last-child { margin-bottom: 0; }
240
- .message.bot strong, .message.bot b { font-weight: 600; color: var(--text-strong); }
241
- .message.bot ul, .message.bot ol { padding-left: 1.5em; margin: 0.5em 0; }
242
- .message.bot li { margin: 0.3em 0; line-height: 1.8; }
243
- .message.bot h1 { font-size: 22px; font-weight: 700; color: var(--text-strong); margin: 1em 0 0.5em; }
244
- .message.bot h2 { font-size: 19px; font-weight: 700; color: var(--text-strong); margin: 0.9em 0 0.4em; }
245
- .message.bot h3 { font-size: 17px; font-weight: 600; color: var(--text-strong); margin: 0.8em 0 0.35em; }
246
- .message.bot h4 { font-size: 15px; font-weight: 600; color: var(--text); margin: 0.7em 0 0.3em; }
247
- .message.bot a { color: var(--tc-blue); }
248
- .message.bot blockquote { border-left: 3px solid var(--border-strong); margin: 0.8em 0; padding: 4px 16px; color: var(--text-muted); }
249
- .message.bot hr { border: none; border-top: 1px solid var(--border); margin: 1.2em 0; }
250
- .message.bot table { display: block; width: max-content; max-width: 100%; overflow-x: auto; border-collapse: collapse; margin: 0.8em 0; font-size: 14px; }
251
  .message.bot th, .message.bot td { border: 1px solid var(--border); padding: 8px 14px; text-align: left; vertical-align: top; }
252
  .message.bot th { background: var(--bg-muted); font-weight: 600; }
253
- .message.bot code { font-family: var(--font-mono); font-size: 0.9em; }
254
- .message.bot :not(pre) > code { background: var(--bg-muted); padding: 2px 6px; border-radius: 4px; color: var(--text); }
255
- .hy-codeblock { margin: 0.9em 0; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--bg-soft); }
256
- .hy-codeblock-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 6px 8px 6px 14px; background: var(--bg-muted); border-bottom: 1px solid var(--border); font-size: 12px; line-height: 1; color: var(--text-muted); user-select: none; }
257
  .hy-codeblock-lang { text-transform: lowercase; letter-spacing: 0.02em; font-weight: 500; }
258
  .hy-codeblock-lang:empty::before { content: "text"; opacity: 0.7; }
259
- .hy-codeblock pre { margin: 0; border: none; border-radius: 0; background: transparent; padding: 12px 16px; overflow-x: auto; font-size: 13px; line-height: 1.6; }
260
- .code-copy-btn { flex-shrink: 0; width: 26px; height: 26px; padding: 0; display: inline-flex; align-items: center; justify-content: center; color: inherit; background: transparent; border: none; border-radius: 6px; cursor: pointer; transition: background 0.15s ease, color 0.15s ease; }
261
  .code-copy-btn svg { display: block; width: 14px; height: 14px; }
262
  .code-copy-btn:hover { background: var(--tc-blue-060); color: var(--tc-blue); }
263
  .code-copy-btn.copied, .code-copy-btn.copied:hover { color: var(--tc-teal); background: transparent; }
@@ -291,14 +319,14 @@ button, input, textarea, select { font-family: inherit; }
291
  #examples-overlay {
292
  position: absolute; inset: 0; z-index: 5;
293
  display: flex; align-items: center; justify-content: center;
294
- background: var(--bg); overflow-y: auto; padding: 40px 20px;
295
  transition: opacity 0.25s ease;
296
  }
297
  #examples-overlay.hidden { opacity: 0; pointer-events: none; }
298
  .examples-wrapper { display: flex; flex-direction: column; align-items: center; max-width: 1020px; }
299
- .examples-hero { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
300
- .examples-hero img { width: 52px; height: 52px; border-radius: 12px; }
301
- .examples-heading { font-size: 24px; font-weight: 700; color: var(--text-strong); margin: 0 0 26px; letter-spacing: -0.01em; text-align: center; }
302
  .examples-grid { display: grid; grid-template-columns: minmax(0, 460px) minmax(0, 460px); column-gap: 20px; row-gap: 14px; justify-content: center; width: min(1020px, 100%); }
303
  .example-btn:nth-child(1), .example-btn:nth-child(4) { grid-column: 1 / span 2; justify-self: center; }
304
  .example-btn:nth-child(2) { grid-column: 1; justify-self: end; }
@@ -306,12 +334,12 @@ button, input, textarea, select { font-family: inherit; }
306
  .example-btn {
307
  display: flex; align-items: center; justify-content: center;
308
  width: 460px; height: 72px; overflow: hidden;
309
- background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
310
  padding: 14px 20px; font-size: 14px; line-height: 1.5; color: var(--text);
311
  cursor: pointer; user-select: none; text-align: center;
312
- transition: transform 0.15s ease, border-color 0.2s ease, box-shadow 0.2s ease, color 0.2s ease;
313
  }
314
- .example-btn:hover { border-color: var(--tc-blue); color: var(--text-strong); box-shadow: var(--shadow-md); transform: translateY(-1px); }
315
  .example-btn-text { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; width: 100%; }
316
  @media (max-width: 1020px) {
317
  .examples-grid { grid-template-columns: minmax(0, 1fr); }
@@ -319,38 +347,59 @@ button, input, textarea, select { font-family: inherit; }
319
  .example-btn { width: 100%; max-width: 520px; }
320
  }
321
 
322
- /* ── Composer (input row) ─────────────────────────────────────────────── */
 
 
 
323
  #composer {
324
- grid-area: composer; display: flex; align-items: center; gap: 10px;
325
- padding: 12px clamp(16px, 5vw, 64px); background: var(--bg);
326
- border-top: 1px solid var(--border); z-index: 10;
 
 
 
327
  }
 
 
 
 
 
 
 
 
 
328
  #composer textarea {
329
- flex: 1; height: 56px; min-height: 56px; max-height: 56px;
330
  resize: none; overflow-y: auto;
331
- border: 1px solid var(--border); border-radius: 999px;
332
- padding: 16px 22px; font-size: 15px; line-height: 1.5; background: var(--bg);
333
- color: var(--text); box-shadow: var(--shadow-sm); transition: border-color 0.15s ease, box-shadow 0.15s ease;
334
  }
335
- #composer textarea:focus { outline: none; border-color: var(--tc-blue); box-shadow: 0 0 0 3px var(--tc-blue-120); }
336
- .round-btn {
337
- width: 46px; height: 46px; border-radius: 50%; padding: 0;
338
- display: flex; align-items: center; justify-content: center;
339
- flex-shrink: 0; cursor: pointer; border: none; transition: all 0.15s ease;
 
 
 
 
 
 
 
 
 
340
  }
341
- .round-btn svg { width: 20px; height: 20px; }
342
- #send-btn { background: var(--tc-blue); color: #fff; }
343
  #send-btn:hover { background: var(--tc-blue-hover); }
344
- #send-btn:disabled { background: var(--border-strong); color: #fff; cursor: not-allowed; opacity: 0.7; }
345
- #send-btn svg { width: 22px; height: 22px; }
346
- #new-chat-btn { background: var(--bg); color: var(--text-muted); border: 1px solid var(--border); }
347
- #new-chat-btn:hover { background: var(--bg-muted); color: var(--text); border-color: var(--border-strong); }
348
 
349
  /* ── Tool-call input panel ───────────────────────────────────────────── */
350
  #tool-area {
351
- position: absolute; bottom: 96px; left: 50%; transform: translateX(-50%);
352
  width: min(640px, 90%); z-index: 30;
353
- background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
354
  padding: 16px; box-shadow: var(--shadow-lg); display: none; flex-direction: column; gap: 10px;
355
  }
356
  #tool-area.visible { display: flex; }
@@ -387,25 +436,29 @@ button, input, textarea, select { font-family: inherit; }
387
  .toast.show { opacity: 1; }
388
  .toast.error { background: var(--tc-red); }
389
 
390
- /* ── Sidebar toggle on small screens ──────────────────────────────────── */
391
- #sidebar-toggle { display: none; }
 
 
 
392
  @media (max-width: 860px) {
393
- #app { grid-template-columns: 1fr; grid-template-areas: "header" "main" "composer"; }
394
  #sidebar {
395
- position: fixed; top: 56px; bottom: 0; left: 0; width: 86%; max-width: 360px;
396
  z-index: 50; box-shadow: var(--shadow-lg);
397
  }
398
- #app:not(.sidebar-open) #sidebar { transform: translateX(-100%); }
399
- #sidebar-toggle { display: inline-flex; }
400
- .examples-hero img { width: 44px; height: 44px; }
401
- .examples-heading { font-size: 20px; }
402
  }
403
 
404
- /* ── Scrollbars ───────────────────────────────────────────────────────── */
405
- ::-webkit-scrollbar { width: 9px; height: 9px; }
406
  ::-webkit-scrollbar-track { background: transparent; }
407
- ::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 5px; border: 2px solid transparent; background-clip: padding-box; }
408
  ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); background-clip: padding-box; }
 
409
 
410
  /* KaTeX: keep its own math fonts and reset inherited typography so SVG
411
  stretchy operators don't get distorted by the bubble's line-height. */
@@ -418,7 +471,7 @@ button, input, textarea, select { font-family: inherit; }
418
  </style>
419
  </head>
420
  <body>
421
- <div id="app">
422
  <!-- ── Header ────────────────────────────────────────────────────── -->
423
  <header id="header">
424
  <button id="sidebar-toggle" class="icon-btn" title="Menu" aria-label="Toggle sidebar">
@@ -523,15 +576,17 @@ button, input, textarea, select { font-family: inherit; }
523
  </div>
524
  </main>
525
 
526
- <!-- ── Composer ─────────────────────────────────────────────────── -->
527
  <div id="composer">
528
- <button id="new-chat-btn" class="round-btn" title="New chat" aria-label="New chat">
529
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
530
- </button>
531
- <textarea id="msg-input" rows="1" data-i18n-ph="msg_placeholder"></textarea>
532
- <button id="send-btn" class="round-btn" title="Send" aria-label="Send">
533
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z"/></svg>
534
- </button>
 
 
535
  </div>
536
  </div>
537
 
@@ -629,9 +684,13 @@ import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client@1.7.1/dist/i
629
  setTheme(!document.documentElement.classList.contains("dark"))
630
  );
631
 
632
- /* ─── sidebar toggle (mobile) ───────────────────────────────────── */
 
 
 
 
633
  $("sidebar-toggle").addEventListener("click", () => {
634
- $("app").classList.toggle("sidebar-open");
635
  });
636
 
637
  /* ─── markdown + math rendering ────────────────────────────────────
@@ -1152,7 +1211,7 @@ import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client@1.7.1/dist/i
1152
  });
1153
  msgInput.addEventListener("input", () => {
1154
  msgInput.style.height = "auto";
1155
- msgInput.style.height = Math.min(msgInput.scrollHeight, 140) + "px";
1156
  });
1157
 
1158
  /* ─── new chat ────────────────────────────────────────────────────── */
 
36
  --tc-red: #E53935;
37
  --tc-teal: #00A98F;
38
 
39
+ --bg: #f7f6f3; /* warm canvas, Claude-like */
40
+ --bg-soft: #ffffff; /* surfaces / bubbles / sidebar */
41
+ --bg-muted: #efece6;
42
+ --bg-elev: #ffffff;
43
  --sidebar-bg: #ffffff;
44
+ --text: #2b2b2b;
45
+ --text-strong: #1a1a1a;
46
+ --text-muted: #8a8580;
47
+ --border: #e7e3dc;
48
+ --border-strong: #d8d3cb;
49
+ --accent: #c96442; /* warm terracotta accent (Claude) */
50
+ --accent-soft: #f4ece7;
51
+ --shadow-sm: 0 1px 2px rgba(20, 18, 14, 0.04);
52
+ --shadow-md: 0 4px 14px rgba(20, 18, 14, 0.06);
53
+ --shadow-lg: 0 16px 48px rgba(20, 18, 14, 0.14);
54
+ --ring: 0 0 0 3px rgba(0, 82, 217, 0.16);
55
 
56
  --radius-sm: 8px;
57
+ --radius: 14px;
58
+ --radius-lg: 20px;
59
+ --radius-xl: 26px;
60
 
61
+ --col-max: 768px; /* centered conversation width */
62
+
63
+ --font-sans: "Söhne", "Inter", -apple-system, BlinkMacSystemFont,
64
+ "SF Pro Text", "PingFang SC", "Hiragino Sans GB",
65
+ "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
66
  --font-mono: "SF Mono", "JetBrains Mono", "Fira Code", Consolas, Monaco, monospace;
67
  }
68
 
69
  html.dark {
70
+ --bg: #1a1a1a; /* warm-tinted dark canvas */
71
+ --bg-soft: #232323;
72
+ --bg-muted: #2c2c2c;
73
+ --bg-elev: #232323;
74
+ --sidebar-bg: #202020;
75
+ --text: #ece9e4;
76
  --text-strong: #ffffff;
77
+ --text-muted: #9a948d;
78
+ --border: #34312d;
79
+ --border-strong: #423e39;
80
+ --accent: #d97757;
81
+ --accent-soft: rgba(217, 119, 87, 0.16);
82
  --tc-blue-soft: rgba(0, 82, 217, 0.16);
83
  --tc-blue-060: rgba(0, 82, 217, 0.12);
84
+ --tc-blue-120: rgba(0, 82, 217, 0.24);
85
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
86
+ --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.4);
87
+ --shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.6);
88
+ --ring: 0 0 0 3px rgba(0, 82, 217, 0.3);
89
  }
90
 
91
  * { box-sizing: border-box; }
 
97
  }
98
  button, input, textarea, select { font-family: inherit; }
99
 
100
+ /* ── Layout shell ───────────────────────────────────────────────────────
101
+ The chat surface (#main) IS the warm canvas and fills everything below
102
+ the header; the composer floats at the bottom of it, centered, so the
103
+ conversation scrolls underneath it (Claude-style) rather than living
104
+ in a separate hard-bordered bar. */
105
  #app {
106
  display: grid;
107
+ grid-template-columns: 300px 1fr;
108
+ grid-template-rows: 60px 1fr;
109
  grid-template-areas:
110
  "header header"
111
+ "sidebar main";
 
112
  height: 100vh; width: 100vw;
113
  }
114
  #app.sidebar-closed { grid-template-columns: 0 1fr; }
115
  #app.sidebar-closed #sidebar { transform: translateX(-100%); }
116
 
117
+ /* ── Header / brand bar ────────────────────────────────────────────────
118
+ Transparent over the canvas with only a hairline divider — feels like
119
+ part of the page, not a chrome bar. */
120
  #header {
121
  grid-area: header;
122
  display: flex; align-items: center; gap: 12px;
123
+ padding: 0 20px;
124
+ background: var(--bg-soft);
125
  border-bottom: 1px solid var(--border);
126
  position: relative; z-index: 20;
127
  }
128
+ .brand { display: flex; align-items: center; gap: 12px; cursor: default; }
129
+ /* The logo is a wide horizontal wordmark (Tencent + Hy3). Size it by
130
+ height and let width follow the natural aspect ratio so it never
131
+ gets smushed into a square. */
132
  .brand-logo {
133
+ height: 26px; width: auto;
134
  object-fit: contain;
135
+ display: block;
136
+ border-radius: 4px;
137
  }
138
+ .brand-name { font-size: 16px; font-weight: 650; color: var(--text-strong); letter-spacing: -0.01em; }
139
  .brand-sep { color: var(--border-strong); font-weight: 300; }
140
  .brand-tag { font-size: 13px; color: var(--text-muted); font-weight: 500; }
141
  .brand-badge {
142
+ margin-left: 4px; font-size: 11px; font-weight: 600;
143
  color: var(--tc-blue); background: var(--tc-blue-soft);
144
+ padding: 2px 9px; border-radius: 999px; letter-spacing: 0.02em;
145
  }
146
  .header-spacer { flex: 1; }
147
  .icon-btn {
148
+ width: 36px; height: 36px; border-radius: 9px;
149
+ border: 1px solid transparent; background: transparent; color: var(--text-muted);
150
  display: inline-flex; align-items: center; justify-content: center;
151
+ cursor: pointer; transition: background 0.15s ease, color 0.15s ease; padding: 0;
152
  }
153
+ .icon-btn:hover { background: var(--bg-muted); color: var(--text); }
154
  .icon-btn svg { width: 18px; height: 18px; }
155
 
156
  /* ── Sidebar ──────────────────────────────────────────────────────────── */
 
160
  border-right: 1px solid var(--border);
161
  overflow-y: auto; overflow-x: hidden;
162
  transition: transform 0.22s ease;
163
+ padding: 18px 18px 28px;
164
+ display: flex; flex-direction: column; gap: 16px;
165
  }
166
  .sidebar-notice {
167
+ font-size: 12px; line-height: 1.55; color: var(--text-muted);
168
+ background: var(--accent-soft); border: 1px solid transparent;
169
+ border-radius: var(--radius-sm); padding: 11px 13px;
170
  }
171
+ .field { display: flex; flex-direction: column; gap: 7px; }
172
  .field > label {
173
+ font-size: 11.5px; font-weight: 600; color: var(--text-muted);
174
+ text-transform: none; letter-spacing: 0.01em;
175
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
176
  }
177
  .field .info {
178
  font-size: 11px; font-weight: 400; color: var(--text-muted);
179
+ margin-top: -3px; line-height: 1.45; opacity: 0.85;
180
  }
181
  .field input[type="text"], .field textarea, .field select {
182
  width: 100%; padding: 9px 12px;
183
  border: 1px solid var(--border); border-radius: var(--radius-sm);
184
+ background: var(--bg-soft); color: var(--text); font-size: 14px;
185
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
186
  }
187
  .field textarea { resize: vertical; min-height: 64px; font-family: inherit; line-height: 1.5; }
188
  .field input:focus, .field textarea:focus, .field select:focus {
189
+ outline: none; border-color: var(--tc-blue); box-shadow: var(--ring);
 
190
  }
191
  .field select { appearance: none; cursor: pointer;
192
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238a8580' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
193
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 32px;
194
  }
195
  .range-row { display: flex; align-items: center; gap: 10px; }
196
  .range-row input[type="range"] { flex: 1; accent-color: var(--tc-blue); }
197
  .range-num {
198
  width: 58px; padding: 5px 8px; text-align: center;
199
+ border: 1px solid var(--border); border-radius: 7px;
200
+ background: var(--bg-soft); color: var(--text); font-size: 12px;
201
  font-variant-numeric: tabular-nums;
202
  }
203
+ .range-num:focus { outline: none; border-color: var(--tc-blue); box-shadow: var(--ring); }
204
  .range-row input[type="range"] { -webkit-appearance: none; appearance: none; height: 4px; background: var(--border); border-radius: 2px; }
205
  .range-row input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--tc-blue); cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
206
  .range-row input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border: none; border-radius: 50%; background: var(--tc-blue); cursor: pointer; }
 
210
  }
211
  .check-row input { accent-color: var(--tc-blue); width: 14px; height: 14px; }
212
 
213
+ .accordion { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; background: var(--bg-soft); }
214
  .accordion > summary {
215
+ list-style: none; cursor: pointer; padding: 11px 13px;
216
  font-size: 13px; font-weight: 600; color: var(--text);
217
  display: flex; align-items: center; justify-content: space-between;
 
218
  }
219
  .accordion > summary::-webkit-details-marker { display: none; }
220
  .accordion > summary::after { content: "⌄"; color: var(--text-muted); transition: transform 0.15s ease; }
221
  .accordion[open] > summary::after { transform: rotate(180deg); }
222
+ .accordion > .accordion-body { padding: 13px; display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--border); }
223
  .accordion textarea { width: 100%; min-height: 180px; font-family: var(--font-mono); font-size: 12px; line-height: 1.5; resize: vertical; }
224
  .tiny-btn {
225
+ align-self: flex-start; padding: 7px 15px; font-size: 12px; font-weight: 500;
226
+ border: 1px solid var(--border); border-radius: 8px; background: var(--bg-soft);
227
  color: var(--text); cursor: pointer; transition: all 0.15s ease;
228
  }
229
  .tiny-btn:hover { border-color: var(--tc-blue); color: var(--tc-blue); background: var(--tc-blue-060); }
 
231
  .fn-msg.ok { color: var(--tc-teal); }
232
  .fn-msg.err { color: var(--tc-red); }
233
 
234
+ /* ── Main chat surface ──────────────────────────────────────────────────
235
+ The warm canvas. Conversation is centered in a narrow column with
236
+ generous vertical rhythm; assistant turns are plain text (no bubble),
237
+ user turns are soft pills. The composer floats at the bottom on a
238
+ gradient fade so messages scroll under it gracefully. */
239
  #main {
240
  grid-area: main; position: relative; background: var(--bg);
241
  overflow: hidden; display: flex; flex-direction: column;
242
  }
243
  #chat {
244
  flex: 1; overflow-y: auto; overflow-x: hidden;
245
+ padding: 28px clamp(16px, 5vw, 48px) 220px; /* bottom room for floating composer */
246
  scroll-behavior: auto;
247
  }
248
+ /* Center the conversation in a narrow column. */
249
+ #chat > .col,
250
+ #chat > .message-row { max-width: var(--col-max); margin-left: auto; margin-right: auto; width: 100%; }
251
+ .message-row { display: block; width: 100%; margin: 0; }
252
+ .message-row.user-row { display: flex; justify-content: flex-end; margin: 22px 0 4px; }
253
+ .message-row.bot-row { margin: 0 0 30px; }
254
+ .message { max-width: 100%; }
255
  .message.user {
256
+ background: var(--bg-elev); color: var(--text-strong);
257
+ border: 1px solid var(--border);
258
+ border-radius: var(--radius-lg); padding: 11px 18px;
259
+ max-width: min(560px, 82%); box-shadow: var(--shadow-sm);
260
+ font-weight: 450;
261
  }
262
+ .message.user .hy-user-text { font-size: 15px; line-height: 1.65; white-space: pre-wrap; word-break: break-word; }
263
+ .message.bot { background: transparent; padding: 0; max-width: 100%; }
264
+ .message.bot .markdown { font-size: 16px; line-height: 1.7; color: var(--text); letter-spacing: 0.005em; }
265
+ .message.bot p { margin: 0.85em 0; }
266
  .message.bot p:first-child { margin-top: 0; }
267
  .message.bot p:last-child { margin-bottom: 0; }
268
+ .message.bot strong, .message.bot b { font-weight: 650; color: var(--text-strong); }
269
+ .message.bot ul, .message.bot ol { padding-left: 1.5em; margin: 0.6em 0; }
270
+ .message.bot li { margin: 0.35em 0; line-height: 1.7; }
271
+ .message.bot h1 { font-size: 23px; font-weight: 700; color: var(--text-strong); margin: 1.1em 0 0.5em; letter-spacing: -0.01em; }
272
+ .message.bot h2 { font-size: 20px; font-weight: 700; color: var(--text-strong); margin: 1em 0 0.45em; letter-spacing: -0.01em; }
273
+ .message.bot h3 { font-size: 17px; font-weight: 650; color: var(--text-strong); margin: 0.9em 0 0.4em; }
274
+ .message.bot h4 { font-size: 15px; font-weight: 650; color: var(--text); margin: 0.8em 0 0.35em; }
275
+ .message.bot a { color: var(--tc-blue); text-underline-offset: 2px; }
276
+ .message.bot blockquote { border-left: 3px solid var(--border-strong); margin: 0.9em 0; padding: 2px 16px; color: var(--text-muted); }
277
+ .message.bot hr { border: none; border-top: 1px solid var(--border); margin: 1.4em 0; }
278
+ .message.bot table { display: block; width: max-content; max-width: 100%; overflow-x: auto; border-collapse: collapse; margin: 0.9em 0; font-size: 14px; }
279
  .message.bot th, .message.bot td { border: 1px solid var(--border); padding: 8px 14px; text-align: left; vertical-align: top; }
280
  .message.bot th { background: var(--bg-muted); font-weight: 600; }
281
+ .message.bot code { font-family: var(--font-mono); font-size: 0.88em; }
282
+ .message.bot :not(pre) > code { background: var(--bg-muted); padding: 2px 6px; border-radius: 5px; color: var(--text); }
283
+ .hy-codeblock { margin: 1em 0; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; background: var(--bg-soft); }
284
+ .hy-codeblock-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 9px 7px 15px; background: var(--bg-muted); border-bottom: 1px solid var(--border); font-size: 12px; line-height: 1; color: var(--text-muted); user-select: none; }
285
  .hy-codeblock-lang { text-transform: lowercase; letter-spacing: 0.02em; font-weight: 500; }
286
  .hy-codeblock-lang:empty::before { content: "text"; opacity: 0.7; }
287
+ .hy-codeblock pre { margin: 0; border: none; border-radius: 0; background: transparent; padding: 13px 16px; overflow-x: auto; font-size: 13px; line-height: 1.65; }
288
+ .code-copy-btn { flex-shrink: 0; width: 26px; height: 26px; padding: 0; display: inline-flex; align-items: center; justify-content: center; color: inherit; background: transparent; border: none; border-radius: 7px; cursor: pointer; transition: background 0.15s ease, color 0.15s ease; }
289
  .code-copy-btn svg { display: block; width: 14px; height: 14px; }
290
  .code-copy-btn:hover { background: var(--tc-blue-060); color: var(--tc-blue); }
291
  .code-copy-btn.copied, .code-copy-btn.copied:hover { color: var(--tc-teal); background: transparent; }
 
319
  #examples-overlay {
320
  position: absolute; inset: 0; z-index: 5;
321
  display: flex; align-items: center; justify-content: center;
322
+ background: var(--bg); overflow-y: auto; padding: 40px 20px 160px;
323
  transition: opacity 0.25s ease;
324
  }
325
  #examples-overlay.hidden { opacity: 0; pointer-events: none; }
326
  .examples-wrapper { display: flex; flex-direction: column; align-items: center; max-width: 1020px; }
327
+ .examples-hero { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 22px; }
328
+ .examples-hero img { width: auto; height: 56px; border-radius: 8px; object-fit: contain; }
329
+ .examples-heading { font-size: 28px; font-weight: 650; color: var(--text-strong); margin: 0 0 30px; letter-spacing: -0.02em; text-align: center; }
330
  .examples-grid { display: grid; grid-template-columns: minmax(0, 460px) minmax(0, 460px); column-gap: 20px; row-gap: 14px; justify-content: center; width: min(1020px, 100%); }
331
  .example-btn:nth-child(1), .example-btn:nth-child(4) { grid-column: 1 / span 2; justify-self: center; }
332
  .example-btn:nth-child(2) { grid-column: 1; justify-self: end; }
 
334
  .example-btn {
335
  display: flex; align-items: center; justify-content: center;
336
  width: 460px; height: 72px; overflow: hidden;
337
+ background: var(--bg-soft); border: 1px solid var(--border); border-radius: var(--radius);
338
  padding: 14px 20px; font-size: 14px; line-height: 1.5; color: var(--text);
339
  cursor: pointer; user-select: none; text-align: center;
340
+ transition: transform 0.15s ease, border-color 0.2s ease, box-shadow 0.2s ease, color 0.2s ease, background 0.2s ease;
341
  }
342
+ .example-btn:hover { border-color: var(--border-strong); color: var(--text-strong); box-shadow: var(--shadow-md); transform: translateY(-1px); background: var(--bg-elev); }
343
  .example-btn-text { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; width: 100%; }
344
  @media (max-width: 1020px) {
345
  .examples-grid { grid-template-columns: minmax(0, 1fr); }
 
347
  .example-btn { width: 100%; max-width: 520px; }
348
  }
349
 
350
+ /* ── Composer (floating, centered pill) ────────────────────────────────
351
+ Sits at the bottom of the chat canvas, centered to the conversation
352
+ column, with a gradient fade above it so content scrolls under it
353
+ gracefully — the Claude.ai feel. */
354
  #composer {
355
+ position: absolute; left: 0; right: 0; bottom: 0;
356
+ display: flex; align-items: flex-end; justify-content: center; gap: 10px;
357
+ padding: 0 clamp(16px, 5vw, 48px) 20px;
358
+ z-index: 10;
359
+ background: linear-gradient(to top, var(--bg) 52%, rgba(247,246,243,0));
360
+ pointer-events: none; /* let the fade be click-through … */
361
  }
362
+ #composer > * { pointer-events: auto; } /* … but not the controls */
363
+ html.dark #composer { background: linear-gradient(to top, var(--bg) 52%, rgba(26,26,26,0)); }
364
+ .composer-inner {
365
+ display: flex; align-items: flex-end; gap: 8px; width: 100%; max-width: var(--col-max);
366
+ background: var(--bg-elev); border: 1px solid var(--border);
367
+ border-radius: var(--radius-xl); padding: 8px 8px 8px 18px;
368
+ box-shadow: var(--shadow-md); transition: border-color 0.15s ease, box-shadow 0.15s ease;
369
+ }
370
+ .composer-inner:focus-within { border-color: var(--border-strong); box-shadow: var(--shadow-md), var(--ring); }
371
  #composer textarea {
372
+ flex: 1; min-height: 44px; max-height: 200px;
373
  resize: none; overflow-y: auto;
374
+ border: none; border-radius: 0;
375
+ padding: 12px 0; font-size: 15.5px; line-height: 1.55; background: transparent;
376
+ color: var(--text); box-shadow: none; transition: none;
377
  }
378
+ #composer textarea:focus { outline: none; box-shadow: none; }
379
+ #new-chat-btn {
380
+ width: 40px; height: 40px; border-radius: 50%; padding: 0;
381
+ display: flex; align-items: center; justify-content: center; flex-shrink: 0;
382
+ cursor: pointer; border: 1px solid transparent; background: transparent; color: var(--text-muted);
383
+ transition: background 0.15s ease, color 0.15s ease;
384
+ }
385
+ #new-chat-btn:hover { background: var(--bg-muted); color: var(--text); }
386
+ #new-chat-btn svg { width: 19px; height: 19px; }
387
+ #send-btn {
388
+ width: 40px; height: 40px; border-radius: 50%; padding: 0;
389
+ display: flex; align-items: center; justify-content: center; flex-shrink: 0;
390
+ cursor: pointer; border: none; background: var(--tc-blue); color: #fff;
391
+ transition: background 0.15s ease, transform 0.1s ease;
392
  }
 
 
393
  #send-btn:hover { background: var(--tc-blue-hover); }
394
+ #send-btn:active { transform: scale(0.95); }
395
+ #send-btn:disabled { background: var(--border-strong); cursor: not-allowed; opacity: 0.6; }
396
+ #send-btn svg { width: 18px; height: 18px; }
 
397
 
398
  /* ── Tool-call input panel ───────────────────────────────────────────── */
399
  #tool-area {
400
+ position: absolute; bottom: 104px; left: 50%; transform: translateX(-50%);
401
  width: min(640px, 90%); z-index: 30;
402
+ background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius);
403
  padding: 16px; box-shadow: var(--shadow-lg); display: none; flex-direction: column; gap: 10px;
404
  }
405
  #tool-area.visible { display: flex; }
 
436
  .toast.show { opacity: 1; }
437
  .toast.error { background: var(--tc-red); }
438
 
439
+ /* ── Sidebar toggle ─────────────────────────────────────────────────────
440
+ One class (``#app.sidebar-closed``) drives collapse on every breakpoint:
441
+ desktop collapses the grid column to 0; mobile slides the fixed overlay
442
+ out. The header toggle is always visible so users can re-open it. */
443
+ #sidebar-toggle { display: inline-flex; }
444
  @media (max-width: 860px) {
445
+ #app { grid-template-columns: 1fr; grid-template-areas: "header" "main"; }
446
  #sidebar {
447
+ position: fixed; top: 60px; bottom: 0; left: 0; width: 86%; max-width: 360px;
448
  z-index: 50; box-shadow: var(--shadow-lg);
449
  }
450
+ /* On mobile the sidebar is an overlay; show it unless explicitly closed. */
451
+ #app.sidebar-closed #sidebar { transform: translateX(-100%); }
452
+ .examples-hero img { height: 46px; }
453
+ .examples-heading { font-size: 22px; }
454
  }
455
 
456
+ /* ── Scrollbars (slim & subtle) ─────────────────────────────────���────── */
457
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
458
  ::-webkit-scrollbar-track { background: transparent; }
459
+ ::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; border: 3px solid transparent; background-clip: padding-box; }
460
  ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); background-clip: padding-box; }
461
+ * { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
462
 
463
  /* KaTeX: keep its own math fonts and reset inherited typography so SVG
464
  stretchy operators don't get distorted by the bubble's line-height. */
 
471
  </style>
472
  </head>
473
  <body>
474
+ <div id="app" class="sidebar-closed">
475
  <!-- ── Header ────────────────────────────────────────────────────── -->
476
  <header id="header">
477
  <button id="sidebar-toggle" class="icon-btn" title="Menu" aria-label="Toggle sidebar">
 
576
  </div>
577
  </main>
578
 
579
+ <!-- ── Composer (floating pill) ─────────────────────────────────── -->
580
  <div id="composer">
581
+ <div class="composer-inner">
582
+ <button id="new-chat-btn" title="New chat" aria-label="New chat">
583
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
584
+ </button>
585
+ <textarea id="msg-input" rows="1" data-i18n-ph="msg_placeholder"></textarea>
586
+ <button id="send-btn" title="Send" aria-label="Send">
587
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
588
+ </button>
589
+ </div>
590
  </div>
591
  </div>
592
 
 
684
  setTheme(!document.documentElement.classList.contains("dark"))
685
  );
686
 
687
+ /* ─── sidebar toggle ───────────────────────────────────────────────
688
+ One class (``sidebar-closed``) drives collapse on every breakpoint;
689
+ the header button flips it, so the same control opens/closes the
690
+ sidebar on both desktop and mobile. It starts closed by default
691
+ (see the ``sidebar-closed`` class on #app). */
692
  $("sidebar-toggle").addEventListener("click", () => {
693
+ $("app").classList.toggle("sidebar-closed");
694
  });
695
 
696
  /* ─── markdown + math rendering ────────────────────────────────────
 
1211
  });
1212
  msgInput.addEventListener("input", () => {
1213
  msgInput.style.height = "auto";
1214
+ msgInput.style.height = Math.min(msgInput.scrollHeight, 200) + "px";
1215
  });
1216
 
1217
  /* ─── new chat ────────────────────────────────────────────────────── */