diff --git a/docs/research/08-美化专项方案.md b/docs/research/08-美化专项方案.md new file mode 100644 index 0000000..1de0aa6 --- /dev/null +++ b/docs/research/08-美化专项方案.md @@ -0,0 +1,149 @@ +# 博客美化专项方案(视觉打磨批次) + +> 侦察员 @agent-591c3f | 2026-10-26 +> 证据链:仓库源码逐文件审计(tokens/global.css + 9 组件 + 2 文章页)× design/mockup.html 丙路线对照 × 本地重建 34 页实测(dist 内 Shiki 内联样式实抓)× WCAG 对比度数学计算 × 5 站补充抓取。 +> 截图证据床 /tmp/beauty-shots/(22 张,1280×900 fullPage,SW 阻断,gz-server 18800 测试床):现状 12 张 `{home,reading,tech,books,gallery,moments}-{light,dark}.png`;mockup 基线 10 张 `mock-{home,reading,tech,gallery,moments}-{light,dark}.png`。 +> 纪律分工:token 值/选择器/对比度数字=本报告结构性结论;"观感好坏"=⚠视觉待验,交视觉模型按 §5 问题清单复核,卡片产出不受阻。 + +## 0. 补充探索(每站聚焦视觉细节) + +**抓取失败如实标注**:veselinov.pro、xivudong.me、photos.antfu.me 三域本机 DNS 无解析(getent 空记录,代理 7897 亦 000),已按任务预案换站并注明理由。 + +1. **rauno.me** ✅(HTML+2 CSS 实抓)——灰阶密度才是质感:stitches 体系 12 级灰(gray1–12 双主题 hsl 全套);间距阶严格 8px 步进(--space-1..11 = 8→88px);圆角三档 4/8/16+round;阴影三档全部 12% 黑透明(阴影当层级语言而非装饰);全站唯一动效曲线 `cubic-bezier(.2,.8,.2,1)`;focus-ring 变量化。字体=自研 X + JetBrains Mono + Georgia 点缀。 +2. **paco.me** ✅(3 CSS 实抓)——灰阶走**黑/白 alpha 阶梯**(--black-a1..a12 = 5%–95% 共 12 档):灰由前景色透明度派生,暗色主题零重复维护;Newsreader 斜体做强调词是签名手法;字号全站仅 13/14/16/1.25rem/4rem 五档;边框唯一 `--border-thin:1px`;页边距 `max(24px, env(safe-area-inset-*))` 安全区与留白合一。 +3. **mattdesl.com** ✅(换站理由见上)——全站等宽身份(BerkleyMono→Courier 回退)+ 97% 灰底/10% 墨字;标题 font-weight **normal**、统一 margin-top 1.5em——层级全靠字号与节奏不靠字重;标题小写化;标题锚 `#` 前缀常显;a:active 才变灰。与我们的 mono 轨同源:等宽当身份时,字重必须让位给间距。 +4. **tw93.fun** ✅(替代 xivudong.me,DNS 失败)——body 15px,身份字体藏锋金楷 TsangerJinKai02(标题正文混排),中文个人站"手写体温"代表;内联 prefers-reduced-motion 全量豁免(与我们同款纪律);header 图标化导航。启示:中文身份字体走金楷/文楷一脉成立,我们 `--font-kai` 已在栈内,金句正是它的岗位。 +5. **antfu.me/photos** ✅(photos 子域 DNS 失败,主域 /photos 200)——照片 img 带 inline `radial-gradient` **blur-up 占位**:图未加载先出主色近似色块,加载即有构图而非白洞;导航相机图标常驻;照片**无圆角无边框无阴影**直贴(摄影=内容本体不加框)。启示:图库质感优先做加载占位,而非边框阴影装饰。 + +## 1. 现状视觉审计(元素/现状/差距/目标) + +| # | 元素 | 现状(源码事实) | 差距 | 目标 | +|---|---|---|---|---| +| 1 | 间距阶 | `--space-1..6`=4/8/16/24/40/64,跳档不均(缺 12/32) | rauno 8px 步进全阶 | 主阶不动,补正文流距 token(K) | +| 2 | 标题节奏 | `.prose-* h2/h3` 仅 margin-top 1.8/1.5em,**无下距**(global.css:69-79) | 标题贴死正文;mockup h2 为 `1.8em 0 .6em` | h2/h3 补下距(K) | +| 3 | 正文段距 | `p+p{margin-top:.9em}` 双轨 6 处字面量 | 不可一处调 | `--flow-*` token 化(K) | +| 4 | 灰阶层级 | ink-1..4+line 五档;**ink-4(2.52:1) 用于 13px 日期/图注正文级文字**(PostList row-date、tl-date、g-note)不达 AA;无 border-strong 档 | ink-3 5.09:1 达标;ink-4 应退纯装饰位 | ink-4 停用于文字,新增 `--line-strong`(L) | +| 5 | 圆角 | 4/6/8/10/12/999 字面量散落 7+ 处组件 | 未 token | `--radius-s/m/l` 三档(O) | +| 6 | 动效时长 | 0.15s/160ms/0.4s/0.6s/2.4s 与 `--dur:350ms` 并存;**且 `.postlist .row` hover 1px 上浮是死规则**(global.css:196 类名应为 `post-list`,dist 实证从未生效) | 时长纪律散 + 微交互断线 | 修死规则 + `--dur-fast/slow` 补阶(O) | +| 7 | 书评纸面板 | `.prose-reading` 仅上下 hairline + bg(global.css:52-63) | mockup 丙=全边框圆角卡(pad 44/radius 14)形态差 | 两案裁定(Q)⚠视觉待验 | +| 8 | 代码块 | Astro 默认 Shiki github-dark,dist 实测内联 `background:#24292e` **压过 token `--code-bg:#0d1117`**;无语言标签;`.term-dots` 为死选择器 | token 与实际分裂 | Shiki css-variables 主题接管 + 灰阶窗条 + 语言标签(P) | +| 9 | 表格 | global.css **零表格规则**;内容 3 篇含 markdown 表(dist 实证 `` 裸渲染) | UA 默认裸表 | 分隔线制表格样式(R) | +| 10 | 列表 | reset `*{margin:0}` 后无 prose 列表规则;内容 5 篇含列表 | li 间距仅靠行高,紧贴 | li+li 间距 + marker 色(R) | +| 11 | 金句 | `.pull-quote` 全仓无使用(死选择器);blockquote 只有 A 墨线模式 | D 金句模式从未落地 | 写作指南模板 + mood 注入(Q) | +| 12 | 引文规则 | global.css 与 [...slug].astro:172-177 **镜像双份** | 漂移风险 | 单源化(Q) | +| 13 | 图库衬底 | `.stage` 仅 container-type,无背景 | mockup `--stage:#f4f4f2` 面板+radius 14 | 两案裁定(N)⚠视觉待验 | +| 14 | 页面标题 | books/gallery/moments 用 `--text-h1` 27px | mockup g-title 20px/700 | 降一档 22px 或保持(K)⚠ | +| 15 | 首屏 | IdCard=60px 渐变头像(紫→accent 彩色占位)+21px 名字,slot 被 socials 占用,**无身份陈述行** | mockup hero 有 bio 15px 行 | M 两案 | +| 16 | 热力图 | ink 灰四档(组件注释明示决策) | mockup 原型为绿四档 | S 裁定 ⚠视觉待验 | +| 17 | 达标项(不动) | 灯箱 backdrop 95%、focus ring 全局 2px、::selection 半透明、明暗双套 tokens、reduced-motion 全豁免(row hover 上浮除外——行 6 实锤为死规则) | — | 保持 | + +## 2. 美化卡片(K–S,续 v2 A–J) + +### K|正文流距 token 化与标题下距 +- **目标**:标题-正文、段落-段落的呼吸成为可调参数;治愈 h2 贴正文。 +- **改法**(tokens.css + global.css):新增 `--flow-p: 0.9em; --flow-h2-pre: 1.8em; --flow-h2-post: 0.6em; --flow-h3-pre: 1.5em; --flow-h3-post: 0.45em;`;global.css 双轨 h2/h3 改用变量并补 margin-bottom;`p+p` 改 `var(--flow-p)`。页面标题(Books/Gallery/Moments h1.page-title)27px→`--text-h2`(22px) 降档对齐 mockup g-title(视觉待验§5-6)。 +- **涉及**:`src/styles/tokens.css`、`src/styles/global.css`、三页组件 `page-title` 规则。 +- **验收**:playwright 断言 `.prose-tech h2` computed marginBottom ≈13.2px(22×0.6)、marginTop≈39.6px;`:root` `--flow-p`===' 0.9em';books 页 `h1.page-title` fontSize==='22px'。 +- **工作量**:0.5d。 + +### L|灰阶达标与 border-strong +- **目标**:全部正文级文字 ≥4.5:1(WCAG AA 实测数:ink-3 亮 5.09/暗 5.22 ✓,ink-4 亮 2.52/暗 2.67 ✗);分隔线获得强弱两档。 +- **改法**:PostList `.row-date`、MomentsPage `.tl-date`、GalleryPage `.g-note`、index `.lab` 的 `color: var(--ink-4)`→`var(--ink-3)`;tokens 新增 `--line-strong: #d4d6db` / dark `#3d434f`,供 kbd 边框、chip 选中态(现用 ink-3 充当)、TOC 选中线。ink-4 仅保留纯装饰(track 前方块、beat-dot)。 +- **涉及**:tokens.css、PostList.astro、MomentsPage.astro、GalleryPage.astro、index.astro。 +- **验收**:`.row-date` computed color==='rgb(107, 110, 120)';对比度数学 5.09:1;`--line-strong` 存在且 chip:checked border-color===rgb(212,214,219)。 +- **工作量**:0.5d。 + +### M|首屏叙事两案(⚠视觉待验 §5-1 定案) +- **案1 极简维持+身份陈述**(推荐先行):IdCard 结构改两行——名字 21px 下加 `.idcard-bio`(15px/ink-3,一句身份陈述,文案用户定);socials 移到 bio 行下;头像渐变占位灰阶化(`--mood-3/accent` 渐变→`ink-3→ink-1` 灰渐变,真头像接入前不破纪律)。`margin-block` 40→56px 加呼吸。 +- **案2 hero 强化**:头像 72px、名字 `--text-h1` 27px、bio 一行 mono 14px tagline(如 `阅读 · 技术 · 摄影`),首屏区块底加 `--line` 分隔。视觉重量↑,与"骨架克制"张力↑。 +- **涉及**:IdCard.astro、Avatar.astro、index.astro。 +- **验收**:案1 `.idcard-bio` 存在且 fontSize==='15px'、color===ink-3;头像 svg 首个 stop 颜色为灰阶(无 hue)。 +- **工作量**:案1 0.5d / 案2 1d。 + +### N|图片质感与灯箱纯度 +- **目标**:照片墙获得"策展台"层次而非散图直贴;灯箱进入"暗房"纯度。 +- **改法**:tokens 新增 `--stage: #f4f4f2` / dark `#101318`(mockup 丙同位);GalleryPage `.stage` 加 `background: var(--stage); padding: var(--space-3); border-radius: var(--radius-l, 14px)`(⚠两案:有衬底 vs 无衬底,§5-4);新增 `--radius-img: 10px` 统一 .shot/.thumb/.mom-fig/prose img 圆角(现 8/8/8/10 混用);灯箱 backdrop `rgba(8,10,14,.95)`→`.97` + 底条 mono 字距 `0.02em`;blur-up 占位列观望(antfu 手法需管线配合,非纯 CSS)。 +- **涉及**:tokens.css、GalleryPage.astro、MomentsPage.astro、index.astro、global.css。 +- **验收**:`.stage` computed backgroundColor==='rgb(244, 244, 242)';`:root` `--radius-img` 存在且 `.thumb` borderRadius==='10px';dialog#lb backdrop 不便断言→断言 CSS 源含 0.97。 +- **工作量**:1d。 + +### O|微交互 token 化与 focus ring 收尾 +- **改法**:先修死规则——global.css `.postlist .row`→`.post-list .row`(hover 1px 上浮即刻复活);tokens 新增 `--dur-fast: 150ms; --dur-slow: 600ms;`;替换字面量——row hover `0.15s ease`→`var(--dur-fast) var(--ease)`、GalleryPage `#lb-img` 160ms→`var(--dur-fast)`、`.bg-glow` 0.6s→`var(--dur-slow)`、rise-in 0.4s→`calc(var(--dur) + 50ms)`;圆角 token:`--radius-s:6px; --radius-m:10px; --radius-l:14px`,全局字面量归位;`:focus-visible` 补 `border-radius: 2px`(mockup:29,防直角 outline 扎圆角钮)。 +- **涉及**:tokens.css、global.css、Header.astro、GalleryPage.astro、各组件 radius 字面量。 +- **验收**:`.post-list .row` computed transitionDuration==='0.15s' 且 hover 后 transform==='matrix(1, 0, 0, 1, 0, -1)' 且 timingFunction 含 'cubic-bezier(0.19, 1, 0.22, 1)';`:focus-visible` computed borderRadius==='2px';`grep -c 'px' radius 字面量` 下降(构建审计)。 +- **工作量**:0.5d。 + +### P|代码块窗口化(Shiki 接管 + 语言标签 + 灰阶窗条) +- **目标**:`--code-bg/--code-ink` token 恢复统治(现被 Shiki 内联 #24292e 压制);代码块获得窗口身份。 +- **改法**:astro.config.mjs `markdown.shikiConfig.theme: 'css-variables'`(Shiki 官方主题,颜色全走 `--shiki-*` 变量);global.css 定义 `--shiki-default/--shiki-key/...` 对齐现有 github-dark 色系但 bg/ink 用 `var(--code-bg)/var(--code-ink)`,亮暗同底纪律恢复;`pre.astro-code[data-language]::after{content:attr(data-language); …mono 11px; color:#8b949e; text-align:right; display:block}` 语言标签(零 JS,dist 实证 data-language 属性已在);窗条三灰点用 `pre::before{content:'';display:block;width:10px;height:10px;border-radius:50%;background:#3f4650;box-shadow:16px 0 0 #3f4650,32px 0 0 #3f4650;margin-bottom:8px}`(灰阶三档 `#3f4650/#4a515b/#565f6a` 递进,macOS 彩点不采——红线);pre padding 顶加 `6px`。删除 `.term-dots` 死规则。**行号不做**(短命令块为主,320px 移动端宽度宝贵,见 §4)。 +- **涉及**:astro.config.mjs、global.css。 +- **验收**:dist 文章页 `pre.astro-code` 无内联 background-color(`getAttribute('style')` 不含 'background-color');pre computed backgroundColor==='rgb(13, 17, 23)';`getComputedStyle(pre,'::after').content` 非 'none' 且含 attr;`getComputedStyle(pre,'::before')` width==='10px'。 +- **工作量**:1d。 + +### Q|书评轨:纸面板形态 + 金句实装 + 引文单源 +- **目标**:书评页的"纸感"从色块升级为形态;D 金句模式真正可用。 +- **改法**: + - 纸面板两案:**A 卡化**=`.prose-reading{border:1px solid var(--paper-line);border-radius:var(--radius-l);padding:var(--space-5) clamp(20px,4vw,32px)}`(mockup sheet 形态);**B 维持通栏** hairline 仅把上下线升级 `--line-strong`。(⚠§5-2 裁定) + - 金句:内容约定 HTML 直书 `

