PicoBot/web/src/index.css
oudecheng eaee29841d feat(web): 对齐 deepseek-harness 设计语言,重构前端视觉与三栏布局
- 设计 token 重映射为 DeepSeek 调色板(深浅双主题),正文改无衬线字体栈,全面去霓虹化
- 移除顶部 Header,控件迁入左栏(Logo/连接/通道/会话/tabs/底部操作区),左右栏支持拖拽调宽并持久化,折叠为图标 rail
- 对话区对齐 DeepSeek 聊天风:hero/docked 状态机、736px 居中列、用户右对齐柔和气泡、助手无气泡平铺、composer 卡片与反差发送键;子智能体点击导航完整保留
- 全功能区同步换肤:侧栏列表、右栏面板、ConfigPage、弹窗、选择器等
- fix: 修复 virtual-core 3.17.x 陈旧行高导致消息行重叠(宽度变化/滚动停止后强制 resizeItem 重测)
- fix: 修复 ConfigPage/Modal 引用不存在的 fadeIn/scaleIn keyframes 致入场动画失效
2026-08-14 19:15:45 +08:00

476 lines
10 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@import 'tailwindcss';
/* ============================================
PicoBot Theme — Dark (default)
对齐 deepseek-harness 设计语言
--accent-cyan 语义为品牌主色 DeepSeek blue
============================================ */
:root {
/* Core colors */
--bg-primary: rgb(35, 35, 36);
--bg-secondary: rgb(27, 27, 28);
--bg-tertiary: rgb(44, 44, 46);
--bg-hover: rgba(255, 255, 255, 0.08);
/* Accent colors */
--accent-cyan: rgb(103, 158, 254);
--accent-blue: rgb(96, 165, 250);
--accent-purple: rgb(183, 200, 254);
--accent-green: rgb(78, 209, 126);
--accent-amber: rgb(247, 173, 49);
/* Text colors */
--text-primary: rgb(249, 250, 251);
--text-secondary: rgb(207, 211, 214);
--text-muted: rgb(151, 157, 166);
--text-accent: var(--accent-cyan);
/* Border */
--border-color: rgba(255, 255, 255, 0.12);
--border-accent: rgba(103, 158, 254, 0.4);
/* Overlay — for hover / subtle surface effects */
--overlay-hover: rgba(255, 255, 255, 0.08);
--overlay-subtle: rgba(255, 255, 255, 0.14);
--overlay-medium: rgba(255, 255, 255, 0.24);
--overlay-dim: rgba(0, 0, 0, 0.2);
--overlay-dim-strong: rgba(0, 0, 0, 0.3);
--overlay-dim-heavy: rgba(0, 0, 0, 0.4);
--overlay-code: rgba(0, 0, 0, 0.3);
/* Shadows */
--shadow-glow-sm: rgba(103, 158, 254, 0.1);
--shadow-glow: rgba(103, 158, 254, 0.16);
--shadow-glow-strong: rgba(103, 158, 254, 0.24);
--shadow-glow-soft: rgba(103, 158, 254, 0.32);
/* Focus ring */
--focus-ring: rgba(103, 158, 254, 0.3);
/* Selection / code highlight */
--selection-bg: rgba(103, 158, 254, 0.28);
/* Divider */
--divider-color: rgba(255, 255, 255, 0.08);
/* Chat composer / user bubble surfaces */
--bubble-user: rgb(44, 44, 46);
--surface-input: rgb(44, 44, 46);
--btn-contrast: rgb(249, 250, 251);
--btn-contrast-fg: rgb(27, 27, 28);
color-scheme: dark;
}
/* ============================================
PicoBot Theme — Light
============================================ */
html.light {
/* Backgrounds */
--bg-primary: rgb(255, 255, 255);
--bg-secondary: rgb(249, 250, 251);
--bg-tertiary: rgb(241, 243, 245);
--bg-hover: rgba(38, 49, 72, 0.06);
/* Accents */
--accent-cyan: rgb(65, 118, 230);
--accent-blue: rgb(59, 130, 246);
--accent-purple: rgb(65, 118, 230);
--accent-green: rgb(34, 197, 94);
--accent-amber: rgb(245, 158, 11);
/* Text */
--text-primary: rgb(15, 17, 21);
--text-secondary: rgb(97, 102, 107);
--text-muted: rgb(151, 157, 166);
--text-accent: var(--accent-cyan);
/* Borders */
--border-color: rgba(0, 0, 0, 0.1);
--border-accent: rgba(65, 118, 230, 0.4);
/* Overlays */
--overlay-hover: rgba(38, 49, 72, 0.06);
--overlay-subtle: rgba(38, 49, 72, 0.1);
--overlay-medium: rgba(38, 49, 72, 0.16);
--overlay-dim: rgba(0, 0, 0, 0.04);
--overlay-dim-strong: rgba(0, 0, 0, 0.06);
--overlay-dim-heavy: rgba(0, 0, 0, 0.08);
--overlay-code: rgba(0, 0, 0, 0.06);
/* Shadows — softer */
--shadow-glow-sm: rgba(65, 118, 230, 0.08);
--shadow-glow: rgba(65, 118, 230, 0.12);
--shadow-glow-strong: rgba(65, 118, 230, 0.18);
--shadow-glow-soft: rgba(65, 118, 230, 0.25);
/* Focus ring */
--focus-ring: rgba(65, 118, 230, 0.25);
/* Selection / code highlight */
--selection-bg: rgba(65, 118, 230, 0.2);
/* Divider */
--divider-color: rgba(0, 0, 0, 0.08);
/* Chat composer / user bubble surfaces */
--bubble-user: rgb(237, 243, 254);
--surface-input: rgb(255, 255, 255);
--btn-contrast: rgb(67, 69, 74);
--btn-contrast-fg: rgb(255, 255, 255);
color-scheme: light;
}
/* ============================================
Smooth theme transition
============================================ */
html.theme-transitioning *,
html.theme-transitioning *::before,
html.theme-transitioning *::after {
transition:
background-color 0.3s ease,
color 0.3s ease,
border-color 0.3s ease,
box-shadow 0.3s ease,
text-shadow 0.3s ease !important;
}
/* 虚拟列表行使用内联 transform 定位,主题过渡期间禁止对其做 transition避免行位移被动画化 */
html.theme-transitioning [data-index] {
transition: none !important;
}
/* ============================================
Custom scrollbar
============================================ */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: var(--bg-secondary);
}
::-webkit-scrollbar-thumb {
background: rgb(101, 103, 107);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: rgb(129, 133, 140);
}
html.light ::-webkit-scrollbar-thumb {
background: rgb(229, 229, 229);
}
html.light ::-webkit-scrollbar-thumb:hover {
background: rgb(212, 212, 212);
}
/* Hide scrollbar utility */
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
/* ============================================
Base styles
============================================ */
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family:
-apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto,
'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
font-size: 15px;
}
/* ============================================
Custom selection
============================================ */
::selection {
background: var(--selection-bg);
color: var(--text-primary);
}
/* ============================================
Glowing text effectDeepSeek 风格下仅保留品牌色,无发光)
============================================ */
.glow-text {
color: var(--accent-cyan);
}
/* ============================================
Gradient border
============================================ */
.gradient-border {
position: relative;
}
.gradient-border::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
background: var(--accent-cyan);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
/* ============================================
Animations
============================================ */
@keyframes pulse-glow {
0%,
100% {
box-shadow: 0 0 0 1px var(--shadow-glow);
}
50% {
box-shadow: 0 0 0 3px var(--shadow-glow);
}
}
@keyframes slide-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes typing-dot {
0%,
60%,
100% {
transform: translateY(0);
}
30% {
transform: translateY(-4px);
}
}
@keyframes scale-in {
0% {
opacity: 0;
transform: scale(0.5);
}
50% {
transform: scale(1.1);
}
100% {
opacity: 1;
transform: scale(1);
}
}
.animate-slide-in {
animation: slide-in 0.3s ease-out;
}
.animate-fade-in {
animation: fade-in 0.2s ease-out;
}
.animate-scale-in {
animation: scale-in 0.3s ease-out;
}
/* ============================================
TodoPanel animations
============================================ */
@keyframes todo-card-in {
from {
opacity: 0;
transform: scale(0.92) translateY(-8px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
@keyframes todo-item-in {
from {
opacity: 0;
transform: translateX(-6px);
max-height: 0;
}
to {
opacity: 1;
transform: translateX(0);
max-height: 40px;
}
}
@keyframes todo-ring-pulse {
0%,
100% {
box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.4);
}
50% {
box-shadow: 0 0 0 6px rgba(245, 158, 11, 0);
}
}
@keyframes todo-highlight-pulse {
0%,
100% {
background-color: transparent;
}
50% {
background-color: color-mix(in srgb, var(--accent-cyan) 15%, transparent);
}
}
.animate-todo-card-in {
animation: todo-card-in 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.animate-todo-item-in {
animation: todo-item-in 0.2s ease-out forwards;
}
.animate-todo-ring-pulse {
animation: todo-ring-pulse 2s ease-in-out infinite;
}
/* 待办点击高亮效果 */
.todo-highlight {
animation: todo-highlight-pulse 1s ease-in-out 2;
border-radius: 8px;
}
/* 分组折叠内容展开/收起 */
.todo-group-body {
overflow: hidden;
transition:
max-height 0.25s ease,
opacity 0.2s ease;
}
.todo-group-body-open {
max-height: 600px;
opacity: 1;
}
.todo-group-body-closed {
max-height: 0;
opacity: 0;
}
@keyframes thinking-reveal {
from {
max-height: 0;
opacity: 0;
}
to {
max-height: 300px;
opacity: 1;
}
}
.animate-thinking-reveal {
animation: thinking-reveal 0.25s ease-out;
}
.typing-indicator span {
animation: typing-dot 1.4s infinite;
display: inline-block;
}
.typing-indicator span:nth-child(2) {
animation-delay: 0.2s;
}
.typing-indicator span:nth-child(3) {
animation-delay: 0.4s;
}
/* ============================================
Markdown list — kill extra spacing from loose-list <p> wrappers
list-inside + block <p> pushes marker and content apart.
Use list-outside so the marker sits outside the <p> flow.
============================================ */
.markdown-content li > p {
margin: 0;
}
/* ============================================
Code block styling
============================================ */
pre {
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 12px;
overflow-x: auto;
}
code {
font-family: 'SF Mono', 'Fira Code', 'JetBrains Mono', monospace;
font-size: 0.9em;
}
/* ============================================
Focus styles
============================================ */
input:focus,
textarea:focus {
outline: none;
border-color: var(--accent-cyan);
box-shadow: 0 0 0 2px var(--focus-ring);
}
/* Composer 内的无边框 textarea聚焦高亮由外层卡片 focus-within 提供 */
textarea.composer-area:focus {
border-color: transparent;
box-shadow: none;
}
/* ============================================
Button hover effects
============================================ */
button {
transition: all 0.2s ease;
}
/* ============================================
Link styles
============================================ */
a {
color: var(--accent-cyan);
text-decoration: none;
transition: all 0.2s;
}
a:hover {
opacity: 0.85;
}