Files
mokeeText/frontend/static/css/style.css
2026-07-15 16:08:17 +08:00

702 lines
19 KiB
CSS

/* ========================================
MoKeeText — Feishu-inspired Design System
======================================== */
/* ——— Design Tokens ——— */
:root {
/* Surface */
--bg-page: #F5F6F8;
--bg-sidebar: #FCFCFD;
--bg-surface: #FFFFFF;
--bg-hover: #F2F3F5;
--bg-active: #EEF3FF;
/* Text */
--text-primary: #1F2329;
--text-secondary: #646A73;
--text-tertiary: #8F959E;
--text-placeholder:#BCC0C6;
/* Border */
--border-light: #E5E6EB;
--border-medium: #DEE0E3;
/* Brand */
--brand: #3370FF;
--brand-hover: #245BDB;
--brand-light: #EEF3FF;
--brand-ghost: rgba(51,112,255,0.06);
/* Semantic */
--danger: #F54A45;
--danger-light: #FFF1F0;
--success: #34C759;
/* Radius */
--r-sm: 6px;
--r-md: 8px;
--r-lg: 12px;
/* Shadow */
--shadow-sm: 0 1px 2px rgba(0,0,0,0.04);
--shadow-md: 0 4px 12px rgba(0,0,0,0.08);
--shadow-lg: 0 8px 24px rgba(0,0,0,0.12);
/* Spacing */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 12px;
--space-lg: 16px;
--space-xl: 20px;
--space-2xl: 24px;
}
/* ——— Reset ——— */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text-primary);
background: var(--bg-page);
height: 100vh;
overflow: hidden;
-webkit-font-smoothing: antialiased;
}
/* ——— Top Navigation ——— */
.topnav {
display: flex;
align-items: center;
height: 48px;
padding: 0 var(--space-xl);
background: var(--bg-surface);
border-bottom: 1px solid var(--border-light);
gap: 0;
flex-shrink: 0;
user-select: none;
}
.topnav-brand {
font-weight: 700;
font-size: 15px;
color: var(--text-primary);
text-decoration: none;
margin-right: var(--space-2xl);
letter-spacing: -0.01em;
}
.topnav-link {
padding: 13px var(--space-lg);
font-size: 13px;
font-weight: 500;
color: var(--text-secondary);
text-decoration: none;
border-bottom: 2px solid transparent;
transition: color 0.15s;
letter-spacing: 0;
}
.topnav-link:hover { color: var(--brand); }
.topnav-link.active {
color: var(--brand);
border-bottom-color: var(--brand);
}
/* ——— User Widget ——— */
.user-widget {
margin-left: auto;
display: flex;
align-items: center;
gap: 8px;
padding: 4px 10px 4px 4px;
border-radius: 20px;
cursor: pointer;
transition: background 0.15s;
user-select: none;
}
.user-widget:hover { background: var(--bg-hover); }
.user-avatar {
width: 28px; height: 28px;
border-radius: 50%;
background: var(--brand);
color: #fff;
display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 600;
flex-shrink: 0;
}
.user-name { font-size: 13px; font-weight: 500; color: var(--text-primary); }
/* ——— Footer ——— */
.footer {
display: flex;
align-items: center;
justify-content: space-between;
height: 32px;
padding: 0 var(--space-xl);
background: var(--bg-surface);
border-top: 1px solid var(--border-light);
font-size: 11px;
color: var(--text-tertiary);
flex-shrink: 0;
}
.footer-icp { color: var(--text-placeholder); }
/* ——— Main Layout ——— */
.layout { display: flex; height: calc(100vh - 48px - 32px); }
/* ——— Sidebar ——— */
.sidebar {
width: 260px;
min-width: 260px;
background: var(--bg-sidebar);
border-right: 1px solid var(--border-light);
display: flex;
flex-direction: column;
padding: var(--space-md);
gap: var(--space-sm);
overflow: hidden;
}
/* Sidebar section label */
.sidebar-label {
font-size: 11px;
font-weight: 600;
color: var(--text-tertiary);
text-transform: uppercase;
letter-spacing: 0.04em;
padding: 4px 0;
margin-top: 4px;
display: flex;
align-items: center;
justify-content: space-between;
}
/* ——— Buttons ——— */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 36px;
padding: 0 var(--space-lg);
border: none;
border-radius: var(--r-sm);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.15s;
font-family: inherit;
white-space: nowrap;
}
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.btn-primary {
background: var(--brand);
color: #fff;
}
.btn-primary:hover { background: var(--brand-hover); }
.btn-outline {
background: var(--bg-surface);
color: var(--brand);
border: 1px solid var(--brand);
}
.btn-outline:hover { background: var(--brand-light); }
.btn-ghost {
background: transparent;
color: var(--text-secondary);
}
.btn-ghost:hover { background: var(--bg-hover); color: var(--text-primary); }
.btn-danger-ghost {
background: transparent;
color: var(--text-tertiary);
}
.btn-danger-ghost:hover { background: var(--danger-light); color: var(--danger); }
.btn-block { width: 100%; }
.btn-sm { height: 30px; font-size: 12px; padding: 0 12px; }
/* ——— Input ——— */
.input {
width: 100%;
height: 36px;
padding: 0 12px;
border: 1px solid var(--border-medium);
border-radius: var(--r-sm);
font-size: 13px;
color: var(--text-primary);
background: var(--bg-surface);
outline: none;
transition: border 0.15s;
font-family: inherit;
}
.input:focus { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-light); }
.input::placeholder { color: var(--text-placeholder); }
.textarea {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--border-medium);
border-radius: var(--r-sm);
font-size: 13px;
color: var(--text-primary);
background: var(--bg-surface);
outline: none;
resize: vertical;
font-family: inherit;
transition: border 0.15s;
min-height: 60px;
}
.textarea:focus { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-light); }
.select {
width: 100%;
height: 36px;
padding: 0 12px;
border: 1px solid var(--border-medium);
border-radius: var(--r-sm);
font-size: 13px;
color: var(--text-primary);
background: var(--bg-surface);
outline: none;
cursor: pointer;
font-family: inherit;
}
/* ——— Folder Tree ——— */
.folder-item {
display: flex;
align-items: center;
gap: 6px;
height: 32px;
padding: 0 8px;
border-radius: var(--r-sm);
cursor: pointer;
font-size: 13px;
color: var(--text-primary);
transition: background 0.1s;
user-select: none;
}
.folder-item:hover { background: var(--bg-hover); }
.folder-item.active { background: var(--brand-light); color: var(--brand); font-weight: 500; }
.folder-item .count {
margin-left: auto;
font-size: 11px;
color: var(--text-tertiary);
}
.folder-item.active .count { color: var(--brand); opacity: 0.7; }
/* Folder menu */
.folder-more {
opacity: 0;
padding: 2px 6px;
font-size: 16px;
font-weight: 700;
color: var(--text-tertiary);
border-radius: 4px;
cursor: pointer;
line-height: 1;
}
.folder-item:hover .folder-more { opacity: 1; }
.folder-more:hover { background: var(--bg-hover); color: var(--text-primary); }
.folder-menu {
position: absolute;
right: 0;
top: 100%;
background: var(--bg-surface);
border: 1px solid var(--border-light);
border-radius: var(--r-md);
box-shadow: var(--shadow-md);
z-index: 10;
min-width: 120px;
padding: 4px;
}
.folder-menu-item {
padding: 6px 12px;
cursor: pointer;
font-size: 12px;
color: var(--text-primary);
border-radius: var(--r-sm);
transition: background 0.1s;
}
.folder-menu-item:hover { background: var(--bg-hover); }
.folder-menu-item.danger { color: var(--danger); }
.folder-menu-item.danger:hover { background: var(--danger-light); }
.folder-children { margin-left: 16px; }
.folder-arrow { font-size: 10px; color: var(--text-tertiary); width: 12px; flex-shrink: 0; }
/* ——— Site List ——— */
.site-item {
display: flex;
align-items: center;
gap: 8px;
height: 36px;
padding: 0 8px;
border-radius: var(--r-sm);
cursor: pointer;
font-size: 13px;
transition: background 0.1s;
user-select: none;
}
.site-item:hover { background: var(--bg-hover); }
.site-item.active { background: var(--brand-light); color: var(--brand); font-weight: 500; }
.site-item .site-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.site-item .site-count { font-size: 10px; color: var(--text-tertiary); flex-shrink: 0; }
.site-item.active .site-count { color: var(--brand); opacity: 0.7; }
/* ——— Content Area ——— */
.content {
flex: 1;
display: flex;
flex-direction: column;
background: var(--bg-surface);
min-width: 0;
}
.content-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px var(--space-xl);
border-bottom: 1px solid var(--border-light);
gap: var(--space-md);
flex-shrink: 0;
}
.content-title {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
border: none;
outline: none;
background: transparent;
flex: 1;
font-family: inherit;
}
.content-title::placeholder { color: var(--text-placeholder); }
/* ——— View Toggle ——— */
.toggle-group {
display: flex;
background: var(--bg-hover);
border-radius: var(--r-sm);
padding: 2px;
}
.toggle-group button {
height: 28px;
padding: 0 12px;
border: none;
background: transparent;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
color: var(--text-secondary);
transition: all 0.15s;
font-family: inherit;
}
.toggle-group button.active {
background: var(--bg-surface);
box-shadow: var(--shadow-sm);
color: var(--text-primary);
font-weight: 500;
}
/* ——— Editor Area ——— */
.editor-wrap {
flex: 1;
display: flex;
min-height: 0;
}
.editor-pane {
flex: 1;
padding: var(--space-xl);
overflow-y: auto;
min-width: 0;
}
.editor-pane + .editor-pane { border-left: 1px solid var(--border-light); }
/* ——— Tiptap Toolbar ——— */
.tb-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 2px;
padding: 4px 6px;
background: var(--bg-sidebar);
border: 1px solid var(--border-light);
border-radius: var(--r-md);
margin-bottom: var(--space-lg);
}
.tb-divider {
width: 1px;
height: 16px;
background: var(--border-medium);
margin: 0 4px;
}
.tb-btn {
height: 28px;
padding: 0 8px;
border: none;
background: transparent;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
color: var(--text-secondary);
white-space: nowrap;
font-family: inherit;
transition: all 0.1s;
}
.tb-btn:hover { background: var(--bg-hover); }
.tb-btn.active { background: var(--brand-light); color: var(--brand); }
.tb-color {
width: 24px;
height: 24px;
border: 1px solid var(--border-medium);
border-radius: 4px;
cursor: pointer;
padding: 0;
margin: 0 2px;
}
/* ProseMirror / Tiptap Content */
.ProseMirror { outline: none; min-height: 300px; font-size: 14px; line-height: 1.8; }
.ProseMirror h1 { font-size: 22px; font-weight: 700; margin: 16px 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--border-light); }
.ProseMirror h2 { font-size: 18px; font-weight: 600; margin: 14px 0 6px; }
.ProseMirror h3 { font-size: 15px; font-weight: 600; margin: 12px 0 4px; }
.ProseMirror p { margin: 4px 0; }
.ProseMirror ul, .ProseMirror ol { padding-left: 20px; margin: 4px 0; }
.ProseMirror li { margin: 2px 0; }
.ProseMirror blockquote { border-left: 3px solid var(--brand); padding-left: 12px; color: var(--text-secondary); margin: 8px 0; }
.ProseMirror pre { background: #F7F8FA; padding: 12px 16px; border-radius: var(--r-sm); overflow-x: auto; font-family: "SF Mono","Fira Code","Consolas",monospace; font-size: 13px; line-height: 1.6; }
.ProseMirror code { background: #F2F3F5; padding: 2px 6px; border-radius: 3px; font-size: 12px; font-family: "SF Mono","Fira Code","Consolas",monospace; }
.ProseMirror table { border-collapse: collapse; width: 100%; margin: 8px 0; }
.ProseMirror th, .ProseMirror td { border: 1px solid var(--border-light); padding: 8px 12px; text-align: left; }
.ProseMirror th { background: #F7F8FA; font-weight: 600; font-size: 13px; }
.ProseMirror img { max-width: 100%; border-radius: var(--r-sm); }
.ProseMirror mark { background: #FFF3CD; padding: 2px 4px; border-radius: 2px; }
/* ——— Note List in Sidebar ——— */
.note-list-item {
display: flex;
align-items: center;
gap: 8px;
height: 34px;
padding: 0 8px;
border-radius: var(--r-sm);
cursor: pointer;
font-size: 12px;
transition: background 0.1s;
}
.note-list-item:hover { background: var(--bg-hover); }
.note-list-item.active { background: var(--brand-light); }
.note-list-item .note-title-s {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 500;
}
.note-list-item .note-date { font-size: 10px; color: var(--text-tertiary); }
/* ——— Account Card ——— */
.card {
background: var(--bg-surface);
border: 1px solid var(--border-light);
border-radius: var(--r-lg);
padding: var(--space-lg);
transition: box-shadow 0.15s;
}
.card:hover { box-shadow: var(--shadow-sm); }
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.card-title { font-size: 14px; font-weight: 600; }
.card-body { display: grid; grid-template-columns: auto 1fr auto; gap: 8px 12px; font-size: 13px; align-items: center; }
.card-body .label { color: var(--text-tertiary); font-size: 12px; white-space: nowrap; }
.card-body .value { font-family: "SF Mono","Fira Code","Consolas",monospace; font-size: 13px; word-break: break-all; }
.card-actions { display: flex; gap: 6px; }
.card-btn {
height: 30px;
padding: 0 10px;
border: 1px solid var(--border-light);
border-radius: var(--r-sm);
background: var(--bg-surface);
font-size: 12px;
cursor: pointer;
color: var(--text-secondary);
transition: all 0.15s;
font-family: inherit;
}
.card-btn:hover { background: var(--bg-hover); border-color: var(--border-medium); }
.card-btn.edit:hover { color: var(--brand); border-color: var(--brand); background: var(--brand-light); }
.card-btn.danger:hover { color: var(--danger); border-color: var(--danger); background: var(--danger-light); }
/* ——— Modal ——— */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.35);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
animation: fade-in 0.15s ease;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
.modal {
background: var(--bg-surface);
border-radius: var(--r-lg);
box-shadow: var(--shadow-lg);
width: 480px;
max-width: 90vw;
max-height: 85vh;
display: flex;
flex-direction: column;
animation: slide-in 0.15s ease;
}
@keyframes slide-in { from { transform: translateY(8px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-lg) var(--space-xl);
border-bottom: 1px solid var(--border-light);
flex-shrink: 0;
}
.modal-title { font-size: 15px; font-weight: 600; }
.modal-close {
width: 28px; height: 28px;
display: flex; align-items: center; justify-content: center;
border: none; background: transparent;
border-radius: var(--r-sm);
cursor: pointer;
font-size: 18px; color: var(--text-tertiary);
transition: all 0.15s;
}
.modal-close:hover { background: var(--bg-hover); color: var(--text-primary); }
.modal-body { padding: var(--space-xl); overflow-y: auto; flex: 1; }
.modal-footer {
display: flex;
justify-content: flex-end;
gap: var(--space-sm);
padding: var(--space-md) var(--space-xl);
border-top: 1px solid var(--border-light);
flex-shrink: 0;
}
/* ——— Form ——— */
.form-group { margin-bottom: var(--space-lg); }
.form-group:last-child { margin-bottom: 0; }
.form-label { display: block; font-size: 12px; font-weight: 600; color: var(--text-secondary); margin-bottom: 4px; }
.form-row { display: flex; gap: var(--space-sm); align-items: center; }
/* ——— Import Area ——— */
.import-textarea {
width: 100%;
height: 90px;
padding: 10px 12px;
border: 2px solid var(--brand);
border-radius: var(--r-md);
font-size: 13px;
font-family: inherit;
resize: vertical;
outline: none;
background: var(--brand-light);
}
.import-hint { font-size: 11px; color: var(--text-tertiary); margin: 4px 0 12px; }
.result-box {
background: #F0FAF0;
border: 1px solid #A3E4A7;
border-radius: var(--r-md);
padding: 14px 16px;
margin-bottom: var(--space-lg);
}
.result-grid { display: grid; grid-template-columns: 70px 1fr; gap: 6px 12px; font-size: 13px; }
.alert {
padding: 8px 12px;
border-radius: var(--r-sm);
font-size: 12px;
}
.alert-warning { background: #FFF7E6; color: #8A5D00; }
/* ——— Stats ——— */
.stat-row { display: flex; gap: 6px; }
.stat {
flex: 1;
text-align: center;
padding: 8px 4px;
background: var(--bg-surface);
border: 1px solid var(--border-light);
border-radius: var(--r-sm);
font-size: 11px;
}
.stat-num { font-size: 18px; font-weight: 700; }
.stat-label { color: var(--text-tertiary); font-size: 10px; }
/* ——— Toast ——— */
.toast {
position: fixed;
top: 20px;
right: 20px;
background: #1F2329;
color: #fff;
padding: 8px 16px;
border-radius: var(--r-sm);
font-size: 13px;
z-index: 9999;
animation: fade-in 0.2s ease;
}
/* ——— Tag Badge ——— */
.tag-badge {
display: inline-block;
padding: 2px 10px;
background: var(--bg-hover);
border-radius: 10px;
font-size: 11px;
cursor: pointer;
color: var(--text-secondary);
transition: all 0.15s;
}
.tag-badge:hover { background: #DEE0E3; }
.tag-badge.active { background: var(--brand); color: #fff; }
.tag-add { border: 1px dashed var(--border-medium); background: transparent; color: var(--text-tertiary); }
.tag-add:hover { border-color: var(--brand); color: var(--brand); background: transparent; }
/* ——— Helpers ——— */
.hidden { display: none !important; }
.flex-1 { flex: 1; }
.text-muted { color: var(--text-tertiary); font-size: 12px; }
.text-sm { font-size: 12px; }
.gap-xs { gap: var(--space-xs); }
.gap-sm { gap: var(--space-sm); }
.mb-sm { margin-bottom: var(--space-sm); }
.mb-md { margin-bottom: var(--space-md); }
/* ——— Scrollbar ——— */
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #D0D3D7; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #B0B3B7; }
/* ——— Brand wrapper ——— */
.save-badge {
font-size: 10px;
color: var(--text-tertiary);
background: var(--bg-hover);
padding: 2px 8px;
border-radius: 10px;
flex-shrink: 0;
}