…

——作者《书名》
`(写作指南已有 raw HTML 先例);pull-quote 样式修 62px→`3.2em` 相对化 + `--mood` 从文章 frontmatter 经 [...slug].astro `article style="--mood:…"` 注入(现 PostList 已用同源 mood,接线一致);docs/写作指南.md 加模板一节。 + - 引文单源:删除 [...slug].astro:172-177 镜像规则,markdown 裸 blockquote 全靠 global.css。 +- **涉及**:global.css、pages/archives/[...slug].astro、en 同文件、docs/写作指南.md。 +- **验收**:`grep -c 'blockquote' src/pages/archives/[...slug].astro`===0;含 pull-quote 的页面 computed fontFamily 含 'WenKai'、`::before` fontSize==='64px'(20×3.2);A 案 `.prose-reading` computed borderRadius==='14px'。 +- **工作量**:0.5d。 + +### R|表格与列表基建(从零到精) +- **改法**(global.css,作用于 `.prose-reading/.prose-tech`):表格 `table{border-collapse:collapse;width:100%;font-size:.92em;margin-block:1.2em} th{text-align:left;font-weight:600;color:var(--ink-1)?→书评轨用 paper-ink} th,td{padding:6px 12px 6px 0;border-bottom:1px solid var(--line)} tbody tr:last-child>*{border-bottom:0} td{font-variant-numeric:tabular-nums}`——分隔线制,**不做 Zebra**(灰阶密度已够,见 §4);列表 `ul,ol{padding-left:1.5em;margin-block:1.2em} li+li{margin-top:.35em} li::marker{color:var(--ink-3)}`;tech 轨 kbd 已有样式保持。 +- **涉及**:global.css(含 3 篇含表内容无需改动)。 +- **验收**:tech 文章页 `th` computed borderBottomWidth==='1px';`li+li` marginTop≈6.65px(.35em@19px);`li::marker` color==='rgb(107, 110, 120)'。 +- **工作量**:0.5d。 + +### S|热力图色系裁定(⚠视觉待验 §5-5) +- **现状**:ink 灰四档(hm-l1..4=ink-4..1),组件注释明示"灰阶纪律"决策;mockup 原型为 GitHub 绿四档。绿=贡献量语义直觉(外部认知零成本),灰=骨架纯度。 +- **改法(若裁定换绿)**:tokens 新增 `--hm-0:#ebedf0/--hm-1:#9be9a8/--hm-2:#40c463/--hm-3:#30a14e/--hm-4:#216e39` + dark 套(#22272e/#0e4429/#006d32/#26a641/#39d353),Heatmap.astro 四行替换。默认建议**维持灰阶**(热力图是骨架层不是内容层;绿色块会成为首页唯一大面积彩色,重心被劫持)。 +- **验收**:若换绿 `--hm-4`===' #216e39' 且 `.hm-l4` backgroundColor 对应;维持则零改动,S 卡关闭。 +- **工作量**:0.2d。 + +## 3. 优先级(视觉收益 × 工作量) + +| 卡 | 视觉收益 | 工作量 | 象限 | +|---|---|---|---| +| L 灰阶达标 | 高(可读性硬指标) | 0.5d | ★高收益低成本 | +| R 表格列表 | 高(3+5 篇内容直接受益,现裸样式) | 0.5d | ★ | +| K 流距/标题下距 | 高(全文页节奏) | 0.5d | ★ | +| M 案1 首屏陈述 | 高(第一屏人格) | 0.5d | ★ | +| P 代码块窗口化 | 高(技术轨视觉主件) | 1d | ★(成本略高但收益覆盖全部技术文) | +| Q 纸面板+金句 | 中高 | 0.5d | 次批 | +| O 微交互 token | 中(一致性负债清偿) | 0.5d | 次批 | +| N 图库质感 | 中 | 1d | 次批(含⚠两案) | +| S 热力图 | 低(大概率维持现状) | 0.2d | 随批 | + +**前 5(高收益低成本)**:L → R → K → M案1 → P。合计 ≈3d,其中 L/R/K 纯 global+tokens 层,一次提交可收。 + +## 4. 明确不做(与灰阶克制红线冲突,含理由) + +1. **玻璃拟态/大面积毛玻璃**:backdrop-filter 大面积使用与"纸墨实体感"冲突;微信内置浏览器兼容与滚动性能翻车史;Header 8px blur 轻量例外保留。 +2. **渐变色文字/渐变大块**:全站唯一强调色(--accent 单色)是丙路线根基;渐变=多色并存,01 报告诊断的多色病复发。 +3. **大圆角卡片风(≥16px)**:圆阶上限钉 `--radius-l:14px`;大圆角是消费 App 友好风,与终端/制版感相反。 +4. **macOS 三彩圆点/彩色窗条**:代码窗条采灰阶三档(P 卡);彩点是全站唯一彩点的地位争夺者。 +5. **噪点/纸纹覆盖层**(02 报告 Tier1 曾列,本批否决):纸感已由 `--paper` 米白承担;噪点在低分屏/微信内染摩尔纹,reduced-motion 需额外豁免,收益/成本比不成立。 +6. **表格 Zebra 斑马纹**:隔行灰块密度过高,与分隔线骨感二选一取线(R 卡)。 +7. **代码行号**:内容以短命令块为主,行号吃掉 320px 移动端宽度;Shiki attrs 可后补不锁死。 +8. **行尾点号悬挂/首行缩进**:03 报告已证伪(无出版惯例/避头尾风险)。 +9. **弹跳缓动/大面积视差/入场加码**:红线"不弹跳宁轻勿闹";现有 12px rise-in + 1px hover 是上限。 +10. **自定义光标**:02 Tier3 已判,正文必须标准 I-beam。 + +## 5. 截图问题清单(⚠视觉待验——交视觉模型,附证据文件) + +| # | 问题 | 证据对 | +|---|---|---| +| 1 | 首屏 M 案裁定:现状 IdCard+列表直连的密度 vs mockup hero 的呼吸,哪个更"被设计过"?案2 hero 是否过度? | home-{light,dark}.png ↔ mock-home-{light,dark}.png | +| 2 | 纸面板 Q-A/B:通栏 hairline(现状)vs 全边框圆角卡(mockup),哪个更"书页"?暗色下 paper #f8f6f1↔#201d18 转换是否自然? | reading-{light,dark}.png ↔ mock-reading-{light,dark}.png | +| 3 | 代码块 P:加灰阶窗条+语言标签后是否加分?(可先看 mockup term 窗对比现裸块) | tech-{light,dark}.png ↔ mock-tech-{light,dark}.png | +| 4 | 图库 N:stage 米灰衬底 vs 直贴,哪个衬托照片更好? | gallery-{light,dark}.png ↔ mock-gallery-{light,dark}.png | +| 5 | 热力图 S:灰四档 vs 绿四档的量级辨识与首页色彩重心 | home-{light,dark}.png(热力图区) | +| 6 | 页面标题降档(27→22px):books/gallery/moments 三页标题现值是否过重? | books-{light,dark}.png(无 mock 对照,独立判断) | +| 7 | 现状整体灰阶层级是否"够用"(rauno 12 档 vs 我们 5 档):列表行 hairline+日期档位是否单薄? | home-*.png 列表区 ↔ mock-home-*.png | + +## 附:测试床与复现 + +- 截图环境:`npm run build`(34 页)→ `python3 scripts/build-perf/gz-server.py 18800 dist`(写稿时仍在跑,用后可杀:`pgrep -f gz-server` 取 PID kill);脚本 `/tmp/beauty-shots/shoot.cjs` 与 `shoot-mockup.cjs`(`NODE_PATH=$(pwd)/node_modules node …`)。 +- 对比度计算:sRGB 相对亮度公式手算(§1-4 数值即此口径),可直接进验收注释。