4df8dc6f87
新建 web/website/(Astro 零 SSR): - 组件迁移:交互块保留 .jsx 经 @astrojs/react(Header/AnnouncementBar/SignupForm/PricingPlans),纯展示块转 .astro 去运行时 JS;像素以原型为基准。 - 令牌同源:build-tokens.mjs 从 design/colors_and_type.css 生成 tokens.gen.css,仅剔除第三方 Google Fonts @import,数值不改。 - 字体自托管:@fontsource(Sora/Manrope/Noto Sans SC/JetBrains Mono),无第三方 CDN。 - 图标:Lucide 构建期内联 SVG(替代 unpkg CDN),零运行时、零 CDN。 - i18n:/(zh)与 /en/(en)双路由单显,语言切换组件;文案沿用 ui_kits 脱敏文案。 - 安全:public/_headers 严格 CSP(全 self + 自托管资源 + 内联片段 sha256,无 unsafe-inline)+ HSTS;无支付表单。 - CI:.gitea/workflows/website.yml 构建(红线扫描+lint+CSP 哈希)→ 同时发布 Cloudflare Pages 主站与镜像。 - 灾备:README 写明干净环境 npm ci && npm run build 可直接部署到任意静态托管;dist 指纹确定性,主站镜像一致。 测试:npm run lint(0 error)/ npm test(build+CSP 哈希注入+红线扫描 0 命中)/ 两次干净构建 dist 指纹一致。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
55 lines
1.7 KiB
CSS
55 lines
1.7 KiB
CSS
/* site-extra.css — 仅承载「替换原型内联 style= 属性」的工具类。
|
||
原型 index.html 里有少量 inline style;严格 CSP(style-src 'self',不含 'unsafe-inline')
|
||
会拦截内联样式,故逐一搬到这里为等价 class,website.css 保持逐字不动。 */
|
||
|
||
/* hero <h1 style="white-space:pre-line"> */
|
||
.h1-preline { white-space: pre-line; }
|
||
|
||
/* hero orb 速率单位 <span style="font-size:10px;color:var(--fg3)"> */
|
||
.orb-unit { font-size: 10px; color: var(--fg3); }
|
||
|
||
/* orb-node <i ... style="width:18px;height:18px;color:var(--fg3)"> */
|
||
.orb-node-chev { width: 18px; height: 18px; color: var(--fg3); }
|
||
|
||
/* orb-node 中部 <div style="flex:1"> */
|
||
.orb-node-grow { flex: 1; }
|
||
|
||
/* 功能对比标题 <h3 style="font-family:var(--font-display);font-weight:700;font-size:22px;margin:46px 0 0;text-align:center"> */
|
||
.cmp-h {
|
||
font-family: var(--font-display);
|
||
font-weight: 700;
|
||
font-size: 22px;
|
||
margin: 46px 0 0;
|
||
text-align: center;
|
||
}
|
||
|
||
/* 语言切换由原型 <button> 改为路由 <a>(zh=/ , en=/en/);复刻 .langseg button 视觉。 */
|
||
.langseg a {
|
||
border: none;
|
||
cursor: pointer;
|
||
border-radius: var(--radius-full);
|
||
padding: 5px 11px;
|
||
font-family: var(--font-sans);
|
||
font-size: 12.5px;
|
||
font-weight: 700;
|
||
background: transparent;
|
||
color: var(--fg3);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
text-decoration: none;
|
||
}
|
||
.langseg a.on { background: var(--accent); color: var(--fg-on-accent); }
|
||
|
||
/* 视觉隐藏(无障碍用,当前未强依赖) */
|
||
.visually-hidden {
|
||
position: absolute;
|
||
width: 1px;
|
||
height: 1px;
|
||
padding: 0;
|
||
margin: -1px;
|
||
overflow: hidden;
|
||
clip: rect(0, 0, 0, 0);
|
||
white-space: nowrap;
|
||
border: 0;
|
||
}
|