- 编辑器初始化等待文章和草稿两个查询都返回,此前草稿接口先返回 空内容时会用默认文本初始化并被自动保存覆盖真实草稿 - CodeMirror 容器加 min-h-0(flex 子项默认 min-height:auto 会被 内容撑开),并约束 .cm-editor 高度为 100% 使内部滚动生效 - 修复规则必须放在 @layer 外,否则被 Tailwind 当作未使用样式裁剪
294 lines
7.9 KiB
CSS
294 lines
7.9 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
:root {
|
|
color-scheme: light dark;
|
|
}
|
|
|
|
html {
|
|
@apply scroll-smooth;
|
|
}
|
|
|
|
body {
|
|
@apply bg-paper text-stone-900 antialiased font-serif;
|
|
font-feature-settings: 'cv11', 'ss01';
|
|
}
|
|
|
|
html.dark body {
|
|
@apply bg-space-950 text-star font-sans;
|
|
}
|
|
|
|
::selection {
|
|
@apply bg-indigo-500/30 text-indigo-900;
|
|
}
|
|
|
|
.dark ::selection {
|
|
@apply bg-nebula/40 text-star;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
.stars {
|
|
background-image:
|
|
radial-gradient(2px 2px at 20px 30px, rgba(255,255,255,0.3), transparent),
|
|
radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.2), transparent),
|
|
radial-gradient(1px 1px at 90px 40px, rgba(255,255,255,0.4), transparent),
|
|
radial-gradient(2px 2px at 160px 120px, rgba(255,255,255,0.2), transparent),
|
|
radial-gradient(1px 1px at 230px 80px, rgba(255,255,255,0.3), transparent),
|
|
radial-gradient(2px 2px at 300px 20px, rgba(255,255,255,0.2), transparent),
|
|
radial-gradient(1px 1px at 350px 150px, rgba(255,255,255,0.4), transparent);
|
|
background-repeat: repeat;
|
|
background-size: 400px 200px;
|
|
}
|
|
|
|
.nebula {
|
|
background-image:
|
|
radial-gradient(ellipse at 20% 30%, rgba(99,102,241,0.12), transparent 40%),
|
|
radial-gradient(ellipse at 80% 70%, rgba(139,92,246,0.08), transparent 40%),
|
|
radial-gradient(ellipse at 50% 50%, rgba(34,211,238,0.06), transparent 50%);
|
|
}
|
|
|
|
.glass {
|
|
@apply bg-white/70 backdrop-blur-md border border-white/20;
|
|
}
|
|
|
|
.dark .glass {
|
|
@apply bg-space-800/60 border-indigo-500/20;
|
|
}
|
|
|
|
.glow-text {
|
|
@apply text-transparent bg-clip-text bg-gradient-to-r from-indigo-400 via-purple-400 to-cyan-400;
|
|
}
|
|
|
|
.nav-link {
|
|
@apply relative text-stone-600 hover:text-stone-900 transition-colors;
|
|
}
|
|
|
|
.dark .nav-link {
|
|
@apply text-star-dim hover:text-star;
|
|
}
|
|
|
|
.nav-link::after {
|
|
content: '';
|
|
@apply absolute left-0 -bottom-1 w-0 h-0.5 bg-indigo-500 transition-all duration-300;
|
|
}
|
|
|
|
.nav-link:hover::after {
|
|
@apply w-full;
|
|
}
|
|
|
|
/* 卡片悬浮光晕 */
|
|
.card-glow {
|
|
@apply relative overflow-hidden rounded-lg border border-stone-200 bg-white shadow-sm transition-all duration-300;
|
|
}
|
|
|
|
.dark .card-glow {
|
|
@apply border-indigo-500/20 bg-space-800/60 shadow-none;
|
|
}
|
|
|
|
.card-glow::before {
|
|
content: '';
|
|
@apply absolute inset-0 opacity-0 transition-opacity duration-300 pointer-events-none;
|
|
background: radial-gradient(600px circle at var(--mouse-x, 50%) var(--mouse-y, 50%), rgba(99,102,241,0.08), transparent 40%);
|
|
}
|
|
|
|
.dark .card-glow::before {
|
|
background: radial-gradient(600px circle at var(--mouse-x, 50%) var(--mouse-y, 50%), rgba(129,140,248,0.12), transparent 40%);
|
|
}
|
|
|
|
.card-glow:hover::before {
|
|
@apply opacity-100;
|
|
}
|
|
|
|
/* 发光边框 */
|
|
.glow-border {
|
|
position: relative;
|
|
}
|
|
|
|
.glow-border::after {
|
|
content: '';
|
|
@apply absolute inset-0 rounded-2xl opacity-0 transition-opacity duration-300 pointer-events-none;
|
|
padding: 1px;
|
|
background: linear-gradient(135deg, rgba(99,102,241,0.4), rgba(139,92,246,0.4), rgba(34,211,238,0.4));
|
|
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
-webkit-mask-composite: xor;
|
|
mask-composite: exclude;
|
|
}
|
|
|
|
.glow-border:hover::after {
|
|
@apply opacity-100;
|
|
}
|
|
|
|
/* 标题动画 */
|
|
.title-reveal {
|
|
@apply inline-block overflow-hidden;
|
|
}
|
|
|
|
.title-reveal span {
|
|
@apply inline-block transform translate-y-full;
|
|
animation: titleUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
}
|
|
|
|
@keyframes titleUp {
|
|
to {
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* 夜间模式正文调白(prose-invert 用的是 invert 变量,得在这里覆盖) */
|
|
.dark .prose {
|
|
--tw-prose-invert-body: #ffffff;
|
|
--tw-prose-invert-headings: #ffffff;
|
|
--tw-prose-invert-bold: #ffffff;
|
|
--tw-prose-invert-quotes: #ffffff;
|
|
--tw-prose-invert-counters: #e0e7ff;
|
|
--tw-prose-invert-bullets: #818cf8;
|
|
}
|
|
|
|
/* 代码块:浅色底框 + 顶部语言标注栏(夜间为深空蓝) */
|
|
.prose .code-block-wrapper {
|
|
@apply relative my-6 overflow-hidden rounded-lg border border-stone-200 bg-[#f6f8fa];
|
|
}
|
|
|
|
.prose .code-block-header {
|
|
@apply flex items-center justify-between border-b border-stone-200 bg-stone-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wider text-stone-500;
|
|
}
|
|
|
|
.prose pre.code-block-content {
|
|
@apply m-0 overflow-x-auto bg-transparent p-4 font-mono text-sm leading-relaxed text-stone-800;
|
|
}
|
|
|
|
/* hljs 主题自带底色和内边距,去掉以免和容器冲突 */
|
|
.prose pre.code-block-content .hljs {
|
|
background: transparent;
|
|
padding: 0;
|
|
}
|
|
|
|
/* 夜间:深空蓝底 + GitHub Dark 语法配色 */
|
|
.dark .prose .code-block-wrapper {
|
|
@apply border-indigo-500/20 bg-space-800;
|
|
}
|
|
|
|
.dark .prose .code-block-header {
|
|
@apply border-indigo-500/10 bg-space-900 text-star-dim;
|
|
}
|
|
|
|
.dark .prose pre.code-block-content {
|
|
@apply text-slate-200;
|
|
}
|
|
|
|
.dark .hljs { color: #c9d1d9; }
|
|
.dark .hljs-doctag,
|
|
.dark .hljs-keyword,
|
|
.dark .hljs-meta .hljs-keyword,
|
|
.dark .hljs-template-tag,
|
|
.dark .hljs-template-variable,
|
|
.dark .hljs-type,
|
|
.dark .hljs-variable.language_ { color: #ff7b72; }
|
|
.dark .hljs-title,
|
|
.dark .hljs-title.class_,
|
|
.dark .hljs-title.class_.inherited__,
|
|
.dark .hljs-title.function_ { color: #d2a8ff; }
|
|
.dark .hljs-attr,
|
|
.dark .hljs-attribute,
|
|
.dark .hljs-literal,
|
|
.dark .hljs-meta,
|
|
.dark .hljs-number,
|
|
.dark .hljs-operator,
|
|
.dark .hljs-variable,
|
|
.dark .hljs-selector-attr,
|
|
.dark .hljs-selector-class,
|
|
.dark .hljs-selector-id { color: #79c0ff; }
|
|
.dark .hljs-regexp,
|
|
.dark .hljs-string,
|
|
.dark .hljs-meta .hljs-string { color: #a5d6ff; }
|
|
.dark .hljs-built_in,
|
|
.dark .hljs-symbol { color: #ffa657; }
|
|
.dark .hljs-comment,
|
|
.dark .hljs-code,
|
|
.dark .hljs-formula { color: #8b949e; }
|
|
.dark .hljs-name,
|
|
.dark .hljs-quote,
|
|
.dark .hljs-selector-tag,
|
|
.dark .hljs-selector-pseudo { color: #7ee787; }
|
|
.dark .hljs-subst { color: #c9d1d9; }
|
|
.dark .hljs-section { color: #1f6feb; font-weight: bold; }
|
|
.dark .hljs-bullet { color: #f2cc60; }
|
|
.dark .hljs-emphasis { color: #c9d1d9; font-style: italic; }
|
|
.dark .hljs-strong { color: #c9d1d9; font-weight: bold; }
|
|
.dark .hljs-addition { color: #aff5b4; background-color: #033a16; }
|
|
.dark .hljs-deletion { color: #ffdcd7; background-color: #67060c; }
|
|
|
|
/* 阅读进度条 */
|
|
.progress-bar {
|
|
@apply fixed left-0 top-0 h-1 bg-gradient-to-r from-indigo-500 via-purple-500 to-cyan-500 transition-transform origin-left z-50;
|
|
}
|
|
|
|
/* TOC */
|
|
.toc-item {
|
|
@apply relative pl-4 text-sm text-stone-500 transition-colors hover:text-indigo-600 dark:text-star-dim dark:hover:text-nebula-glow;
|
|
}
|
|
|
|
.toc-item::before {
|
|
content: '';
|
|
@apply absolute left-0 top-1/2 h-0 w-0.5 -translate-y-1/2 bg-indigo-500 transition-all duration-200;
|
|
}
|
|
|
|
.toc-item.active::before {
|
|
@apply h-4;
|
|
}
|
|
|
|
.toc-item.active {
|
|
@apply text-indigo-600 font-medium dark:text-nebula-glow;
|
|
}
|
|
|
|
/* 滚动条美化 */
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
@apply bg-transparent;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
@apply rounded-full bg-stone-300;
|
|
}
|
|
|
|
.dark ::-webkit-scrollbar-thumb {
|
|
@apply bg-space-700;
|
|
}
|
|
|
|
/* 按钮按压效果 */
|
|
.btn-press {
|
|
@apply active:scale-95 transition-transform;
|
|
}
|
|
|
|
/* 标签云 */
|
|
.tag-pill {
|
|
@apply inline-flex items-center gap-1 rounded-full px-3 py-1 text-xs font-medium transition-all duration-200;
|
|
}
|
|
|
|
/* 输入框聚焦光效 */
|
|
.input-glow {
|
|
@apply transition-all duration-200;
|
|
}
|
|
|
|
.input-glow:focus {
|
|
@apply shadow-[0_0_0_3px_rgba(99,102,241,0.15)];
|
|
}
|
|
|
|
.dark .input-glow:focus {
|
|
@apply shadow-[0_0_0_3px_rgba(129,140,248,0.2)];
|
|
}
|
|
}
|
|
|
|
/* CodeMirror 编辑器内部滚动(必须是无层级的普通 CSS,
|
|
放在 @layer 里会被 Tailwind 当作未使用样式裁剪掉) */
|
|
.cm-editor {
|
|
height: 100%;
|
|
}
|