939 lines
28 KiB
CSS
939 lines
28 KiB
CSS
/* ==================== 1. 全局 ==================== */
|
||
body, html {
|
||
margin: 0; padding: 0;
|
||
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
|
||
background-color: #ffffff;
|
||
color: #333;
|
||
overflow-x: hidden;
|
||
/* 🌟 不再给 html/body 设 height:100%(会让 body 退化为内部滚动容器,
|
||
导致 window.scrollY/scrollTo 失效;视口高度由 #chat-container 的 min-height:100vh 承担) */
|
||
}
|
||
|
||
#chat-container {
|
||
max-width: 95%;
|
||
margin: 0 auto;
|
||
padding: 20px 20px 20px 20px;
|
||
min-height: 100vh; /* 🌟 至少占满整个视口高度 */
|
||
}
|
||
|
||
/* ==================== 隐藏 WebEngine 原生滚动条 ==================== */
|
||
/* 改用右侧自定义 Qt 滚动条(WebScrollBar),避免内置滚动条高速滑动时的重绘延迟观感 */
|
||
::-webkit-scrollbar {
|
||
width: 0px;
|
||
height: 0px;
|
||
background: transparent;
|
||
}
|
||
|
||
/* ==================== 会话加载界面 ==================== */
|
||
.session-loading {
|
||
position: fixed;
|
||
top: 0; left: 0; right: 0; bottom: 0;
|
||
z-index: 999;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: #ffffff;
|
||
opacity: 1;
|
||
transition: opacity 0.45s ease; /* 结束后的渐变退场 */
|
||
}
|
||
.session-loading.hide {
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
}
|
||
.session-loading-box {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
.session-loading-icon {
|
||
width: 72px;
|
||
height: 72px;
|
||
}
|
||
.session-loading-bar {
|
||
width: 190px;
|
||
height: 4px;
|
||
margin-top: 26px;
|
||
background: #eceef2;
|
||
border-radius: 2px;
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
.session-loading-bar-fill {
|
||
position: absolute;
|
||
top: 0; left: 0;
|
||
height: 100%;
|
||
width: 36%;
|
||
border-radius: 2px;
|
||
background: linear-gradient(90deg, rgba(59,130,246,0) 0%, #3b82f6 50%, rgba(59,130,246,0) 100%);
|
||
animation: loadingSweep 1.2s ease-in-out infinite; /* 从左到右扫描,非进度条 */
|
||
}
|
||
@keyframes loadingSweep {
|
||
0% { transform: translateX(-110%); }
|
||
100% { transform: translateX(300%); }
|
||
}
|
||
|
||
/* ==================== 欢迎界面 ==================== */
|
||
.welcome-screen {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
position: fixed; /* 🌟 固定定位,脱离文档流 */
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
padding: 60px 20px;
|
||
pointer-events: none; /* 🌟 允许点击穿透到下方的输入框 */
|
||
}
|
||
|
||
.welcome-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
pointer-events: auto; /* 🌟 但内容本身可以交互 */
|
||
/* 旧的渐入动画已移除:会话切换统一由加载界面完成过渡 */
|
||
}
|
||
|
||
/* 欢迎页图标:main.svg */
|
||
.welcome-icon {
|
||
width: 56px;
|
||
height: 56px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.brand-name {
|
||
font-size: 40px;
|
||
font-weight: 700;
|
||
margin: 0;
|
||
letter-spacing: 6px;
|
||
font-family: "Microsoft YaHei UI", "Microsoft YaHei", "微软雅黑", "Segoe UI", sans-serif;
|
||
background: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%);
|
||
-webkit-background-clip: text;
|
||
background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
text-fill-color: transparent;
|
||
}
|
||
|
||
.brand-tagline {
|
||
font-size: 15px;
|
||
color: #8a94a6;
|
||
margin: 14px 0 0 0;
|
||
font-weight: 400;
|
||
letter-spacing: 5px;
|
||
}
|
||
|
||
|
||
/* ==================== 2. 消息气泡 ==================== */
|
||
.message-wrapper {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
margin-bottom: 30px;
|
||
}
|
||
.message-wrapper.user { justify-content: flex-end; }
|
||
|
||
/* ==================== 3. 头像 ==================== */
|
||
.avatar {
|
||
width: 32px; height: 32px;
|
||
border-radius: 6px;
|
||
display: flex; justify-content: center; align-items: center;
|
||
font-weight: bold; font-size: 14px;
|
||
flex-shrink: 0;
|
||
margin-top: 20px;
|
||
}
|
||
.assistant .avatar { background-color: #4a90d9; color: white; margin-right: 15px; }
|
||
.user .avatar { background-color: #e3e3e3; color: #555; margin-left: 15px; order: 2; }
|
||
|
||
/* ==================== 4. 消息内容区 ==================== */
|
||
.message-content {
|
||
max-width: 85%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.assistant .message-content {
|
||
align-items: flex-start;
|
||
/* 🆕 助手气泡恒定宽度:输出中/完成后一律 85%,不随内容伸缩(流式特效不受影响) */
|
||
width: 85%;
|
||
}
|
||
/* 🆕 内层同步撑满:.reply-content 基类是 fit-content(贴内容缩),
|
||
可见内容块(正文段/思考卡/工具卡)都在它里面 → 必须 100% 才真正恒定 */
|
||
.assistant .reply-content { width: 100%; }
|
||
.user .message-content { align-items: flex-end; }
|
||
|
||
.sender-name {
|
||
font-size: 11px; color: #aaa;
|
||
margin-bottom: 6px; font-weight: 600;
|
||
text-transform: uppercase; letter-spacing: 0.5px;
|
||
}
|
||
|
||
.reply-content {
|
||
line-height: 1.6; font-size: 15px;
|
||
width: fit-content; max-width: 100%;
|
||
}
|
||
.user .reply-content {
|
||
background-color: #f4f4f4;
|
||
padding: 10px 18px;
|
||
border-radius: 18px; border-top-right-radius: 4px;
|
||
color: #333; text-align: left;
|
||
}
|
||
|
||
/* ==================== 5. 思考过程 ==================== */
|
||
.think-block {
|
||
margin-bottom: 12px; border-radius: 8px;
|
||
background-color: #ffffff; border: 1px solid #eaeaea;
|
||
overflow: hidden; transition: all 0.3s ease; width: 100%;
|
||
}
|
||
.think-block summary {
|
||
padding: 8px 14px; font-size: 13px; color: #888;
|
||
cursor: pointer; user-select: none;
|
||
background-color: #fafafa; list-style: none;
|
||
display: flex; align-items: center; font-weight: 500;
|
||
}
|
||
.think-block summary .chev { color: #b8b8b8; margin-right: 8px; }
|
||
.think-block[open] summary { border-bottom: 1px dashed #eaeaea; }
|
||
.think-content {
|
||
padding: 12px 14px; font-size: 13px; color: #777;
|
||
background-color: #fff; max-height: 400px; overflow-y: auto;
|
||
}
|
||
|
||
/* 🌟 流式输出中:flex 锁底,展示最新思考内容 */
|
||
/* 🌟 流式输出中:思考框保持可滚动,JS 控制锁底 */
|
||
.message-wrapper.streaming .think-content {
|
||
overflow-y: auto !important;
|
||
}
|
||
|
||
|
||
.think-inner {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
|
||
.think-content.markdown-body p { color: #777; margin-bottom: 8px; }
|
||
|
||
/* ============ 思考/压缩气泡内:代码朴素渲染 ============
|
||
压缩摘要充满代码:浅色语法色(#a626a4 紫)+ code-block-wrapper 边框/语言栏,
|
||
让定格后的气泡观感"紫色带边框"。此处统一朴素灰、无边框无头部;
|
||
正文气泡的代码块不受影响。 */
|
||
.think-content .code-block-wrapper {
|
||
border: none;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
min-width: 0;
|
||
margin: 8px 0;
|
||
}
|
||
.think-content .code-header { display: none; }
|
||
.think-content .code-block-wrapper pre,
|
||
.think-content .code-block-wrapper pre code,
|
||
.think-content .code-block-wrapper .hljs,
|
||
.think-content .code-block-wrapper .hljs * {
|
||
color: #777 !important;
|
||
background: transparent !important;
|
||
}
|
||
.think-content code,
|
||
.think-content.markdown-body p code {
|
||
color: #777;
|
||
background-color: #f6f7f9;
|
||
}
|
||
|
||
/* ==================== 6. Markdown 基础 ==================== */
|
||
.markdown-body p { margin-top: 0; margin-bottom: 10px; }
|
||
.markdown-body code {
|
||
font-family: 'Consolas', 'Courier New', monospace; font-size: 13px;
|
||
}
|
||
.markdown-body p code {
|
||
background-color: #f0f0f0; color: #e83e8c;
|
||
padding: 2px 5px; border-radius: 4px;
|
||
}
|
||
|
||
/* ==================== 6b. 🌟 KaTeX 公式渲染 ==================== */
|
||
.katex-display {
|
||
margin: 10px 0; padding: 4px 2px;
|
||
overflow-x: auto; overflow-y: hidden;
|
||
}
|
||
.katex-display::-webkit-scrollbar { height: 6px; }
|
||
.katex-display::-webkit-scrollbar-thumb { background: #d0d0d0; border-radius: 3px; }
|
||
.markdown-body .katex { font-size: 1.06em; }
|
||
.markdown-body .katex-display { font-size: 1.08em; }
|
||
|
||
/* ==================== 7. 代码块 ==================== */
|
||
.code-block-wrapper {
|
||
position: relative;
|
||
border: 1px solid #e5e5e5; border-radius: 8px;
|
||
margin: 12px 0; overflow: hidden;
|
||
background-color: #ffffff;
|
||
min-width: 500px; /* 短代码也保持基本宽度,避免气泡过窄难看 */
|
||
}
|
||
|
||
.code-header {
|
||
display: flex; justify-content: space-between; align-items: center;
|
||
background-color: #fafafa; padding: 4px 10px;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
.code-lang-label {
|
||
font-size: 11px; color: #aaa; font-weight: 500;
|
||
text-transform: lowercase; letter-spacing: 0.3px;
|
||
}
|
||
.code-header-actions { display: flex; align-items: center; gap: 4px; }
|
||
|
||
.code-header button {
|
||
background: transparent; border: 1px solid transparent;
|
||
color: #999; cursor: pointer;
|
||
display: flex; align-items: center; gap: 4px;
|
||
font-size: 12px; padding: 3px 8px; border-radius: 4px;
|
||
transition: all 0.15s ease; font-family: inherit; outline: none;
|
||
}
|
||
.code-header button:hover {
|
||
background-color: #f0f0f0; border-color: #e0e0e0; color: #555;
|
||
}
|
||
.copy-btn.copied {
|
||
color: #52c41a !important;
|
||
border-color: rgba(82, 196, 26, 0.3) !important;
|
||
background-color: rgba(82, 196, 26, 0.06) !important;
|
||
}
|
||
|
||
/* 代码主体 */
|
||
.code-body {
|
||
margin: 0; padding: 14px;
|
||
background-color: #fafafa !important;
|
||
overflow-x: auto;
|
||
max-height: 5000px;
|
||
}
|
||
|
||
/* 修改折叠态:允许滚动但隐藏滚动条 */
|
||
.code-body.collapsed {
|
||
max-height: 140px !important;
|
||
overflow-y: auto !important; /* ← 从 hidden 改为 auto */
|
||
scrollbar-width: none; /* Firefox */
|
||
}
|
||
.code-body.collapsed::-webkit-scrollbar {
|
||
display: none; /* Chrome/Safari */
|
||
}
|
||
|
||
/* 🌟 流式输出中:用 flex 布局天然展示底部代码,不依赖 JS scrollTop */
|
||
.message-wrapper.streaming .code-body.collapsed {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
justify-content: flex-end !important;
|
||
overflow: hidden !important;
|
||
}
|
||
|
||
|
||
/* 默认折叠遮罩:底部渐隐(展示顶部代码) */
|
||
.code-block-wrapper:has(.code-body.collapsed)::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0; left: 0; right: 0;
|
||
height: 40px;
|
||
background: linear-gradient(transparent, #fafafa);
|
||
pointer-events: none;
|
||
border-radius: 0 0 8px 8px;
|
||
}
|
||
|
||
/* 🌟 流式输出中遮罩:顶部渐隐(展示底部最新代码) */
|
||
.message-wrapper.streaming .code-block-wrapper:has(.code-body.collapsed)::after {
|
||
top: 36px; bottom: auto;
|
||
border-radius: 0;
|
||
background: linear-gradient(#fafafa, transparent);
|
||
}
|
||
|
||
/* 强制覆盖 highlight.js 深色背景 */
|
||
.code-block-wrapper pre,
|
||
.code-block-wrapper pre code,
|
||
.code-block-wrapper .hljs {
|
||
background-color: #fafafa !important;
|
||
color: #383a42 !important;
|
||
}
|
||
|
||
/* 浅色语法高亮 */
|
||
.code-block-wrapper .hljs-keyword,
|
||
.code-block-wrapper .hljs-selector-tag,
|
||
.code-block-wrapper .hljs-title,
|
||
.code-block-wrapper .hljs-section,
|
||
.code-block-wrapper .hljs-doctag,
|
||
.code-block-wrapper .hljs-name,
|
||
.code-block-wrapper .hljs-strong { color: #a626a4; }
|
||
.code-block-wrapper .hljs-string,
|
||
.code-block-wrapper .hljs-attr { color: #50a14f; }
|
||
.code-block-wrapper .hljs-number,
|
||
.code-block-wrapper .hljs-literal,
|
||
.code-block-wrapper .hljs-variable,
|
||
.code-block-wrapper .hljs-template-variable,
|
||
.code-block-wrapper .hljs-tag .hljs-attr { color: #986801; }
|
||
.code-block-wrapper .hljs-comment,
|
||
.code-block-wrapper .hljs-quote { color: #a0a1a7; font-style: italic; }
|
||
.code-block-wrapper .hljs-built_in,
|
||
.code-block-wrapper .hljs-builtin-name { color: #c18401; }
|
||
.code-block-wrapper .hljs-function .hljs-title,
|
||
.code-block-wrapper .hljs-class .hljs-title { color: #4078f2; }
|
||
.code-block-wrapper .hljs-type,
|
||
.code-block-wrapper .hljs-params { color: #c18401; }
|
||
.code-block-wrapper .hljs-meta { color: #4078f2; }
|
||
.code-block-wrapper code {
|
||
font-family: 'Consolas', 'Courier New', monospace; font-size: 13px;
|
||
}
|
||
|
||
/* ==================== 7.1 SVG 代码块:绘制/源码 切换 ==================== */
|
||
/* 渲染容器:透明背景、居中,防超大 SVG 撑破布局 */
|
||
.svg-render-body {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 14px;
|
||
background: transparent;
|
||
overflow: auto;
|
||
max-height: 5000px;
|
||
}
|
||
.svg-render-body svg {
|
||
min-width: 360px; /* 小图适当放大,避免渲染出来太小看不清 */
|
||
max-width: 100%;
|
||
height: auto;
|
||
}
|
||
/* 渲染态:隐藏代码体与折叠渐隐遮罩 */
|
||
.code-block-wrapper.svg-mode .code-body { display: none !important; }
|
||
.code-block-wrapper.svg-mode:has(.code-body.collapsed)::after { display: none; }
|
||
/* 渲染态按钮高亮(此时按钮文案为「源码」) */
|
||
.code-header .svg-render-btn.active {
|
||
color: #10a37f;
|
||
border-color: rgba(16, 163, 127, 0.3);
|
||
background-color: rgba(16, 163, 127, 0.06);
|
||
}
|
||
/* 折叠按钮被锁定时(处于渲染态) */
|
||
.code-header .fold-btn:disabled {
|
||
opacity: 0.4;
|
||
cursor: not-allowed;
|
||
pointer-events: none;
|
||
}
|
||
/* 流式输出中隐藏「绘制」按钮(与复制按钮同等待遇,避免重渲冲掉切换状态) */
|
||
.message-wrapper.streaming .svg-render-btn {
|
||
display: none !important;
|
||
}
|
||
|
||
/* ==================== 8. 长文本附件卡片 ==================== */
|
||
.long-text-card {
|
||
display: flex; align-items: center; gap: 12px;
|
||
padding: 12px 16px; background-color: #f8f8f8;
|
||
border: 1px solid #e8e8e8; border-radius: 12px;
|
||
cursor: pointer; transition: all 0.2s ease; max-width: 320px;
|
||
}
|
||
.long-text-card:hover {
|
||
background-color: #f0f0f0; border-color: #d0d0d0;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||
}
|
||
.card-icon {
|
||
flex-shrink: 0; width: 40px; height: 40px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
background-color: #fff; border-radius: 8px; border: 1px solid #eee;
|
||
}
|
||
.card-info { overflow: hidden; }
|
||
.card-title {
|
||
font-size: 13px; color: #333; font-weight: 500;
|
||
white-space: nowrap; overflow: hidden;
|
||
text-overflow: ellipsis; max-width: 220px;
|
||
}
|
||
.card-meta { font-size: 11px; color: #aaa; margin-top: 3px; }
|
||
|
||
/* ==================== 9. 模态框 ==================== */
|
||
.content-modal-overlay {
|
||
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
|
||
background-color: rgba(0,0,0,0);
|
||
display: flex; justify-content: center; align-items: center;
|
||
z-index: 9999; transition: background-color 0.2s ease;
|
||
}
|
||
.content-modal-overlay.visible { background-color: rgba(0,0,0,0.4); }
|
||
.content-modal {
|
||
background-color: #fff; border-radius: 12px;
|
||
width: 70%; max-width: 700px; max-height: 75vh;
|
||
display: flex; flex-direction: column;
|
||
box-shadow: 0 20px 60px rgba(0,0,0,0.15);
|
||
transform: scale(0.95); opacity: 0;
|
||
transition: all 0.2s ease; overflow: hidden;
|
||
}
|
||
.content-modal-overlay.visible .content-modal {
|
||
transform: scale(1); opacity: 1;
|
||
}
|
||
.modal-header {
|
||
display: flex; justify-content: space-between; align-items: center;
|
||
padding: 14px 20px; border-bottom: 1px solid #eee;
|
||
font-size: 14px; font-weight: 600; color: #333;
|
||
}
|
||
.modal-close-btn {
|
||
background: transparent; border: none; font-size: 18px;
|
||
color: #999; cursor: pointer; padding: 4px 8px;
|
||
border-radius: 4px; transition: all 0.15s ease; line-height: 1;
|
||
}
|
||
.modal-close-btn:hover { background-color: #f0f0f0; color: #333; }
|
||
.modal-body {
|
||
padding: 16px 20px; overflow-y: auto;
|
||
font-family: 'Consolas', 'Courier New', monospace;
|
||
font-size: 13px; line-height: 1.6; color: #444;
|
||
white-space: pre-wrap; word-break: break-all;
|
||
margin: 0; background-color: #fafafa;
|
||
}
|
||
|
||
/* ==================== 10. 错误与动画 ==================== */
|
||
.system-error {
|
||
background-color: #fef0f0; border: 1px solid #fde2e2;
|
||
color: #f56c6c; padding: 10px 15px; border-radius: 8px;
|
||
margin-top: 10px; font-size: 13px; font-weight: bold;
|
||
display: inline-block;
|
||
}
|
||
|
||
/* ==================== 11. 多附件容器 ==================== */
|
||
.attachments-container {
|
||
display: flex; flex-direction: column;
|
||
gap: 8px; margin-bottom: 8px;
|
||
}
|
||
.attachments-container .long-text-card { max-width: 300px; }
|
||
.user .attachments-container + .reply-content { margin-top: 4px; }
|
||
/* ==================== 12. 流式输出状态(纯 CSS 控制,不闪烁) ==================== */
|
||
.message-wrapper.streaming .copy-btn {
|
||
display: none !important;
|
||
}
|
||
|
||
.message-wrapper.streaming .fold-btn {
|
||
font-size: 0 !important;
|
||
pointer-events: none;
|
||
position: relative;
|
||
}
|
||
|
||
.message-wrapper.streaming .fold-btn::after {
|
||
content: '输出中...';
|
||
font-size: 12px;
|
||
color: #f5a623;
|
||
}
|
||
/* 过渡态:从 flex-end 切换到 scroll 模式,保持显示底部 */
|
||
.code-body.collapsed.scroll-locked {
|
||
display: block !important;
|
||
overflow-y: auto !important;
|
||
justify-content: initial !important;
|
||
flex-direction: initial !important;
|
||
scrollbar-width: none;
|
||
}
|
||
.code-body.collapsed.scroll-locked::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
/* ==================== 13. 消息操作栏 ==================== */
|
||
.message-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 2px;
|
||
margin-top: 8px;
|
||
}
|
||
|
||
.action-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 30px;
|
||
height: 30px;
|
||
border: none;
|
||
background: transparent;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
color: #999;
|
||
transition: all 0.15s ease;
|
||
padding: 0;
|
||
}
|
||
|
||
.action-btn:hover {
|
||
background-color: #f0f0f0;
|
||
color: #555;
|
||
}
|
||
|
||
.action-btn svg {
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 流式输出中隐藏操作栏 */
|
||
.message-wrapper.streaming .message-actions {
|
||
display: none !important;
|
||
}
|
||
/* ================= 分支选择器 ================= */
|
||
.branch-selector {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
margin-left: 10px;
|
||
background-color: #f0f0f0;
|
||
border-radius: 12px;
|
||
padding: 2px 6px;
|
||
font-size: 11px;
|
||
color: #666;
|
||
user-select: none;
|
||
}
|
||
|
||
/* 暗色模式的话可以加这句,如果是纯亮色就不用 */
|
||
@media (prefers-color-scheme: dark) {
|
||
.branch-selector { background-color: #333; color: #aaa; }
|
||
}
|
||
|
||
.branch-btn {
|
||
background: transparent;
|
||
border: none;
|
||
cursor: pointer;
|
||
padding: 0 4px;
|
||
color: #888;
|
||
font-size: 10px;
|
||
font-weight: bold;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.branch-btn:hover:not(:disabled) {
|
||
color: #111;
|
||
}
|
||
|
||
.branch-btn:disabled {
|
||
color: #ccc;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
.branch-text {
|
||
margin: 0 4px;
|
||
font-family: monospace;
|
||
}
|
||
/* ================= 删除确认气泡 ================= */
|
||
.delete-confirm-popover {
|
||
position: absolute;
|
||
bottom: 120%; /* 浮在按钮上方 */
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background-color: #fee2e2; /* 淡红色警告背景 */
|
||
border: 1px solid #f87171;
|
||
border-radius: 6px;
|
||
padding: 6px 10px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
box-shadow: 0 4px 10px rgba(239, 68, 68, 0.2);
|
||
z-index: 100;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
width: max-content; /* 🌟 核心修复:保证气泡背景宽度根据文字自适应,不被按钮挤压 */
|
||
}
|
||
.delete-confirm-popover:hover {
|
||
background-color: #fecaca;
|
||
}
|
||
.delete-confirm-text {
|
||
color: #ef4444;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
}
|
||
.delete-confirm-popover svg {
|
||
stroke: #ef4444;
|
||
}
|
||
|
||
/* ================= 用户消息专属操作栏 ================= */
|
||
.user-actions {
|
||
display: flex;
|
||
justify-content: flex-end; /* 靠右对齐 */
|
||
margin-top: 4px;
|
||
opacity: 1; /* 默认隐藏,悬浮显示 */
|
||
transition: opacity 0.2s ease-in-out;
|
||
}
|
||
|
||
.message-wrapper.user:hover .user-actions {
|
||
opacity: 1; /* 鼠标悬浮气泡时,显示操作栏 */
|
||
}
|
||
|
||
/* 强制指定按钮的图标颜色、大小和边距,打破继承魔咒 */
|
||
.user-actions .action-btn {
|
||
background: transparent;
|
||
border: none;
|
||
color: #999999; /* 强制指定为高级灰,让 SVG 显形 */
|
||
padding: 6px;
|
||
margin-left: 4px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.user-actions .action-btn:hover {
|
||
background-color: #eaeaea;
|
||
color: #333333; /* 悬浮时图标变深 */
|
||
}
|
||
|
||
.user-actions .user-delete-btn:hover {
|
||
background-color: #fee2e2;
|
||
color: #ef4444;
|
||
}
|
||
|
||
/* 🌟 用户侧靠右对齐 */
|
||
.user-actions .delete-confirm-popover {
|
||
left: auto;
|
||
right: 0;
|
||
transform: none;
|
||
}
|
||
|
||
/* ⚠️ 注意:删除原本文件最底部的 "确认删除弹窗基础样式" 这一大段重复代码,避免样式冲突 */
|
||
|
||
/* ================= 确认删除弹窗基础样式 ================= */
|
||
.delete-confirm-popover {
|
||
position: absolute;
|
||
bottom: 120%;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background-color: #fee2e2;
|
||
border: 1px solid #f87171;
|
||
border-radius: 6px;
|
||
padding: 6px 10px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
box-shadow: 0 4px 10px rgba(239, 68, 68, 0.2);
|
||
z-index: 100;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.delete-confirm-popover:hover {
|
||
background-color: #fecaca;
|
||
}
|
||
|
||
.delete-confirm-text {
|
||
color: #ef4444;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.delete-confirm-popover svg {
|
||
stroke: #ef4444;
|
||
}
|
||
/* ==================== 工具执行气泡(pi tool_execution_* 事件,浅色·对齐思考气泡) ==================== */
|
||
.tool-chip {
|
||
margin: 10px 0 4px 0; border-radius: 8px;
|
||
background-color: #ffffff; border: 1px solid #eaeaea;
|
||
overflow: hidden; transition: all 0.3s ease; width: 100%;
|
||
}
|
||
.tool-chip.streaming {
|
||
border-color: #d6e4ff;
|
||
background-color: #fbfdff;
|
||
}
|
||
.tool-chip summary {
|
||
padding: 8px 14px; font-size: 12.5px; color: #888;
|
||
cursor: pointer; user-select: none;
|
||
background-color: #fafafa; list-style: none;
|
||
display: flex; align-items: center; gap: 8px; font-weight: 500;
|
||
}
|
||
.tool-chip summary::-webkit-details-marker { display: none; }
|
||
.tool-chip summary .chev { color: #b8b8b8; }
|
||
.tool-chip[open] summary { border-bottom: 1px dashed #eaeaea; }
|
||
.tool-chip-icon { font-size: 13px; color: #bbb; }
|
||
.tool-chip-name {
|
||
font-family: Consolas, Monaco, monospace;
|
||
font-weight: 600; color: #666; font-size: 12px;
|
||
}
|
||
.tool-chip-brief {
|
||
font-family: Consolas, Monaco, monospace;
|
||
color: #aaa; font-size: 12px;
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
flex: 1;
|
||
}
|
||
.tool-chip-brief.done { color: #52c41a; }
|
||
.tool-chip-status {
|
||
margin-left: auto; flex-shrink: 0;
|
||
font-size: 11px; padding: 1px 8px; border-radius: 10px;
|
||
}
|
||
.tool-chip-status.running {
|
||
color: #4a7fd4; background: #eef4ff;
|
||
animation: toolPulse 1.2s ease-in-out infinite;
|
||
}
|
||
.tool-chip-status.ok { color: #52c41a; background: #f6ffed; }
|
||
.tool-chip-status.fail { color: #cf1322; background: #fff1f0; }
|
||
@keyframes toolPulse {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.45; }
|
||
}
|
||
.tool-chip-body {
|
||
padding: 10px 14px 12px 14px;
|
||
max-height: 260px; overflow: auto; background-color: #fff;
|
||
}
|
||
.tool-chip-label {
|
||
font-size: 11px; color: #bbb; font-weight: 600;
|
||
margin: 6px 0 4px 0; letter-spacing: 0.5px;
|
||
}
|
||
.tool-chip-label:first-child { margin-top: 0; }
|
||
.tool-chip-pre {
|
||
margin: 0 0 6px 0; padding: 8px 10px;
|
||
background-color: #f6f7f9; color: #555;
|
||
border: 1px solid #eef0f3; border-radius: 6px;
|
||
font-family: Consolas, Monaco, monospace;
|
||
font-size: 11.5px; line-height: 1.55;
|
||
white-space: pre-wrap; word-break: break-all;
|
||
max-height: 150px; overflow: auto;
|
||
}
|
||
|
||
/* ==================== 系统提示(如:已自动压缩上下文) ==================== */
|
||
.system-note {
|
||
text-align: center;
|
||
font-size: 12px;
|
||
color: #6b7280;
|
||
background: #f3f4f6;
|
||
border-radius: 10px;
|
||
padding: 6px 14px;
|
||
margin: 10px auto;
|
||
max-width: 70%;
|
||
}
|
||
|
||
/* ==================== 增量流式渲染容器 ==================== */
|
||
/* 注意:不能用 display:contents —— 本机 Chromium 下父盒(.md-segment)高度坍缩为 0,
|
||
导致流式正文整段不可见(切会话重渲走无包裹路径所以可见)。用 block 规避。 */
|
||
.md-stable, .md-tail {
|
||
display: block;
|
||
}
|
||
|
||
/* ==================== 浅色 SVG 箭头(替代文字字形) ==================== */
|
||
.chev {
|
||
flex: none; display: inline-block;
|
||
transition: transform 0.2s ease-in-out;
|
||
}
|
||
.think-block[open] .chev, .tool-chip[open] .chev { transform: rotate(90deg); }
|
||
.think-label { color: inherit; }
|
||
|
||
/* ==================== 深度思考:默认收起 + 进行中蓝色呼吸动画 ==================== */
|
||
.think-block.streaming-think > summary .think-label {
|
||
color: #3b82f6;
|
||
font-weight: 600;
|
||
animation: think-breathe 1.6s ease-in-out infinite;
|
||
}
|
||
.think-block.streaming-think > summary .think-label::after {
|
||
content: '';
|
||
display: inline-block;
|
||
width: 1.2em;
|
||
text-align: left;
|
||
animation: think-dots 1.4s infinite;
|
||
}
|
||
@keyframes think-breathe {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.4; }
|
||
}
|
||
@keyframes think-dots {
|
||
0% { content: ''; }
|
||
25% { content: '.'; }
|
||
50% { content: '..'; }
|
||
75% { content: '...'; }
|
||
}
|
||
|
||
/* ==================== 工具 chip:耗时 / 超时徽章 ==================== */
|
||
.tool-chip-time {
|
||
font-size: 11px;
|
||
color: #9ca3af;
|
||
font-variant-numeric: tabular-nums;
|
||
margin-left: 2px;
|
||
}
|
||
.tool-chip-timeout {
|
||
font-size: 11px;
|
||
color: #dc2626;
|
||
font-weight: 600;
|
||
margin-left: 2px;
|
||
}
|
||
.tool-chip-livetimer {
|
||
/* 🆕 bash 运行中每秒读秒(N/Ts):琥珀色 + 等宽数字,不跳动 */
|
||
font-size: 11px;
|
||
color: #d97706;
|
||
font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
margin-left: 2px;
|
||
}
|
||
|
||
/* ==================== 工具结果:长输出展开按钮 ==================== */
|
||
.tool-expand-btn {
|
||
display: block;
|
||
width: 100%;
|
||
margin: 4px 0 0;
|
||
padding: 3px 8px;
|
||
font-size: 11px;
|
||
line-height: 1.5;
|
||
color: #3b82f6;
|
||
background: #eff6ff;
|
||
border: 1px solid #bfdbfe;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
text-align: center;
|
||
font-family: inherit;
|
||
}
|
||
.tool-expand-btn:hover { background: #dbeafe; }
|
||
.tool-chip-pre.tool-chip-full {
|
||
max-height: 360px;
|
||
overflow: auto;
|
||
}
|
||
|
||
/* ==================== 时间线:正文段 / 流式光标 ==================== */
|
||
.md-segment:empty { display: none; }
|
||
.md-segment > :first-child { margin-top: 0; }
|
||
.md-segment > :last-child { margin-bottom: 0; }
|
||
/* block 包裹下,额外压平内层首尾段落的边距,保持气泡观感 */
|
||
.md-segment > :last-child > :last-child { margin-bottom: 0; }
|
||
/* 光标 "Chasing a shining star":文字顶住不动,只有 ● 缩放闪烁(星光脉冲无限循环)。
|
||
生命周期=原版:消息第一个时间线事件出现即显示 → finishMessage 移除,
|
||
思考/工具/压缩/正文全程保持(无休眠态) */
|
||
.streaming-typing {
|
||
display: inline-block; margin-left: 4px; color: #3b82f6;
|
||
font-size: 13px;
|
||
font-family: "Cascadia Mono", "Cascadia Code", Consolas, "Lucida Console", monospace;
|
||
}
|
||
.streaming-typing .typing-dot {
|
||
display: inline-block;
|
||
animation: cursor-star 1.6s ease-in-out infinite;
|
||
}
|
||
@keyframes cursor-star {
|
||
0%, 100% {
|
||
opacity: .25;
|
||
transform: scale(.85);
|
||
text-shadow: none;
|
||
}
|
||
50% {
|
||
opacity: 1;
|
||
transform: scale(1.15);
|
||
text-shadow: 0 0 6px rgba(59, 130, 246, .8), 0 0 12px rgba(59, 130, 246, .45);
|
||
}
|
||
}
|
||
|
||
|
||
/* ========== 助手正文(流式中/完成后一致,保持透明) ========== */
|
||
.message-wrapper.assistant .reply-content .md-segment {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
padding: 0;
|
||
color: #30343b;
|
||
background: transparent;
|
||
border: none;
|
||
border-radius: 0;
|
||
}
|
||
.message-wrapper.assistant .reply-content .md-segment + .md-segment {
|
||
margin-top: 6px;
|
||
}
|
||
|
||
/* ==================== 🆕 P1-01 渲染窗口:加载入口按钮 ==================== */
|
||
/* 上/下两端的「加载更多」入口:无边框浅灰胶囊,居中;无更多消息时由 JS 隐藏 */
|
||
.load-window-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 220px;
|
||
margin: 14px auto;
|
||
padding: 6px 14px;
|
||
font-size: 12px;
|
||
color: #666;
|
||
background: #f4f4f6;
|
||
border: 1px solid #e3e3e8;
|
||
border-radius: 999px;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
transition: background 0.15s ease, color 0.15s ease;
|
||
}
|
||
.load-window-btn:hover {
|
||
background: #eaeaf0;
|
||
color: #333;
|
||
}
|
||
.load-window-btn[hidden] {
|
||
display: none;
|
||
}
|
||
/* 底部入口与 scroll-anchor 的间距(scroll-anchor 自带 150px margin) */
|
||
#load-newer {
|
||
margin-bottom: 4px;
|
||
}
|