AIstudioProxyAPI / webui.css
hins111's picture
Upload 11 files
6a0eaad verified
/* --- Modernized M3-Inspired Styles --- */
:root {
/* Material 3 宇宙极光主题 - 亮色调色板 (更柔和版) */
--primary-rgb: 85, 77, 175;
/* #554DAF - 柔和深蓝紫色 */
--on-primary-rgb: 255, 255, 255;
/* 在主色上的文本 */
--primary-container-rgb: 231, 229, 252;
/* #E7E5FC - 柔和淡紫色容器 */
--on-primary-container-rgb: 31, 26, 70;
/* #1F1A46 - 主色容器上的文本 */
--secondary-rgb: 105, 81, 146;
/* #695192 - 柔和紫罗兰色 */
--on-secondary-rgb: 255, 255, 255;
/* 次色上的文本 */
--secondary-container-rgb: 238, 230, 255;
/* #EEE6FF - 更淡的紫色容器 */
--on-secondary-container-rgb: 45, 32, 70;
/* #2D2046 - 次色容器上的文本 */
--tertiary-rgb: 76, 173, 188;
/* #4CADBC - 柔和青蓝色 */
--on-tertiary-rgb: 0, 55, 62;
/* #00373E - 第三色上的文本 */
--tertiary-container-rgb: 220, 242, 246;
/* #DCF2F6 - 淡青蓝色容器 */
--on-tertiary-container-rgb: 8, 76, 84;
/* #084C54 - 第三色容器上的文本 */
--surface-rgb: 249, 249, 252;
/* #F9F9FC - 更中性的表面 */
--on-surface-rgb: 28, 30, 34;
/* #1C1E22 - 表面上的文本 */
--surface-variant-rgb: 232, 231, 242;
/* #E8E7F2 - 更柔和的表面变体 */
--on-surface-variant-rgb: 73, 74, 90;
/* #494A5A - 表面变体上的文本 */
--error-rgb: 178, 69, 122;
/* #B2457A - 柔和的错误色 */
--on-error-rgb: 255, 255, 255;
/* 错误色上的文本 */
--error-container-rgb: 255, 228, 238;
/* #FFE4EE - 更淡的错误容器 */
--on-error-container-rgb: 75, 13, 49;
/* #4B0D31 - 错误容器上的文本 */
--outline-rgb: 128, 127, 147;
/* #807F93 - 柔和轮廓线 */
/* 亮色主题变量 */
--bg-color: #f5f5fa;
/* 更中性的淡色背景 */
--container-bg: rgb(var(--surface-rgb));
/* 表面 */
--text-color: rgb(var(--on-surface-rgb));
/* 文本颜色 */
--primary-color: rgb(var(--primary-rgb));
/* 主色 */
--on-primary: rgb(var(--on-primary-rgb));
/* 主色上的文本 */
--primary-container: rgb(var(--primary-container-rgb));
/* 主色容器 */
--on-primary-container: rgb(var(--on-primary-container-rgb));
/* 主色容器上的文本 */
--secondary-color: rgb(var(--secondary-rgb));
/* 次色 */
--on-secondary: rgb(var(--on-secondary-rgb));
/* 次色上的文本 */
--secondary-container: rgb(var(--secondary-container-rgb));
/* 次色容器 */
--on-secondary-container: rgb(var(--on-secondary-container-rgb));
/* 次色容器上的文本 */
--user-msg-bg: var(--primary-container);
/* 用户消息背景 */
--user-msg-text: var(--on-primary-container);
/* 用户消息文本 */
--assistant-msg-bg: rgb(var(--surface-variant-rgb));
/* 助手消息背景 */
--assistant-msg-text: rgb(var(--on-surface-variant-rgb));
/* 助手消息文本 */
--system-msg-bg: rgba(var(--on-surface-rgb), 0.05);
/* 系统消息背景 */
--system-msg-text: rgba(var(--on-surface-rgb), 0.7);
/* 系统消息文本 */
--error-color: rgb(var(--error-rgb));
/* 错误颜色 */
--on-error: rgb(var(--on-error-rgb));
/* 错误颜色上的文本 */
--error-container: rgb(var(--error-container-rgb));
/* 错误容器 */
--on-error-container: rgb(var(--on-error-container-rgb));
/* 错误容器上的文本 */
--error-msg-bg: var(--error-container);
--error-msg-text: var(--on-error-container);
--border-color: rgba(var(--outline-rgb), 0.7);
/* 边框颜色 */
--input-bg: var(--container-bg);
/* 输入框背景 */
--input-border: rgba(var(--outline-rgb), 0.4);
/* 输入框边框 */
--input-focus-border: var(--primary-color);
/* 输入框聚焦边框 */
--input-focus-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.1);
/* 聚焦阴影 */
--button-bg: var(--primary-color);
/* 按钮背景 */
--button-text: var(--on-primary);
/* 按钮文本 */
--button-hover-bg: rgb(71, 64, 150);
/* 按钮悬停背景 - 深蓝色 */
--button-disabled-bg: rgba(var(--on-surface-rgb), 0.12);
/* 禁用按钮背景 */
--button-disabled-text: rgba(var(--on-surface-rgb), 0.38);
/* 禁用按钮文本 */
--clear-button-bg: rgba(var(--secondary-rgb), 0.9);
/* 清除按钮背景 */
--clear-button-text: var(--on-secondary);
/* 清除按钮文本 */
--clear-button-hover-bg: rgb(92, 71, 128);
/* 清除按钮悬停背景 - 深紫色 */
--sidebar-bg: rgba(var(--surface-rgb), 0.95);
/* 侧边栏背景 */
--sidebar-border: rgba(var(--outline-rgb), 0.3);
/* 侧边栏边框 */
--icon-button-bg: transparent;
--icon-button-hover-bg: rgba(var(--primary-rgb), 0.08);
--icon-button-color: rgb(var(--on-surface-variant-rgb));
--log-terminal-bg: #232043;
/* 日志终端背景 - 深蓝紫色但更柔和 */
--log-terminal-text: #d8d8e8;
/* 日志终端文本 - 更柔和的淡紫白色 */
--log-status-text: #f0f0ff;
/* 日志状态文本 - 浅色模式下使用更亮的白色 */
--log-status-error: #ff9db3;
/* 日志状态错误文本 - 浅色模式下的错误颜色 */
--theme-toggle-hover-bg: rgba(var(--secondary-rgb), 0.08);
--theme-toggle-color: var(--icon-button-color);
--theme-toggle-bg: transparent;
--card-bg: var(--container-bg);
--card-border: rgba(var(--outline-rgb), 0.2);
--card-shadow: var(--shadow-sm);
/* 边框半径 */
--border-radius-sm: 8px;
--border-radius-md: 12px;
--border-radius-lg: 16px;
--border-radius-xl: 28px;
/* 阴影 */
--shadow-sm: 0 1px 3px rgba(85, 77, 175, 0.08), 0 1px 2px rgba(85, 77, 175, 0.04);
--shadow-md: 0 4px 6px rgba(85, 77, 175, 0.06), 0 2px 4px rgba(85, 77, 175, 0.06);
--shadow-lg: 0 10px 15px rgba(85, 77, 175, 0.04), 0 4px 6px rgba(85, 77, 175, 0.03);
/* 尺寸变量 */
--sidebar-width: 320px;
--sidebar-transition: width 0.3s ease, padding 0.3s ease, border 0.3s ease, transform 0.3s ease;
--content-padding: 16px;
/* 动画速度 */
--transition-speed: 0.2s;
}
/* 深色模式调色板 */
html.dark-mode {
/* 深色主题 宇宙极光 调色板 (更柔和版) */
--primary-rgb: 161, 153, 219;
/* #A199DB - 柔和紫蓝色 */
--on-primary-rgb: 38, 33, 80;
/* #262150 - 深蓝紫色 */
--primary-container-rgb: 60, 53, 113;
/* #3C3571 - 柔和深蓝紫色容器 */
--on-primary-container-rgb: 231, 229, 252;
/* #E7E5FC - 柔和淡紫色 */
--secondary-rgb: 184, 171, 216;
/* #B8ABD8 - 柔和的淡紫蓝色 */
--on-secondary-rgb: 47, 36, 71;
/* #2F2447 - 深紫色 */
--secondary-container-rgb: 70, 57, 98;
/* #463962 - 中深紫色 */
--on-secondary-container-rgb: 238, 230, 255;
/* #EEE6FF - 更淡的紫色 */
--tertiary-rgb: 130, 200, 211;
/* #82C8D3 - 柔和青蓝色 */
--on-tertiary-rgb: 10, 73, 82;
/* #0A4952 - 深青色 */
--tertiary-container-rgb: 15, 86, 96;
/* #0F5660 - 中深青色 */
--on-tertiary-container-rgb: 195, 241, 252;
/* #C3F1FC - 淡青色 */
--surface-rgb: 28, 26, 46;
/* #1C1A2E - 更柔和的深蓝紫黑色 */
--on-surface-rgb: 231, 230, 245;
/* #E7E6F5 - 淡紫白色 */
--surface-variant-rgb: 68, 66, 86;
/* #444256 - 柔和的中深紫色 */
--on-surface-variant-rgb: 214, 212, 232;
/* #D6D4E8 - 柔和的淡紫色 */
--error-rgb: 231, 162, 195;
/* #E7A2C3 - 更柔和的淡粉色 */
--on-error-rgb: 72, 19, 50;
/* #481332 - 深粉色 */
--error-container-rgb: 97, 32, 67;
/* #612043 - 中深粉色 */
--on-error-container-rgb: 255, 228, 238;
/* #FFE4EE - 更淡的粉色 */
--outline-rgb: 147, 145, 169;
/* #9391A9 - 柔和的中灰紫色 */
/* 深色主题变量 */
--bg-color: #18172a;
/* 更柔和的深蓝紫黑色背景 */
--container-bg: #1c1a2e;
/* 更柔和的深蓝紫色表面 */
--text-color: rgb(var(--on-surface-rgb));
--primary-color: rgb(var(--primary-rgb));
--on-primary: rgb(var(--on-primary-rgb));
--primary-container: rgb(var(--primary-container-rgb));
--on-primary-container: rgb(var(--on-primary-container-rgb));
--secondary-color: rgb(var(--secondary-rgb));
--on-secondary: rgb(var(--on-secondary-rgb));
--secondary-container: rgb(var(--secondary-container-rgb));
--on-secondary-container: rgb(var(--on-secondary-container-rgb));
--user-msg-bg: var(--primary-container);
--user-msg-text: var(--on-primary-container);
--assistant-msg-bg: rgb(var(--surface-variant-rgb));
--assistant-msg-text: rgb(var(--on-surface-variant-rgb));
--system-msg-bg: rgba(var(--on-surface-rgb), 0.08);
--system-msg-text: rgba(var(--on-surface-rgb), 0.7);
--error-color: rgb(var(--error-rgb));
--on-error: rgb(var(--on-error-rgb));
--error-container: rgb(var(--error-container-rgb));
--on-error-container: rgb(var(--on-error-container-rgb));
--border-color: rgba(var(--outline-rgb), 0.6);
--input-bg: rgba(var(--surface-rgb), 0.8);
--input-border: rgba(var(--outline-rgb), 0.3);
--button-hover-bg: rgb(178, 171, 228);
/* 更柔和的淡紫蓝色 */
--sidebar-bg: #201e36;
/* 更柔和的深蓝紫色 */
--log-terminal-bg: #16152c;
/* 更柔和的深蓝紫黑色 */
--log-terminal-text: #d8d7ee;
/* 更柔和的淡紫色文本 */
--log-status-text: #a8a7c8;
/* 日志状态文本 - 深色模式下使用中等亮度的紫色 */
--log-status-error: #ff8aa5;
/* 日志状态错误文本 - 深色模式下的错误颜色 */
--card-shadow: 0 4px 6px rgba(0, 0, 0, 0.25), 0 5px 7px rgba(0, 0, 0, 0.18);
/* 阴影 */
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 2px rgba(161, 153, 219, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.22), 0 2px 4px rgba(161, 153, 219, 0.06);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.25), 0 4px 6px rgba(161, 153, 219, 0.08);
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: 'Noto Sans SC', 'Roboto', sans-serif;
margin: 0;
padding: 0;
display: flex;
height: 100vh;
overflow: hidden;
font-size: 12px;
line-height: 1.6;
transition: background-color var(--transition-speed), color var(--transition-speed);
}
/* --- 工作区布局 --- */
.workspace-container {
display: flex;
width: 100%;
height: 100%;
position: relative;
/* MODIFIED: For #toggleSidebarButton desktop positioning */
}
.chat-panel {
/* flex-grow: 1; Removed, no longer a direct flex child competing for space with sidebar */
width: 100%; /* Takes full width as sidebar is overlay */
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
background-color: var(--container-bg);
transition: background-color var(--transition-speed);
}
/* --- 侧边栏样式改进 --- */
.sidebar-panel {
width: var(--sidebar-width); /* Retain for content & transition */
height: 100%;
display: flex; /* Retain for internal flex layout of its children (log-area) */
flex-direction: column; /* Retain */
overflow: hidden; /* Retain */
background-color: var(--sidebar-bg); /* Retain */
/* border-left removed here, added to :not(.collapsed) */
transition: var(--sidebar-transition), background-color var(--transition-speed); /* Retain */
/* New global styles, moved from @media (max-width: 768px) */
position: fixed;
right: 0;
top: 0;
z-index: 100;
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15); /* New shadow */
transform: translateX(100%); /* Default to collapsed/off-screen */
}
.sidebar-panel:not(.collapsed) { /* When open */
transform: translateX(0%);
border-left: 1px solid var(--sidebar-border); /* Show border when open */
}
.sidebar-panel.collapsed {
/* transform: translateX(100%); */ /* Base .sidebar-panel already has this. */
/* width: var(--sidebar-width); */ /* Base .sidebar-panel already has this. */
padding: 0; /* Consistent with no content shown */
border-left: none; /* No border when slid away */
overflow: hidden; /* Keep from original global .collapsed */
}
/* --- 侧边栏切换按钮 --- */
#toggleSidebarButton {
/* New global styles, moved from @media (max-width: 768px) */
position: fixed;
top: 12px;
/* right: 12px; */ /* Default for floating style - This will be conditional based on sidebar state */
/* left: auto !important; */ /* Crucial to override JS if it tries to set left for old desktop style - Let JS handle this or set based on state */
z-index: 101; /* Higher than sidebar */
/* transform: none; */ /* Reset any desktop transforms if JS applied them - This might be okay, or handled by JS */
/* Retain appearance from original global */
width: 36px;
height: 36px;
border-radius: 50%;
border: 1px solid rgba(var(--outline-rgb), 0.3);
background-color: var(--container-bg);
color: var(--icon-button-color);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
font-size: 1em;
transition: background-color var(--transition-speed), color var(--transition-speed), transform 0.3s ease, box-shadow var(--transition-speed), left 0.3s ease, right 0.3s ease;
box-shadow: var(--shadow-sm);
}
#toggleSidebarButton:hover {
border-color: var(--primary-color);
color: var(--primary-color);
box-shadow: var(--shadow-md);
}
/* --- 标题样式 --- */
h1 {
color: var(--text-color);
text-align: center;
margin: 0;
padding: 16px var(--content-padding);
background-color: var(--container-bg);
font-size: 1.4em;
font-weight: 600;
letter-spacing: -0.5px;
flex-shrink: 0;
border-bottom: 1px solid rgba(var(--outline-rgb), 0.1);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
display: flex;
align-items: center;
justify-content: center;
font-family: 'Noto Sans SC', sans-serif;
}
.logo {
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
color: var(--primary-color);
}
/* Removed .title-separator and .subtitle as title is simpler now */
/* --- 链接样式 --- */
a {
color: var(--primary-color);
text-decoration: none;
font-weight: 500;
transition: color var(--transition-speed);
}
a:hover {
text-decoration: none;
opacity: 0.85;
}
/* --- API密钥管理样式 --- */
.api-key-status {
padding: 12px;
border-radius: var(--border-radius-md);
margin-bottom: 16px;
border: 1px solid var(--border-color);
background-color: var(--input-bg);
}
.api-key-status.success {
background-color: rgba(76, 175, 80, 0.1);
border-color: rgba(76, 175, 80, 0.3);
color: #2e7d32;
}
.api-key-status.error {
background-color: var(--error-container);
border-color: var(--error-color);
color: var(--on-error-container);
}
.api-key-input-group {
margin-bottom: 16px;
}
.api-key-input-container {
display: flex;
gap: 8px;
margin-bottom: 12px;
}
.api-key-input-container input {
flex: 1;
}
.api-key-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.api-key-list {
margin-top: 16px;
}
.api-key-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px;
border: 1px solid var(--border-color);
border-radius: var(--border-radius-md);
margin-bottom: 8px;
background-color: var(--input-bg);
transition: background-color var(--transition-speed);
}
.api-key-item:hover {
background-color: rgba(var(--primary-rgb), 0.05);
}
.api-key-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
}
.api-key-value {
font-family: 'Courier New', monospace;
font-size: 0.9em;
color: var(--text-color);
background-color: rgba(var(--outline-rgb), 0.1);
padding: 4px 8px;
border-radius: 4px;
word-break: break-all;
}
.api-key-meta {
font-size: 0.8em;
color: rgba(var(--on-surface-rgb), 0.7);
}
.api-key-actions-item {
display: flex;
gap: 8px;
}
.icon-button {
background: var(--icon-button-bg);
border: 1px solid var(--border-color);
border-radius: var(--border-radius-sm);
padding: 8px;
cursor: pointer;
color: var(--icon-button-color);
transition: background-color var(--transition-speed), color var(--transition-speed);
display: flex;
align-items: center;
justify-content: center;
}
.icon-button:hover {
background-color: var(--icon-button-hover-bg);
color: var(--primary-color);
}
.icon-button.danger:hover {
background-color: rgba(var(--error-rgb), 0.1);
color: var(--error-color);
}
/* --- 消息样式增强 --- */
#chatbox {
flex-grow: 1;
overflow-y: auto;
padding: var(--content-padding);
display: flex;
flex-direction: column;
gap: 16px;
background-color: var(--bg-color);
transition: background-color var(--transition-speed);
}
.message {
padding: 16px 18px;
border-radius: var(--border-radius-lg);
max-width: 85%;
word-wrap: break-word;
line-height: 1.6;
box-shadow: var(--shadow-sm);
border: 1px solid transparent;
position: relative;
transition: background-color var(--transition-speed), box-shadow var(--transition-speed);
}
.message:hover {
box-shadow: var(--shadow-md);
}
.user-message {
background-color: var(--user-msg-bg);
color: var(--user-msg-text);
align-self: flex-end;
margin-left: auto;
border-radius: var(--border-radius-lg) var(--border-radius-sm) var(--border-radius-lg) var(--border-radius-lg);
border-color: rgba(var(--primary-container-rgb), 0.5);
}
.assistant-message {
background-color: var(--assistant-msg-bg);
color: var(--assistant-msg-text);
align-self: flex-start;
margin-right: auto;
white-space: pre-wrap;
border-radius: var(--border-radius-sm) var(--border-radius-lg) var(--border-radius-lg) var(--border-radius-lg);
border-color: rgba(var(--surface-variant-rgb), 0.5);
}
.system-message {
color: var(--system-msg-text);
font-size: 0.92em;
text-align: center;
padding: 10px 14px;
margin: 8px auto;
max-width: 80%;
background-color: var(--system-msg-bg);
border-radius: var(--border-radius-md);
border: 1px solid rgba(var(--outline-rgb), 0.2);
box-shadow: none;
}
.error-message {
background-color: var(--error-container);
color: var(--on-error-container);
align-self: stretch;
text-align: center;
padding: 12px 18px;
border-radius: var(--border-radius-md);
margin: 10px 5%;
box-shadow: none;
border: 1px solid rgba(var(--error-rgb), 0.2);
}
/* --- 输入区域样式增强 --- */
#input-area {
display: flex;
padding: 12px var(--content-padding);
border-top: 1px solid rgba(var(--outline-rgb), 0.1);
flex-shrink: 0;
gap: 10px;
align-items: flex-end;
background-color: var(--container-bg);
flex-wrap: wrap;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.02);
transition: background-color var(--transition-speed);
}
/* 模型选择器样式 */
.model-selector-container {
flex-basis: 100%;
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
}
.model-selector-label {
flex-shrink: 0;
font-size: 0.9em;
color: var(--text-color);
opacity: 0.85;
}
#modelSelector {
flex-grow: 1;
padding: 8px 12px;
border-radius: var(--border-radius-md);
background-color: var(--input-bg);
color: var(--text-color);
border: 1px solid var(--input-border);
font-family: inherit;
font-size: 0.9em;
outline: none;
transition: border-color var(--transition-speed), box-shadow var(--transition-speed);
}
#modelSelector:focus {
border-color: var(--input-focus-border);
box-shadow: var(--input-focus-shadow);
}
#modelSelector option {
background-color: var(--input-bg);
color: var(--text-color);
}
#refreshModelsButton {
background-color: rgba(var(--primary-rgb), 0.1);
color: var(--primary-color);
border: none;
padding: 8px 12px;
border-radius: var(--border-radius-md);
cursor: pointer;
font-size: 0.9em;
transition: background-color var(--transition-speed);
}
#refreshModelsButton:hover {
background-color: rgba(var(--primary-rgb), 0.15);
}
#userInput {
flex-grow: 1;
flex-basis: 300px;
padding: 14px 18px;
background-color: var(--input-bg);
color: var(--text-color);
border: 1px solid var(--input-border);
border-radius: var(--border-radius-xl);
resize: none;
font-family: inherit;
font-size: 1em;
min-height: 48px;
max-height: 200px;
overflow-y: auto;
line-height: 1.5;
outline: none;
box-shadow: var(--shadow-sm);
transition: border-color var(--transition-speed), box-shadow var(--transition-speed), background-color var(--transition-speed);
min-width: 180px;
/* MODIFIED: Prevents excessive shrinking before wrap */
}
#userInput:focus {
border-color: var(--input-focus-border);
box-shadow: var(--input-focus-shadow);
}
/* --- 按钮样式增强 --- */
.action-button {
padding: 12px 24px;
border: none;
border-radius: var(--border-radius-xl);
cursor: pointer;
font-family: inherit;
font-size: 0.95em;
font-weight: 500;
transition: background-color var(--transition-speed), transform 0.1s, box-shadow var(--transition-speed), opacity var(--transition-speed);
line-height: 1.5;
height: 48px;
align-self: flex-end;
box-shadow: var(--shadow-sm);
flex-shrink: 0;
letter-spacing: 0.3px;
}
.action-button:disabled {
cursor: not-allowed;
box-shadow: none;
background-color: var(--button-disabled-bg);
color: var(--button-disabled-text);
transform: none;
opacity: 0.7;
}
.action-button:hover:not(:disabled) {
box-shadow: var(--shadow-md);
transform: translateY(-1px);
opacity: 0.95;
}
.action-button:active:not(:disabled) {
transform: translateY(0px);
box-shadow: var(--shadow-sm);
}
#sendButton {
background-color: var(--button-bg);
color: var(--button-text);
}
#sendButton:hover:not(:disabled) {
background-color: var(--button-hover-bg);
}
#clearButton {
background-color: var(--clear-button-bg);
color: var(--clear-button-text);
order: 1;
/* Default order: Send, Clear */
}
#clearButton:hover:not(:disabled) {
background-color: var(--clear-button-hover-bg);
}
/* --- 图标按钮样式 --- */
.icon-button {
background-color: var(--icon-button-bg);
color: var(--icon-button-color);
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 1.2em;
transition: background-color var(--transition-speed), color var(--transition-speed);
flex-shrink: 0;
}
.icon-button:hover:not(:disabled) {
background-color: var(--icon-button-hover-bg);
color: var(--primary-color);
}
.icon-button:disabled {
color: var(--button-disabled-text);
cursor: not-allowed;
background-color: transparent;
opacity: 0.5;
}
/* --- 服务器信息视图增强 --- */
#server-info-view {
display: none;
/* Initially hidden */
flex-direction: column;
/* MODIFIED: To ensure content flows correctly */
padding: var(--content-padding);
overflow-y: auto;
height: 100%;
background-color: var(--bg-color);
transition: background-color var(--transition-speed);
}
.server-info-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid rgba(var(--outline-rgb), 0.2);
flex-shrink: 0;
/* MODIFIED */
}
.server-info-header h3 {
margin: 0;
font-size: 1.25em;
font-weight: 600;
color: var(--text-color);
}
#refreshServerInfoButton {
background-color: rgba(var(--primary-rgb), 0.1);
color: var(--primary-color);
border-radius: var(--border-radius-md);
padding: 8px 16px;
font-size: 0.9em;
font-weight: 500;
border: none;
cursor: pointer;
transition: background-color var(--transition-speed);
}
#refreshServerInfoButton:hover {
background-color: rgba(var(--primary-rgb), 0.15);
}
.info-card {
background-color: var(--card-bg);
border-radius: var(--border-radius-lg);
padding: 20px;
margin-bottom: 24px;
box-shadow: var(--shadow-sm);
border: 1px solid var(--card-border);
transition: box-shadow var(--transition-speed), background-color var(--transition-speed);
flex-shrink: 0;
/* MODIFIED */
}
.info-card:hover {
box-shadow: var(--shadow-md);
}
.info-card h3 {
margin-top: 0;
margin-bottom: 16px;
font-size: 1.1em;
font-weight: 600;
color: var(--text-color);
padding-bottom: 10px;
border-bottom: 1px solid rgba(var(--outline-rgb), 0.1);
}
#api-info-content,
#health-status-display {
font-size: 0.95em;
}
.info-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.info-list div {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 8px 0;
border-bottom: 1px solid rgba(var(--outline-rgb), 0.08);
}
.info-list div:last-child {
border-bottom: none;
}
.info-list strong {
min-width: 140px;
color: var(--primary-color);
font-weight: 500;
}
/* --- 导航样式增强 --- */
.main-nav {
display: flex;
padding: 12px var(--content-padding) 12px;
background-color: var(--container-bg);
border-bottom: 1px solid rgba(var(--outline-rgb), 0.1);
gap: 12px;
align-items: center;
transition: background-color var(--transition-speed);
flex-shrink: 0;
/* MODIFIED */
}
.nav-button {
padding: 8px 16px;
border: none;
background-color: transparent;
color: var(--text-color);
cursor: pointer;
border-radius: var(--border-radius-md);
font-weight: 500;
transition: background-color var(--transition-speed), color var(--transition-speed), box-shadow var(--transition-speed);
line-height: 1.5;
letter-spacing: 0.2px;
display: flex;
align-items: center;
gap: 8px;
font-family: 'Noto Sans SC', sans-serif;
}
.nav-icon {
opacity: 0.8;
}
.nav-button:hover:not(.active) {
background-color: rgba(var(--primary-rgb), 0.05);
}
.nav-button.active {
color: var(--on-primary-container);
font-weight: 600;
background-color: var(--primary-container);
box-shadow: var(--shadow-sm);
}
.nav-button.active .nav-icon {
opacity: 1;
}
/* --- 主题切换按钮增强 --- */
#themeToggleButton {
background-color: var(--theme-toggle-bg);
border: 1px solid rgba(var(--outline-rgb), 0.3);
color: var(--theme-toggle-color);
cursor: pointer;
font-size: 0.9em;
font-weight: 500;
padding: 6px 6px;
border-radius: var(--border-radius-xl);
transition: background-color var(--transition-speed), color var(--transition-speed), border-color var(--transition-speed);
margin-left: auto;
align-self: center;
white-space: nowrap;
display: flex;
align-items: center;
gap: 6px;
}
#themeToggleButton:hover {
background-color: var(--theme-toggle-hover-bg);
border-color: var(--primary-color);
}
#themeToggleButton .theme-icon {
width: 16px;
height: 16px;
}
html:not(.dark-mode) #darkModeIcon {
display: block;
}
html:not(.dark-mode) #lightModeIcon {
display: none;
}
html.dark-mode #darkModeIcon {
display: none;
}
html.dark-mode #lightModeIcon {
display: block;
}
/* --- 日志区域样式增强 --- */
#log-area {
flex-grow: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 0;
border-top: none;
background-color: var(--sidebar-bg);
transition: background-color var(--transition-speed);
}
#log-area-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px var(--content-padding);
font-weight: 600;
color: var(--text-color);
flex-shrink: 0;
border-bottom: 1px solid rgba(var(--outline-rgb), 0.2);
background-color: var(--container-bg);
transition: background-color var(--transition-speed);
}
#clearLogButton {
margin-left: 10px;
font-size: 0.85em;
padding: 6px 12px;
height: auto;
line-height: 1.4;
border-radius: var(--border-radius-md);
background-color: rgba(var(--secondary-rgb), 0.1);
color: var(--secondary-color);
}
#clearLogButton:hover:not(:disabled) {
background-color: rgba(var(--secondary-rgb), 0.15);
color: var(--secondary-color);
}
#log-terminal-wrapper {
flex-grow: 1;
overflow: hidden;
border: none;
border-radius: 0;
margin: 0;
padding: 0;
background-color: var(--log-terminal-bg);
}
#log-terminal {
height: 100%;
background-color: var(--log-terminal-bg);
color: var(--log-terminal-text);
font-family: "JetBrains Mono", "Cascadia Code", "Fira Code", Consolas, monospace;
font-size: 0.85em;
padding: 12px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
box-sizing: border-box;
}
.log-entry {
margin-bottom: 4px;
line-height: 1.4;
}
.log-status {
font-size: 0.85em;
margin-top: 0;
padding: 10px;
color: var(--log-status-text);
/* 使用主题相关的变量 */
flex-shrink: 0;
background-color: var(--log-terminal-bg);
border-top: 1px solid rgba(var(--outline-rgb), 0.3);
text-align: center;
}
.log-status.error-status {
color: var(--log-status-error);
}
/* --- View Container for Chat/Server Info --- */
.view-container {
flex-grow: 1;
overflow: hidden;
display: flex;
/* To manage child view visibility */
flex-direction: column;
/* Children stack, only one visible */
}
#chat-view {
display: flex;
/* Default visible view */
flex-direction: column;
height: 100%;
overflow: hidden;
}
/* --- 代码块样式增强 --- */
.message pre {
background-color: rgba(0, 0, 0, 0.04);
border: 1px solid rgba(var(--outline-rgb), 0.2);
border-radius: var(--border-radius-sm);
padding: 12px 16px;
margin: 12px 0;
overflow-x: auto;
font-family: "JetBrains Mono", "Cascadia Code", "Fira Code", Consolas, monospace;
font-size: 0.9em;
}
.message code:not(pre > code) {
background-color: rgba(var(--primary-rgb), 0.08);
padding: 2px 5px;
border-radius: 4px;
font-family: "JetBrains Mono", "Cascadia Code", "Fira Code", Consolas, monospace;
font-size: 0.9em;
color: var(--primary-color);
}
html.dark-mode .message pre {
background-color: rgba(255, 255, 255, 0.03);
border-color: rgba(255, 255, 255, 0.1);
}
html.dark-mode .message code:not(pre > code) {
background-color: rgba(var(--primary-rgb), 0.15);
}
/* --- 响应式增强 --- */
@media (max-width: 768px) {
#userInput {
min-height: 44px;
flex-grow: 1;
/* ADDED */
flex-basis: 0;
/* ADDED */
min-width: 120px;
/* ADDED/ADJUSTED */
}
.action-button {
padding: 10px 16px;
height: 44px;
font-size: 0.95em;
}
.message {
max-width: 90%;
}
h1 {
font-size: 1.2em;
padding: 14px 16px;
}
.info-card {
padding: 16px;
}
}
@media (max-width: 280px) {
body {
font-size: 12px;
}
#chatbox {
gap: 12px;
padding: 12px;
}
.message {
padding: 12px 14px;
}
.action-button {
width: 100%;
margin-bottom: 4px;
}
#clearButton {
order: 0;
/* Clear button first on small screens */
}
#sendButton {
order: 1;
/* Send button second */
}
.main-nav {
padding: 8px 12px;
flex-wrap: wrap;
/* Allow nav buttons to wrap if too many/long */
}
.nav-button {
padding: 6px 12px;
font-size: 0.9em;
}
#themeToggleButton {
/* Ensure theme toggle doesn't cause overflow */
margin-left: auto;
flex-shrink: 0;
}
.info-card {
padding: 12px;
margin-bottom: 16px;
}
.info-list strong {
min-width: 100%;
/* Stack key/value on small screens */
margin-bottom: 4px;
display: block;
}
.info-list div {
flex-direction: column;
align-items: flex-start;
}
}
/* --- 闪烁光标动画 --- */
.assistant-message.streaming::after {
content: '|';
animation: blink 1s step-end infinite;
margin-left: 2px;
display: inline-block;
font-weight: bold;
position: relative;
top: -1px;
opacity: 0.7;
}
@keyframes blink {
from,
to {
opacity: 0.7;
}
50% {
opacity: 0;
}
}
/* --- 加载指示器样式 --- */
.loading-indicator {
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
color: var(--system-msg-text);
flex-direction: column;
gap: 12px;
}
.loading-spinner {
width: 24px;
height: 24px;
border: 3px solid rgba(var(--primary-rgb), 0.3);
border-radius: 50%;
border-top-color: var(--primary-color);
animation: spin 1s ease-in-out infinite;
margin-bottom: 8px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* --- 卡片内容动画 --- */
.info-card {
animation: fadeIn 0.3s ease-out;
/* Duplicates from above, ensure consistency or remove if redundant */
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* --- 美化信息列表 --- */
.info-list {
background-color: rgba(var(--surface-rgb), 0.5);
border-radius: var(--border-radius-md);
overflow: hidden;
}
.info-list div {
padding: 10px 16px;
transition: background-color var(--transition-speed);
/* display, flex-wrap, gap, border-bottom already defined */
}
.info-list div:last-child {
border-bottom: none;
}
.info-list div:hover {
background-color: rgba(var(--primary-rgb), 0.03);
}
/* info-list strong already defined */
/* --- 代码标签增强 --- */
code {
/* General code tag style, distinct from .message code */
font-family: "JetBrains Mono", "Cascadia Code", "Fira Code", Consolas, monospace;
background-color: rgba(var(--on-surface-rgb), 0.05);
/* More neutral for general code */
padding: 2px 6px;
border-radius: 4px;
font-size: 0.9em;
color: var(--on-surface-variant-rgb);
}
html.dark-mode code {
background-color: rgba(var(--on-surface-rgb), 0.1);
}
/* --- 按钮动画增强 --- */
.action-button {
position: relative;
overflow: hidden;
}
.action-button:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 5px;
height: 5px;
background: rgba(255, 255, 255, 0.4);
opacity: 0;
border-radius: 100%;
transform: scale(1, 1) translate(-50%);
transform-origin: 50% 50%;
}
.action-button:focus:not(:active)::after {
animation: ripple 1s ease-out;
}
@keyframes ripple {
0% {
transform: scale(0, 0);
opacity: 0.5;
}
20% {
transform: scale(25, 25);
opacity: 0.3;
}
100% {
opacity: 0;
transform: scale(40, 40);
}
}
/* --- 聊天区域滚动条美化 --- */
#chatbox::-webkit-scrollbar,
#log-terminal::-webkit-scrollbar,
/* Apply to log terminal too */
#server-info-view::-webkit-scrollbar
/* And server info view */
{
width: 8px;
}
#chatbox::-webkit-scrollbar-track,
#log-terminal::-webkit-scrollbar-track,
#server-info-view::-webkit-scrollbar-track {
background: transparent;
}
#chatbox::-webkit-scrollbar-thumb,
#log-terminal::-webkit-scrollbar-thumb,
#server-info-view::-webkit-scrollbar-thumb {
background-color: rgba(var(--outline-rgb), 0.2);
border-radius: 20px;
}
/* Add border to scrollbar thumb for better visibility against content */
#chatbox::-webkit-scrollbar-thumb {
border: 2px solid var(--bg-color);
}
#log-terminal::-webkit-scrollbar-thumb {
border: 2px solid var(--log-terminal-bg);
}
#server-info-view::-webkit-scrollbar-thumb {
border: 2px solid var(--bg-color);
}
#chatbox::-webkit-scrollbar-thumb:hover,
#log-terminal::-webkit-scrollbar-thumb:hover,
#server-info-view::-webkit-scrollbar-thumb:hover {
background-color: rgba(var(--outline-rgb), 0.3);
}
/* --- 用户输入框滚动条 --- */
#userInput::-webkit-scrollbar {
width: 6px;
}
#userInput::-webkit-scrollbar-track {
background: transparent;
}
#userInput::-webkit-scrollbar-thumb {
background-color: rgba(var(--outline-rgb), 0.2);
border-radius: 10px;
border: 2px solid var(--input-bg);
}
#userInput::-webkit-scrollbar-thumb:hover {
background-color: rgba(var(--outline-rgb), 0.3);
}
/* --- 加强主题切换按钮样式 --- */
#themeToggleButton {
display: flex;
align-items: center;
gap: 6px;
position: relative;
}
/* 删除之前使用emoji的样式,使用SVG图标替代 */
/* --- 模型设置页面样式 --- */
#model-settings-view {
display: none;
/* Initially hidden */
flex-direction: column;
padding: var(--content-padding);
overflow-y: auto;
height: 100%;
background-color: var(--bg-color);
transition: background-color var(--transition-speed);
}
.settings-group {
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid rgba(var(--outline-rgb), 0.1);
}
.settings-group:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.settings-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: var(--text-color);
}
.settings-description {
font-size: 0.85em;
color: rgba(var(--on-surface-rgb), 0.7);
margin-top: 8px;
line-height: 1.4;
}
.settings-slider-container {
display: flex;
align-items: center;
gap: 12px;
}
.settings-slider {
flex-grow: 1;
height: 6px;
-webkit-appearance: none;
appearance: none;
background: rgba(var(--outline-rgb), 0.2);
border-radius: 3px;
outline: none;
}
.settings-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--primary-color);
cursor: pointer;
transition: background-color var(--transition-speed);
}
.settings-slider::-moz-range-thumb {
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--primary-color);
cursor: pointer;
transition: background-color var(--transition-speed);
border: none;
}
.settings-number {
width: 60px;
padding: 6px 8px;
border-radius: var(--border-radius-md);
border: 1px solid var(--input-border);
background-color: var(--input-bg);
color: var(--text-color);
font-family: inherit;
font-size: 0.9em;
text-align: center;
}
.settings-textarea {
width: 100%;
min-height: 100px;
padding: 12px;
border-radius: var(--border-radius-md);
border: 1px solid var(--input-border);
background-color: var(--input-bg);
color: var(--text-color);
font-family: inherit;
font-size: 0.95em;
resize: vertical;
transition: border-color var(--transition-speed);
}
.settings-textarea:focus,
.settings-number:focus,
.settings-input:focus {
outline: none;
border-color: var(--input-focus-border);
box-shadow: var(--input-focus-shadow);
}
.settings-input {
width: 100%;
padding: 10px 12px;
border-radius: var(--border-radius-md);
border: 1px solid var(--input-border);
background-color: var(--input-bg);
color: var(--text-color);
font-family: inherit;
font-size: 0.95em;
}
.settings-status {
text-align: center;
color: rgba(var(--on-surface-rgb), 0.8);
margin-bottom: 15px;
font-size: 0.9em;
}
.full-width-button {
width: 100%;
margin-top: 10px;
}