Spaces:
Running
Running
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>
- static/index.html +207 -148
static/index.html
CHANGED
|
@@ -36,45 +36,56 @@
|
|
| 36 |
--tc-red: #E53935;
|
| 37 |
--tc-teal: #00A98F;
|
| 38 |
|
| 39 |
-
--bg: #
|
| 40 |
-
--bg-soft: #
|
| 41 |
-
--bg-muted: #
|
|
|
|
| 42 |
--sidebar-bg: #ffffff;
|
| 43 |
-
--text: #
|
| 44 |
-
--text-strong: #
|
| 45 |
-
--text-muted: #
|
| 46 |
-
--border: #
|
| 47 |
-
--border-strong: #
|
| 48 |
-
--
|
| 49 |
-
--
|
| 50 |
-
--shadow-
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
--radius-sm: 8px;
|
| 53 |
-
--radius:
|
| 54 |
-
--radius-lg:
|
|
|
|
| 55 |
|
| 56 |
-
--
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
| 59 |
--font-mono: "SF Mono", "JetBrains Mono", "Fira Code", Consolas, Monaco, monospace;
|
| 60 |
}
|
| 61 |
|
| 62 |
html.dark {
|
| 63 |
-
--bg: #
|
| 64 |
-
--bg-soft: #
|
| 65 |
-
--bg-muted: #
|
| 66 |
-
--
|
| 67 |
-
--
|
|
|
|
| 68 |
--text-strong: #ffffff;
|
| 69 |
-
--text-muted: #
|
| 70 |
-
--border: #
|
| 71 |
-
--border-strong: #
|
|
|
|
|
|
|
| 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.
|
| 75 |
-
--shadow-sm: 0 1px
|
| 76 |
-
--shadow-md: 0 4px
|
| 77 |
-
--shadow-lg: 0
|
|
|
|
| 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:
|
| 93 |
-
grid-template-rows:
|
| 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
|
| 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:
|
|
|
|
|
|
|
|
|
|
| 113 |
.brand-logo {
|
| 114 |
-
|
| 115 |
object-fit: contain;
|
| 116 |
-
|
|
|
|
| 117 |
}
|
| 118 |
-
.brand-name { font-size:
|
| 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:
|
| 123 |
color: var(--tc-blue); background: var(--tc-blue-soft);
|
| 124 |
-
padding: 2px
|
| 125 |
}
|
| 126 |
.header-spacer { flex: 1; }
|
| 127 |
.icon-btn {
|
| 128 |
-
width: 36px; height: 36px; border-radius:
|
| 129 |
-
border: 1px solid
|
| 130 |
display: inline-flex; align-items: center; justify-content: center;
|
| 131 |
-
cursor: pointer; transition:
|
| 132 |
}
|
| 133 |
-
.icon-btn:hover { background: var(--bg-muted); color: var(--text);
|
| 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:
|
| 144 |
-
display: flex; flex-direction: column; gap:
|
| 145 |
}
|
| 146 |
.sidebar-notice {
|
| 147 |
-
font-size: 12px; line-height: 1.
|
| 148 |
-
background: var(--
|
| 149 |
-
border-radius: var(--radius-sm); padding:
|
| 150 |
}
|
| 151 |
-
.field { display: flex; flex-direction: column; gap:
|
| 152 |
.field > label {
|
| 153 |
-
font-size:
|
|
|
|
| 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: -
|
| 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='%
|
| 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:
|
| 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:
|
| 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:
|
| 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:
|
| 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:
|
| 207 |
-
border: 1px solid var(--border); border-radius:
|
| 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:
|
| 223 |
scroll-behavior: auto;
|
| 224 |
}
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
.message-row
|
| 228 |
-
.message {
|
|
|
|
|
|
|
|
|
|
| 229 |
.message.user {
|
| 230 |
-
background: var(--
|
| 231 |
-
border
|
| 232 |
-
|
|
|
|
|
|
|
| 233 |
}
|
| 234 |
-
.message.user .hy-user-text { font-size: 15px; line-height: 1.
|
| 235 |
-
.message.bot { background: transparent; padding:
|
| 236 |
-
.message.bot .markdown { font-size:
|
| 237 |
-
.message.bot p { margin: 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:
|
| 241 |
-
.message.bot ul, .message.bot ol { padding-left: 1.5em; margin: 0.
|
| 242 |
-
.message.bot li { margin: 0.
|
| 243 |
-
.message.bot h1 { font-size:
|
| 244 |
-
.message.bot h2 { font-size:
|
| 245 |
-
.message.bot h3 { font-size: 17px; font-weight:
|
| 246 |
-
.message.bot h4 { font-size: 15px; font-weight:
|
| 247 |
-
.message.bot a { color: var(--tc-blue); }
|
| 248 |
-
.message.bot blockquote { border-left: 3px solid var(--border-strong); margin: 0.
|
| 249 |
-
.message.bot hr { border: none; border-top: 1px solid var(--border); margin: 1.
|
| 250 |
-
.message.bot table { display: block; width: max-content; max-width: 100%; overflow-x: auto; border-collapse: collapse; margin: 0.
|
| 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.
|
| 254 |
-
.message.bot :not(pre) > code { background: var(--bg-muted); padding: 2px 6px; border-radius:
|
| 255 |
-
.hy-codeblock { margin:
|
| 256 |
-
.hy-codeblock-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding:
|
| 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:
|
| 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:
|
| 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:
|
| 300 |
-
.examples-hero img { width:
|
| 301 |
-
.examples-heading { font-size:
|
| 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(--
|
| 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 (
|
|
|
|
|
|
|
|
|
|
| 323 |
#composer {
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
|
|
|
|
|
|
|
|
|
| 327 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
#composer textarea {
|
| 329 |
-
flex: 1;
|
| 330 |
resize: none; overflow-y: auto;
|
| 331 |
-
border:
|
| 332 |
-
padding:
|
| 333 |
-
color: var(--text); box-shadow:
|
| 334 |
}
|
| 335 |
-
#composer textarea:focus { outline: none;
|
| 336 |
-
|
| 337 |
-
width:
|
| 338 |
-
display: flex; align-items: center; justify-content: center;
|
| 339 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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:
|
| 345 |
-
#send-btn
|
| 346 |
-
#
|
| 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:
|
| 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
|
| 391 |
-
#sidebar-
|
|
|
|
|
|
|
|
|
|
| 392 |
@media (max-width: 860px) {
|
| 393 |
-
#app { grid-template-columns: 1fr; grid-template-areas: "header" "main"
|
| 394 |
#sidebar {
|
| 395 |
-
position: fixed; top:
|
| 396 |
z-index: 50; box-shadow: var(--shadow-lg);
|
| 397 |
}
|
| 398 |
-
|
| 399 |
-
#sidebar-
|
| 400 |
-
.examples-hero img {
|
| 401 |
-
.examples-heading { font-size:
|
| 402 |
}
|
| 403 |
|
| 404 |
-
/* ── Scrollbars ───────────────────────────────────────
|
| 405 |
-
::-webkit-scrollbar { width:
|
| 406 |
::-webkit-scrollbar-track { background: transparent; }
|
| 407 |
-
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius:
|
| 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 |
-
<
|
| 529 |
-
<
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
<
|
| 534 |
-
|
|
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| 633 |
$("sidebar-toggle").addEventListener("click", () => {
|
| 634 |
-
$("app").classList.toggle("sidebar-
|
| 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,
|
| 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 ────────────────────────────────────────────────────── */
|