@tailwind base; @tailwind components; @tailwind utilities; /* 设计令牌(颜色)的 CSS 侧来源。 ───────────────────────────────────────────────────────────── 此前 index.css 里三处直接写死了十六进制字面量: · :focus-visible 的 outline → #9e1b1b · .masthead-rule 的 border-top → #17140f · .font-brush 的 color → #9E1B1B(还是大写写法) 它们与 tailwind.config.js 的 press / ink 令牌是同一批颜色,却没有 共享来源。后果:调整品牌红时改令牌不会影响这三处 —— 焦点轮廓、 报头粗线、毛笔字会保持旧色,出现「两个印报红,其中一个没有名字」。 现在把颜色定义在 :root,由 tailwind.config.js 消费同一份变量, 使 CSS 与工具类共享单一来源。改色只需改这里一处。 ⚠️ 值必须写成 RGB 三元组(如 23 20 15)而非 #17140F。 原因:Tailwind 的透明度修饰符(bg-press/60)需要把颜色拆成 rgb(R G B / ) 才能注入 alpha。若变量本身是完整 十六进制,`bg-press-wash/60` 这类写法会**静默不生成任何 CSS** —— 编译不报错,但样式消失(实测踩到过)。三元组写法同时兼容 不需要 alpha 的场景。 */ :root { /* 纸白:微暖底色,像新闻纸而不是纯白画布 */ --paper-50: 253 252 248; --paper-100: 247 244 236; --paper-200: 237 233 222; --paper-300: 221 215 199; /* 墨色:暖黑灰阶 */ --ink-900: 23 20 15; --ink-700: 59 54 46; --ink-500: 110 103 91; --ink-400: 156 149 135; --ink-300: 201 196 184; --ink-200: 226 223 215; /* 印报红:全站唯一强调色 */ --press: 158 27 27; --press-dark: 124 20 20; --press-wash: 247 233 228; } /* 毛体草书(刘建毛草) - 本地自托管子集(仅「先知」两字,约 1KB) 原先直连 jsDelivr 的 @main 分支(未锁版本、国内加载不稳、5MB 全字库)。 现仅保留报头用字,构建期随包发布,消除外部单点依赖。 */ @font-face { font-family: 'Liu Jian Mao Cao'; src: url('./assets/fonts/LiuJianMaoCao-subset.woff2') format('woff2'); font-display: swap; font-weight: 400; unicode-range: U+5148, U+77E5; /* 先 U+5148 / 知 U+77E5 */ } /* 粗毛笔字效果:笔触加粗 + 微描边 */ .font-brush { font-weight: 700; -webkit-text-stroke: 0.3px currentColor; text-shadow: 0.5px 0.5px 0 currentColor; } /* 页面内容横向轻扫+淡入 */ .page-content-enter { animation: pageSlideIn 0.3s ease-out; } @keyframes pageSlideIn { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } } @layer base { html { -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; } body { @apply bg-paper-50 text-ink-800 font-sans antialiased; font-feature-settings: 'tnum' 1; /* 数字等宽:比分/百分比不跳动 */ } ::selection { @apply bg-press-wash text-press; } /* 统一焦点环:印报红细线,键盘可达 */ :focus-visible { outline: 2px solid var(--press); outline-offset: 2px; } /* 细滚动条 */ ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { @apply rounded-full bg-ink-300; } ::-webkit-scrollbar-thumb:hover { @apply bg-ink-400; } /* 尊重「减少动态效果」偏好 */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } } @layer components { /* ── 报头双线:粗线在上、细线在下 ── */ .masthead-rule { border-top: 3px solid var(--ink-900); } /* ── 按钮:方正边框式,悬停反白 ── */ .btn { @apply inline-flex items-center justify-center gap-1.5 border border-ink-300 bg-transparent px-3 text-sm text-ink-700 transition-colors duration-150 hover:border-ink-900 hover:bg-ink-900 hover:text-paper-50 disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-ink-300 disabled:hover:bg-transparent disabled:hover:text-ink-700 min-h-[44px] py-1.5; } .btn-sm { @apply px-2.5 text-xs min-h-[36px]; } .btn-solid { @apply border-ink-900 bg-ink-900 text-paper-50 hover:border-press hover:bg-press; } .btn-danger { @apply border-press bg-transparent text-press hover:bg-press hover:text-paper-50; } /* 描边确认按钮:次级动作中需要比默认 btn 更明确轮廓的场合 (此前三处使用但从未定义,样式静默失效) */ .btn-outline { @apply border-ink-900 bg-transparent text-ink-900 hover:border-press hover:bg-press-wash hover:text-press-dark; } /* 幽灵按钮:无边、无底色,仅 hover 时浮出浅纸底。 用于「重置」「取消」等最轻量的次要动作。 (EvalPage 曾使用但从未定义,与 btn-outline 同型问题; 现由 src/components/ui 的 Button variant 类型约束兜底,不再可能静默失效) */ .btn-ghost { @apply border-transparent bg-transparent text-ink-500 hover:bg-paper-200 hover:text-ink-900 disabled:hover:bg-transparent disabled:hover:text-ink-500; } /* ── 弹窗入场:遮罩淡入 + 面板上浮(仅 opacity/transform,GPU 友好) ── */ .modal-overlay-enter { animation: modal-fade 0.18s ease-out both; } .modal-panel-enter { animation: modal-rise 0.2s cubic-bezier(0.22, 1, 0.36, 1) both; } @keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } } @keyframes modal-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } /* ── 不确定态进度条(indeterminate) ── 用于「耗时未知」的等待场景(如多专家预测)。与确定性进度条的区别 是它不表达百分比,只表达「仍在进行」—— 因此不存在「卡在 95%」 这种误导。transform-only,GPU 友好。 */ .predict-scan { animation: predict-scan 1.4s cubic-bezier(0.4, 0, 0.6, 1) infinite; } @keyframes predict-scan { 0% { transform: translateX(-100%); } 100% { transform: translateX(300%); } } /* ── 统一空态 ── */ .empty-state { @apply border-y border-ink-200 py-12 text-center; } .empty-state-title { @apply font-serif text-sm text-ink-600; } .empty-state-sub { @apply mt-1.5 text-xs text-ink-400; } .empty-state-action { @apply mt-4 inline-flex items-center gap-2 text-2xs text-press hover:text-press-dark transition-colors; } /* ── 统一错误横幅(前台用,后台用 Alert) ── */ .error-banner { @apply flex items-start justify-between gap-3 border border-press bg-press-wash px-4 py-3; } .error-banner-title { @apply text-sm font-medium text-press; } .error-banner-detail { @apply mt-0.5 text-xs text-ink-600; } /* ── 表单控件:方正、无圆角 ── */ .field { @apply border border-ink-300 bg-transparent px-2.5 py-1.5 text-sm text-ink-800 transition-colors hover:border-ink-400 focus:border-press focus:outline-none; } /* ── 版面切换文字标签(联赛/状态/模式) ── */ .tab { @apply relative whitespace-nowrap px-0.5 py-1 text-sm text-ink-500 transition-colors hover:text-ink-900; } .tab-on { @apply font-medium text-press; } .tab-on::after { content: ''; @apply absolute inset-x-0 bottom-0 h-0.5 bg-press; } /* ── 小节标题:宋体加粗 + 墨色底线 ── */ .section-head { @apply border-b border-ink-900 pb-1.5 font-serif text-sm font-bold text-ink-900; } /* ── 骨架占位:低调脉动,不用渐变扫光 ── */ .skeleton { @apply animate-pulse rounded-none bg-ink-200; } /* ── 侧边栏图标:统一样式 + hover过渡到品牌色 ── */ .nav-icon { width: 1.125rem; height: 1.125rem; stroke-width: 1.5; flex-shrink: 0; opacity: 0.5; transition: all 0.2s ease; } .nav-icon-wrap:hover .nav-icon, .nav-icon-wrap.active .nav-icon { opacity: 1; color: var(--press); stroke-width: 2; } } /* ── Admin 后台 ── 与前台共用同一套报刊风组件(.btn/.field/.tab/.section-head/.skeleton), 不再单独维护暗色主题。 */