--- version: alpha name: Climperor Web description: Dark Dota-inspired information panels for the Climperor Web desktop site. colors: primary: "#5EC8FF" secondary: "#8FA3BC" tertiary: "#3DCE7A" neutral: "#0B1018" surface: "#0E1622" surface-raised: "#101824" on-surface: "#E8EEF7" on-surface-muted: "#8FA3BC" border: "rgba(140, 170, 210, 0.18)" accent: "#5EC8FF" good: "#3DCE7A" bad: "#E07A2F" syn: "#7EC8FF" danger: "#E86A6A" gold: "#E8C878" live: "#FE2C55" panel: "rgba(14, 22, 34, 0.96)" panel-soft: "rgba(8, 12, 20, 0.55)" on-accent: "#0B0D10" typography: brand: fontFamily: "Noto Serif SC, Songti SC, STSong, SimSun, serif" fontSize: 18px fontWeight: 700 lineHeight: 1.3 letterSpacing: 0.16em display: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 32px fontWeight: 800 lineHeight: 1.1 letterSpacing: 0.02em page-title: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 22px fontWeight: 800 lineHeight: 1.2 letterSpacing: 0.02em title-lg: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 18px fontWeight: 700 lineHeight: 1.3 letterSpacing: 0.04em title-md: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 16px fontWeight: 700 lineHeight: 1.35 letterSpacing: 0.02em body-lg: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 15px fontWeight: 400 lineHeight: 1.5 body-md: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 14px fontWeight: 400 lineHeight: 1.5 body-sm: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 13px fontWeight: 500 lineHeight: 1.45 label-md: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 13px fontWeight: 600 lineHeight: 1.3 letterSpacing: 0.06em label-sm: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 12px fontWeight: 600 lineHeight: 1.3 letterSpacing: 0.04em numeric-lg: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 28px fontWeight: 700 lineHeight: 1.1 letterSpacing: 0.02em numeric-md: fontFamily: "Segoe UI, Microsoft YaHei UI, PingFang SC, sans-serif" fontSize: 14px fontWeight: 700 lineHeight: 1.2 rounded: sm: 4px md: 8px lg: 12px xl: 16px full: 9999px spacing: xs: 4px sm: 8px md: 12px lg: 16px xl: 24px 2xl: 32px 3xl: 48px gutter: 16px page-y: 28px content-read: 820px content-standard: 880px content-wide: 1080px content-data: 1200px components: button-primary: backgroundColor: "{colors.primary}" textColor: "{colors.on-accent}" rounded: "{rounded.md}" padding: 12px height: 40px button-primary-hover: backgroundColor: "#7AD4FF" button-secondary: backgroundColor: "{colors.surface}" textColor: "{colors.on-surface}" rounded: "{rounded.md}" padding: 12px height: 40px button-secondary-active: backgroundColor: "{colors.primary}" textColor: "{colors.on-accent}" tab-main: backgroundColor: "{colors.surface}" textColor: "{colors.secondary}" typography: "{typography.body-lg}" height: 42px padding: 10px tab-main-active: backgroundColor: "{colors.surface-raised}" textColor: "{colors.on-surface}" input-search: backgroundColor: "{colors.neutral}" textColor: "{colors.on-surface}" rounded: "{rounded.md}" height: 40px padding: 12px panel-card: backgroundColor: "{colors.surface}" textColor: "{colors.on-surface}" rounded: "{rounded.lg}" padding: 16px chip-filter: backgroundColor: "{colors.surface}" textColor: "{colors.secondary}" rounded: "{rounded.full}" padding: 8px chip-filter-active: backgroundColor: "{colors.surface-raised}" textColor: "{colors.on-surface}" mark-good: backgroundColor: "{colors.neutral}" textColor: "{colors.good}" mark-bad: backgroundColor: "{colors.neutral}" textColor: "{colors.bad}" mark-syn: backgroundColor: "{colors.neutral}" textColor: "{colors.syn}" badge-gold: backgroundColor: "{colors.neutral}" textColor: "{colors.gold}" badge-live: backgroundColor: "{colors.live}" textColor: "#FFFFFF" badge-danger: backgroundColor: "{colors.neutral}" textColor: "{colors.danger}" panel-raised: backgroundColor: "{colors.panel}" textColor: "{colors.on-surface}" panel-soft: backgroundColor: "{colors.panel-soft}" textColor: "{colors.on-surface-muted}" divider: backgroundColor: "{colors.surface}" textColor: "{colors.border}" --- # Climperor Web Design System ## Overview 上分帝 Web 是面向桌面浏览器的 Dota 2 信息站:深色蓝黑底、高信息密度、冷静可读。气质接近官方客户端与选人界面——偏工具面板,不走社交 feed 或明亮营销站。 目标感受: - **Dense but calm**:列表、表格、网格可挤满视口,但字号、行高、间距仍保持清晰节奏。 - **Semantic color first**:青色强调当前选择与导航;绿 / 橙 / 青蓝分别表示克制 / 被克 / 搭档;粉红仅用于直播态。 - **Desktop shell**:`100dvh` 外框 + 页内滚动;手机 / 平板由 `mobile-gate` 拦截,不为真移动端另做一套 IA。 实现源:`web/frontend/style.css` 的 CSS 变量必须与本文件令牌一一对应。工程决策见 `ARCHITECTURE.md`。 ## Colors 调色盘以近黑海军为底,浅冷灰为正文,单一青色作交互主色。 - **Primary (`#5EC8FF`)**:主交互与选中态(主 Tab 底线、侧栏选中填充、焦点环、选中英雄描边)。 - **Secondary (`#8FA3BC`)**:次要文案、标签、时间戳、未选中控件。 - **Tertiary (`#3DCE7A`)**:正向语义(克制、胜率上升、胜场)。 - **Neutral (`#0B1018`)**:页面底色;表面层用更深的半透明面板叠在渐变背景上。 - **Bad / Danger / Gold / Live / Syn**:业务辨识色,不得拿来当通用强调色。 对比度要求:正文与底至少 WCAG AA;muted 文案仅用于辅助信息,不用在关键操作标签上。 ## Typography 系统栈:`Segoe UI` + `Microsoft YaHei UI` + `PingFang SC`。正文与控件优先清晰,不引入全站装饰字体。 品牌例外:顶栏 / 移动端门禁的「上分帝」使用 `brand`(自托管 Noto Serif SC 子集,仅 U+4E0A / U+5206 / U+5E1D),宋体气质贴合「帝」字;正文仍走系统无衬线栈。禁止把衬线栈扩到导航、页标题或表格。 | Token | 用途 | |-------|------| | `brand` | 仅品牌字标「上分帝」(顶栏 + mobile-gate) | | `display` | 版本号等少数展示数字(约 32px,勿再放大到 40px) | | `page-title` | 各顶层页标题(排行 / 走势 / 机制 / 主播 / 物品等) | | `title-lg` / `title-md` | 区段标题、英雄名、物品名 | | `body-lg` / `body-md` / `body-sm` | 导航、正文、说明 | | `label-md` / `label-sm` | 表头、分区标签、徽章 | | `numeric-*` | 表格数字与指标卡,配合 `tabular-nums` | 字重只用 400 / 500 / 600 / 700 / 800。禁止 `650`、`13.5px` 等孤立值。默认行高正文 1.5,标题 1.1–1.3;勿留 `line-height: normal` 在可读正文上。 ## Layout 桌面壳:顶栏固定高度区 + 可滚动 `main.board`;英雄页的英雄网格与固定高 `#detail` 之间放置一行定位筛选。选中英雄后 `#detail` 使用共享固定高度:按视口预留顶栏 + **完整** `#columns` 英雄网格实测高度 + 定位标签后取余,再 `clamp` 到约 `280–640px` (CSS 回退 `min(640px, calc(100dvh - 26rem))`)。技能 Tab 不驱动抽屉高度, 内容在抽屉内 flex/滚动;Tab 切换不跳动;长 Tab(走势/对位等)同理在详情区内滚动。 技能演示片源为官网 16:9;有横向空间时加宽(上限约 720px / 列宽 58%), `aspect-ratio: 16/9` + `object-fit: contain`,勿用拉满高度的 `cover` 裁左右。 ### 顶部壳(紧凑单层) 顶栏只保留主行,禁止品牌 / 主导航 / 搜索三者各自「漂浮居中」造成大块空洞: 1. **首行 `PrimaryRow`**:`display: grid; grid-template-columns: 1fr auto 1fr`(或等价 flex)。 - 左:品牌(logo + 标题) - 中:主导航分段控件(真正几何居中) - 右:工具区(英雄/物品搜索 + 邮件入口),`justify-content: end` 视觉语言轻度借鉴 Dota 2 国服官网导航,但不复刻门户式大顶栏: - 顶栏使用近黑金属渐变与上下 1px 冷色高光,形成连续横梁;总高控制在约 60px。 - 品牌区仅用克制的暗红内光形成视觉锚点,不在 Logo 右侧增加分隔线;不使用视频 Logo、金色奖项条或厚重贴图。 - 主导航保持现代无边框文字 Tab;相邻 Tab 仅用低对比斜切细线分隔,不做梯形按钮。 - 主交互色仍为 `primary` 青色;Dota 红只用于品牌区,不替代全站选中态。 - 宽屏主行采用 44px 控件高:主导航 16px / 最小 76px 宽,品牌 Logo 32px。`lg` 断点恢复 40px、15px 的紧凑规格。 断点降级: - `lg` ≤1200px:Tab 水平内边距收紧;搜索宽约 160–180px - `md` ≤900px:隐藏品牌标题,仅留 logo;搜索再缩短 - `sm` ≤640px:极窄桌面可隐藏整块品牌 内容宽度档位(命名,勿再散落魔法数): | 档位 | 宽度 | 页面 | |------|------|------| | full | 100% | 英雄网格 | | read | 主列 `min(820px)` 页内居中;宽屏「AI 解读」贴主列右侧(不参与居中),宽度随可用侧栏约 280–420px,sticky + 视口内自滚动 | 版本 | | standard | `min(880px, calc(100% - 48px))` | 排行、主播、机制 | | wide | `min(1080px, …)` | 走势 | | data | `min(1200px, …)`(居中时两侧预留侧栏) | 比赛、玩家「我」主页 | 间距尺度:4 / 8 / 12 / 16 / 24 / 32 / 48px。页内 gutter 默认 16px;列表页上下 `page-y` 28px。侧栏与主列间距 20px。 断点收敛为三档: - `sm` ≤640px:极窄桌面(列堆叠、双列网格) - `md` ≤900px:aside 改上下堆叠、英雄两列 - `lg` ≤1200px:物品详情上移、列间距收紧 手机不走上述断点,由 UA 门禁接管。 ## Elevation & Depth 深度靠色调分层与细边框,不用厚重投影: 1. 页面渐变底 2. 半透明顶栏 / 面板(`panel-soft`) 3. 实心一点的浮层(`panel`、物品 sticky 详情、天赋 popover) 选中态用 inset 底线、填充主色或 1–2px `accent` 描边;阴影仅用于浮层(popover / 气泡),模糊约 24–32px、黑色 45% 透明度。 ## Shapes 圆角语言偏克制: - `sm` 4px:表格内图标、小徽章 - `md` 8px:输入框、多数按钮、指标卡 - `lg` 12px:详情面板、机制卡、主内容卡 - `xl` 16px:仅大卡片(主播卡)需要时使用,勿扩散到所有面板 - `full`:筛选 pill、关注按钮 禁止同一视图混用锐角与大圆角而无语义理由。 ## Components ### 玩家主页(Identity / Snapshot / Dashboard) 登录后「我」与 `/players/{id}` 共用**紧凑数据仪表盘**语言,不做小黑盒式社交 feed: - **Identity strip**:整行;`panel-soft` + 细边框 + `radius-lg`;头像 `full` 圆形 56px;昵称 + 段位勋章同行。勋章容器约 64px(OpenDota 图标含画布留白,光学尺寸对齐头像),具体星级用 `rank_icon_*` + `rank_star_*` 叠层表达(如传奇四),不并排写「传奇4」文字;冠绝榜位可保留 `#N`。 - **Snapshot 摘要区**:生涯与近 N 场并排(窄屏堆叠);指标卡 `radius-md`、数字 `tabular-nums`、紧凑五列网格;空数据整组隐藏,禁止显示伪 0% 胜率。 - **Analysis 次级区**:宽屏双栏——左常用英雄列表,右 180 天活动 + 队友;`panel-soft` 分块,避免每块独占整页高度。 - **近期比赛列表**:左英雄/KDA(弹性占满),右「时长/相对时间」与「胜负/#ID」两列双行紧簇右对齐(上:时长·胜负,下:相对时间·#ID);禁止再插 `1fr` 空隙把时长悬在行中;胜负语义色 + 左侧 3px 细边;整行可点。 - **十人详情**:返回控件放在比赛摘要卡上方(非卡内):`surface-raised` + 细边框 + `radius-md`,高 36px,左侧 18px SVG 左箭头 +「返回玩家主页」;hover 用 `primary` 描边/字色。摘要卡仅比赛 ID + 时间 · 时长 · 胜方。天辉/夜魇共享可见列头;昵称列封顶约 16rem(超长截断 + title),勿用弹性列挤占指标;参战/伤害/经济/KDA 四等分占满中间剩余宽度,装备靠右,跨队对齐。胜负始终用 `good` / `danger`,不得把天辉/夜魇阵营色混作胜负色。 - **活动热力图**:按周分列、星期分行的 7×N 网格,使用绿色四级强度并提供「少—多」图例;标注「最近 180 天样本」。 - 主列宽度用 `data`(1200);外层容器须为 1200 内容宽度预留 padding,不得以更小的父级 `max-width` 截断。900–1200px 保持摘要五列与十人详情横向对比,只在空间确实不足时堆叠。 - **加载**:有生涯/近场数据时首屏直出,勿因 TTL `stale` 再转圈或清空页面;空档案才显示「正在同步」并轮询。软过期只静默再拉 `/me`(生产 Queue / 本机后台 enrich),禁止 `loadKey=null` 闪「加载中…」。Cloudflare Worker 在 OpenDota 空/残缺时不得覆盖已有近场/英雄/队友/段位。 ### 导航 - **Main tabs**:无边框文字 Tab,透明背景;相邻项以低对比斜切细线分隔。未选 muted,hover 仅提亮文字,禁止施加矩形 / 渐变底以免与斜切线冲突;选中使用高对比文字 + 居中 44px、2px 高的 `primary` 下划线。宽屏点击区高 44px、字号 16px、最小宽 76px,与搜索 / 邮件对齐;`lg` 断点收敛至 40px / 15px。禁止重新包回连续按钮外框或梯形按钮底。登录后「我」出现在「英雄」前。 - **Detail tabs**:下划线式,字号 `body-md`。 - **Aside filters**(地区 / 机制效果):竖向 filled;选中 `primary` 底 + `on-accent` 字。 - **顶栏邮件**:40×40 图标按钮,muted;hover 提亮。放在右侧工具区,不绝对悬浮到视口角。 ### 英雄定位筛选 位于英雄网格和详情面板之间,使用 Valve 选人筛选符号与中文标签的紧凑斜角按钮。 「全部」用中性网格符号;核心 / 辅助 / 推进 / 逃生 / 爆发 / 先手 / 控制 / 耐久使用对应 Valve 图标。支持多选筛选(`active`);选中英雄时,其定位以同色选中态(`matched`) 高亮,不单独在详情区再放 Chip。当前不展示「幻象」筛选,勿与主导航混排。 ### 搜索 高 40px,圆角 `md`,左侧放大镜;focus 时边框与光晕用 `primary`。默认宽约 200px,落在首行右侧工具区(非 absolute 贴边);物品页换物品搜索,其他页隐藏搜索。 ### 面板 / 卡片 共享 `.ui-panel`:边框 `border`、背景 `panel-soft`、圆角 `lg`、内边距 16px。空态统一 `.ui-empty`:居中 muted、`body-md`、上下 48px。 ### 表格 表头 `label-sm` muted;单元格 `body-md`;数字 `tabular-nums`。行 hover 轻微提亮,不加斑马纹。 ### 焦点 所有可交互控件:`outline: 2px solid primary; outline-offset: 2px`(`.ui-focus`)。最小点击高度 36–40px。 ### 业务标记(不可通用化) - 克 / 怕 / 搭 → `good` / `bad` / `syn` - 直播环与关注按钮 → `live` - 装备金价 → `gold` ## Do's and Don'ts - Do 改视觉前先更新本文件令牌,再改 `style.css` 变量与引用。 - Do 用命名宽度档位与三档断点;Don't 再加孤立 `max-width: Npx`。 - Do 每个顶层页提供清晰的页标题语义(可见 `h1`/`h2` 或等价 `.page-title`)。 - Don't 用 `font-weight: 650` 或非尺度字号(如 `13.5px`)。 - Don't 把直播粉、胜负红、金价黄当作通用 CTA。 - Don't 为真移动端在现有碎片 `@media` 上硬撑;门禁解除前保持桌面壳。 - Do 保持英雄底栏固定高与列表页整板滚动两种壳模型,勿发明第三种。 - Don't 在 data-only 刷新里 bump `SITE_VERSION`;视觉发版才同步 config / export / `?v=` 缓存戳。末位用于增量改动;中段留给壳层 / 路由 / 可索引等阶段性成型(见 `AGENTS.md`)。