zcbot/web/static/ui.css

590 lines
9.8 KiB
CSS

/*
* zcbot UI foundation
*
* The application intentionally stays build-free. This file is the shared
* visual layer for the main SPA: tokens, control states and restrained
* workspace polish. Feature-specific layout remains next to dev.html until
* it is reused by a second surface.
*/
:root {
color-scheme: light;
/* Neutral workspace palette */
--bg: #f3f5f7;
--panel: #ffffff;
--panel-subtle: #f8f9fb;
--panel-muted: #f4f6f8;
--border: #dde2e7;
--border-soft: #e9edf1;
--text: #20242a;
--text-strong: #15181d;
--muted: #6f7782;
/* Institute red is deliberately reserved for primary emphasis. */
--accent: #b83a31;
--accent-hover: #a9322a;
--accent-soft: #fbecea;
--accent-ring: rgba(184, 58, 49, 0.16);
--hover: #f0f3f5;
--code-bg: #f3f5f7;
--user-bg: #f1f5fa;
--asst-bg: #ffffff;
--c-green: #238653;
--c-green-bg: #eaf6ef;
--c-green-bd: #a9d9bd;
--c-blue: #2d6f9f;
--c-blue-bg: #edf5fa;
--c-blue-bd: #b5d5e7;
--c-purple: #7c5192;
--c-purple-bg: #f5eff8;
--c-purple-bd: #d8c4e1;
--c-orange: #bf6a20;
--c-orange-bg: #fdf3e8;
--c-orange-bd: #ebc79f;
--c-red: #b83a31;
--c-red-bg: #fbecea;
--c-red-bd: #e7b3ae;
/* One compact radius and spacing vocabulary. */
--r-sm: 4px;
--r-md: 6px;
--r-lg: 8px;
--r-xl: 10px;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 24px;
--space-6: 32px;
--shadow-float: 0 10px 30px rgba(24, 32, 41, 0.12);
--shadow-card: 0 18px 48px rgba(24, 32, 41, 0.16);
--shadow-card-lg:
0 24px 72px rgba(24, 32, 41, 0.14),
0 2px 8px rgba(24, 32, 41, 0.06);
--mono: ui-monospace, "Cascadia Code", "SF Mono", Consolas, monospace;
--t: background-color 0.15s ease, border-color 0.15s ease,
color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
body {
font-size: 14px;
line-height: 1.55;
color: var(--text);
background: var(--bg);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
button,
input,
textarea,
select {
transition: var(--t);
}
button {
min-height: 32px;
padding: 5px 11px;
font-weight: 500;
}
button.small {
min-height: 28px;
}
button:hover:not(:disabled) {
border-color: #cbd2d9;
}
button.primary {
background: var(--accent);
border-color: var(--accent);
box-shadow: 0 1px 2px rgba(73, 25, 21, 0.16);
}
button.primary:hover:not(:disabled) {
background: var(--accent-hover);
border-color: var(--accent-hover);
filter: none;
}
button:disabled {
opacity: 0.46;
}
button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
textarea,
select {
min-height: 34px;
border-color: var(--border);
}
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):hover,
textarea:hover,
select:hover {
border-color: #c7ced5;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):focus,
textarea:focus,
select:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-ring);
}
::placeholder {
color: #9aa1aa;
}
/* Application shell */
#app.ready {
background: var(--bg);
}
header {
min-height: 48px;
padding: 9px 16px;
border-bottom-color: var(--border);
box-shadow: 0 1px 0 rgba(24, 32, 41, 0.02);
}
header .brand {
gap: 10px;
}
header .brand .logo {
width: 26px;
height: 26px;
box-shadow: 0 2px 8px rgba(184, 58, 49, 0.2);
}
header .title {
color: var(--text-strong);
font-size: 15px;
letter-spacing: 0.1px;
}
header .who {
color: var(--muted);
}
.pane {
border-color: var(--border);
}
#pane-left,
#pane-right {
background: var(--panel-subtle);
}
#pane-mid {
background: var(--panel);
}
.splitter {
background: var(--bg);
}
.splitter::before {
background: #d7dde3;
}
.pane-head {
min-height: 44px;
padding: 8px 12px;
background: rgba(248, 249, 251, 0.96);
border-bottom-color: var(--border-soft);
}
.pane-head .label {
color: var(--text-strong);
font-size: 13px;
letter-spacing: 0.2px;
}
#pane-left .pane-head + .pane-head {
background: var(--panel);
}
#task-scroll,
#file-list {
scrollbar-color: #cbd1d7 transparent;
scrollbar-width: thin;
}
/* Task and resource navigation */
#channel-cards {
padding: 8px 10px 4px;
}
.channel-card {
border-color: rgba(7, 158, 82, 0.26);
background: rgba(7, 158, 82, 0.045);
}
#task-list {
padding: 4px 8px 8px;
}
.task-row {
margin: 3px 0;
padding: 9px 10px;
border: 1px solid transparent;
border-radius: var(--r-md);
}
.task-row:hover {
background: var(--panel);
border-color: var(--border-soft);
box-shadow: 0 1px 3px rgba(24, 32, 41, 0.04);
}
.task-row.active {
padding-left: 8px;
background: var(--accent-soft);
border-color: #f0d2cf;
border-left: 3px solid var(--accent);
box-shadow: none;
}
.task-row .desc {
color: var(--text-strong);
}
.task-row .meta {
color: var(--muted);
}
.task-row .badge,
.sk-badge {
border-radius: var(--r-sm);
}
#rail-resources {
padding: 8px;
border-top-color: var(--border-soft);
background: var(--panel);
}
#rail-resources > button {
min-height: 48px;
border-color: transparent;
color: #59616b;
background: transparent;
}
#rail-resources > button:hover {
color: var(--accent);
border-color: #f0d2cf;
background: var(--accent-soft);
}
/* Menus and lightweight cards */
#floating-menu,
#media-model-pop {
border-color: var(--border);
border-radius: var(--r-lg);
box-shadow: var(--shadow-float);
}
.dd-item {
padding: 7px 14px;
}
.dd-item:hover {
background: var(--panel-muted);
}
.sk-item {
padding: 9px 10px;
border-color: var(--border-soft);
background: var(--panel);
}
.sk-item:hover {
border-color: #d2a09b;
background: var(--accent-soft);
}
.sk-item.active {
border-color: var(--accent);
background: var(--accent-soft);
}
.empty,
.sk-empty {
color: var(--muted);
line-height: 1.7;
}
/* Conversation: assistant content reads like a document, not a bubble stack. */
#chat-meta {
min-height: 40px;
padding: 8px 16px;
background: var(--panel);
border-bottom-color: var(--border-soft);
}
#chat-stream {
gap: 14px;
padding: 20px clamp(16px, 3vw, 36px) 24px;
background: var(--panel);
scrollbar-color: #cbd1d7 transparent;
scrollbar-width: thin;
}
.msg {
padding: 10px 13px;
border-color: var(--border-soft);
border-radius: var(--r-lg);
}
.msg.user {
background: var(--user-bg);
border-color: #dce6f0;
}
.msg.assistant {
padding: 8px 0;
border-color: transparent;
border-radius: 0;
}
.msg.assistant.live-run {
padding: 12px 14px;
border-color: rgba(184, 58, 49, 0.2);
border-radius: var(--r-lg);
box-shadow:
0 0 0 1px rgba(184, 58, 49, 0.05),
0 8px 24px rgba(184, 58, 49, 0.06);
}
.msg .role {
margin-bottom: 4px;
color: #7d858f;
font-family: inherit;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.2px;
}
.msg .body {
color: var(--text);
font-size: 15px;
line-height: 1.7;
}
.msg .body p {
margin: 0.65em 0;
}
.msg .body h1,
.msg .body h2,
.msg .body h3 {
color: var(--text-strong);
line-height: 1.35;
}
.msg-actions {
margin-top: 8px;
}
.tool-call,
.reasoning {
color: #4f5863;
}
.tool-call summary,
.reasoning summary {
padding: 6px 8px;
border: 1px solid var(--border-soft);
border-radius: var(--r-md);
background: var(--panel-muted);
}
.tool-call summary:hover,
.reasoning summary:hover {
background: var(--hover);
}
.tool-call pre {
border: 1px solid var(--border-soft);
background: var(--code-bg);
}
#chat-form {
gap: 8px;
padding: 12px 16px 14px;
border-top-color: var(--border-soft);
background: var(--panel);
box-shadow: 0 -8px 24px rgba(24, 32, 41, 0.035);
}
#chat-input {
min-height: 72px;
padding: 10px 12px;
line-height: 1.6;
border-radius: var(--r-lg);
background: #fcfcfd;
}
#chat-form .row {
align-items: center;
}
#chat-action {
min-width: 64px;
}
/* File pane */
.crumbs {
min-height: 38px;
padding: 9px 12px;
background: var(--panel);
border-bottom-color: var(--border-soft);
}
.file-row {
min-height: 38px;
padding: 7px 12px;
border-bottom-color: var(--border-soft);
}
.file-row:hover {
background: var(--panel);
}
.file-row .name {
color: #30363d;
}
.storage-foot {
padding: 8px 12px;
border-top-color: var(--border-soft);
background: var(--panel);
}
.storage-foot .bar {
height: 5px;
background: #e5e9ed;
}
/* Dialogs and notifications */
.modal {
padding: 16px;
background: rgba(22, 28, 35, 0.46);
}
.modal > .card {
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.72);
box-shadow: var(--shadow-card);
}
#chpw-modal h3,
#app-dialog h3,
#changelog-modal h3,
#skills-modal h3,
#wechat-modal h3,
#crons-modal h3,
#memory-modal h3,
#kb-modal h3 {
min-height: 48px;
padding: 13px 18px;
color: var(--text-strong);
border-bottom-color: var(--border-soft);
}
#app-dialog .body,
#chpw-modal .body {
padding: 18px;
}
#app-dialog .actions,
#chpw-modal .actions,
#src-picker-modal .actions {
padding: 12px 18px;
border-top-color: var(--border-soft);
background: var(--panel-subtle);
}
.toast,
.app-msg {
border: 1px solid var(--border-soft);
border-radius: var(--r-lg);
box-shadow: var(--shadow-float);
}
/* Respect system motion preferences for polish-only transitions too. */
@media (prefers-reduced-motion: reduce) {
button,
input,
textarea,
select {
transition: none;
}
}
@media (max-width: 640px) {
header {
min-height: 46px;
padding: 7px 10px;
}
.pane-head {
min-height: 42px;
}
#chat-stream {
gap: 12px;
padding: 14px 12px 18px;
}
.msg {
max-width: 97%;
}
.msg .body {
font-size: 15px;
line-height: 1.68;
}
#chat-form {
padding: 10px;
}
#chat-input {
min-height: 64px;
}
#chat-form .row button {
min-height: 36px;
}
.modal {
padding: 12px;
}
}