diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..a6f844d
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Keep captured command output verbatim, including terminal whitespace.
+evidence/r2/*.log -whitespace
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d049e3b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+.astro/
+dist/
+.DS_Store
+evidence/r2/local-screens/
diff --git a/WRITER-EVIDENCE.md b/WRITER-EVIDENCE.md
new file mode 100644
index 0000000..c72fdc3
--- /dev/null
+++ b/WRITER-EVIDENCE.md
@@ -0,0 +1,202 @@
+# WRITER-EVIDENCE — askclaw-astro-01-R2
+
+Writer repair and verification evidence only. This is not a red-lane verdict or an approval. Vesper owns the fresh blind rechecks.
+
+- Observed: 2026-09-19 UTC; build and deployment start times are recorded in `evidence/r2/`.
+- Workspace: `/home/computebox/2609/askclaw.dev-astro`
+- Branch: `feat/astro-batch1`
+- Repair commit: `165f56953571853ea9c008f4e7f3aa5b5fe85133`
+- Deployment target: `26430:/var/www/askclaw-site/astro-preview/`
+- Public preview: https://askclaw.dev/astro-preview/
+- Contract checked directly: `/home/computebox/.hermes/red-lane/BREAK-CONTRACT.md`, SHA-256 `57afef2c8ceeb967383cd406def446e377af2e107b80fc6fb223bb7d03d456f3` (matches the work order).
+- Runtime identity reported to this session: `openai-codex / gpt-6-astra`. The work order requested `gpt-5.6-luna-900k`; this evidence does not claim that model override or max-effort execution occurred.
+
+## 1. R2 fixes and direct ground truth
+
+### Score periods: W37 composites, not W36 / 23-case records
+
+Read directly before editing:
+
+| Source | Observed fact |
+|---|---|
+| `../amber-ollama/results/2026-W36.md:24` | glm-5.3-flash = 15/21 |
+| `../amber-ollama/results/2026-W37.md:27-32` | W36 15/21 + two new ops cases = W37 composite 17/23 |
+| `../amber-ollama/results/2026-W37.md:44-60` | d41f's separate full-library debut = W37 17/23 |
+| `../amber-crof/results/2026-W36.md:24` | qwen3.8-27b = 14/21 |
+| `../amber-crof/results/2026-W37.md:28-34` | W36 14/21 + two new ops cases = W37 composite 16/23 |
+| `../askclaw.dev/index.html:131-143` and `../askclaw.dev/en.html:122-134` | Published repo summaries retain Ollama 17/23 and CrofAI 16/23 |
+
+Both method cards now say `W37 · 23 cases`. Their scores and model names are unchanged. A visible explanation distinguishes the composites from the older axis records, links to both W37 result files, and notes that d41f's 17/23 is a full W37 sitting.
+
+`/rank/` still shows glm-5.3-flash 15/21 and qwen3.8-27b 14/21 with `W36 · 21`. Its canonical data file was not rewritten. The method and English pages explain this difference instead of inventing a single shared period.
+
+### Kimi vendor label: explicit whole-label mapping
+
+`src/pages/rank/index.astro` now maps only `lane.id === 'kimi'` to `Kimi official coding`. Every other vendor is passed through unchanged. The broad substring replacement was removed.
+
+The browser test compares every shipped lane field against canonical `axes.json`, allowing only that explicit Kimi label difference. It also reads the rendered table label: `Kimi official coding`, without the duplicated word. Model, total, denominator, week, repository, source-file path and all axis values remain unchanged.
+
+### English mirror: migrated content, not a placeholder
+
+`src/pages/en/index.astro` now ports the public content of `../askclaw.dev/en.html`:
+
+- The English AMBER hero and sealed-history explanation, including the private-cases/public-scores statement.
+- `23 cases / 26 papers`, `11 result repos`, and the weekly-publication statement.
+- The W38 board snapshot, swe-2-max's W37 18/23 result, five-way 17/23 tie, and the published swe-2-high re-run correction/link.
+- Board, nine-axis matrix, trust process, all three findings, result repos and rules sections.
+- All 11 scored result-repo cards, plus the separate `amber` specification card. The browser compares all 12 cards' names, scores, descriptions and URLs with the legacy source.
+- Core Specification, public hash index, roadmap, correction, method and rank links.
+- All six original English PNGs, copied byte-for-byte into `public/assets/`, with source-verified width/height, alt text and `loading="lazy"`.
+
+Charts are static images with ordinary links to full-size versions and source details. Legacy hover/interactive promises were replaced with accurate static-chart instructions. No Vega scripts, chart specs, client framework, web fonts or image-generation replacements were copied.
+
+The root `/` remains the second-batch visual placeholder. Its source and built HTML are unchanged.
+
+### Other direct reads and source-path reconciliation
+
+- Read `../askclaw-dev-rebuild-arrangement-20260918.md`, including §§1, 6 and 9, and both legacy home HTML files directly. No writer session logs were used.
+- `../askclaw.dev/amber/index.html` is a redirect, not a method article. Its actual content is:
+
+```html
+
→ askclaw.dev
+```
+
+- `../askclaw.dev/axes.html` is absent. Read the observed source at `../amber-axes/axes.html` and its `axes.json`; the original page explicitly identifies Ollama/Crof as W36 / 21-case records.
+- The public hash index was retrieved directly from `https://raw.githubusercontent.com/getaskclaw/amber/main/hash-index/v2026-09.md` because no local `../amber/hash-index/v2026-09.md` exists. It states 23 cases / 26 papers, two ops additions after W36, and that W36 used the 21-case library.
+- Both the source and copied axes data have SHA-256 `2ae8b63ef898bd60106d0cc374801cbb7fd061bac6d1465fc4d3fd2c6ec222be`.
+
+## 2. Verification results
+
+| Requirement | R2 result | Evidence |
+|---|---|---|
+| Required static build | PASS; 4 pages, exit 0, specified heap cap | `evidence/r2/build.log` contains the full output |
+| Method periods and composite explanation | PASS; both cards W37 / 23 cases; original scores retained | `final-live.log` scorePeriods and compositeExplanation; `static-verification.json` parsed cards |
+| Kimi label and lane preservation | PASS in shipped data and rendered table | `final-live.log`: laneDataPreserved, kimiVendor |
+| Full English migration | PASS; 11 scored repos + spec card; source-matched copy/cards/images/links | `final-live.log`: englishCards, englishCopy, englishImages, englishLinks, englishLeadPreserved |
+| Rank interaction | PASS; 8 chips, required preset 12 rows, independently recomputed ordering, clear and keyboard toggle | `final-live.log`: chipCount, presetRowCount, rankOrderPreserved, chipInteractionPassed |
+| Four live routes | PASS; all 200, nonempty content, empty console/page/request-failure/HTTP-error arrays | `final-live.log`; compact `browser-summary.txt` |
+| MPA behavior | PASS; direct loads and refreshes on all routes, native method navigation and back from home/rank/English | `final-live.log` |
+| Zero content-page JS | PASS; 0 script elements on `/`, `/method/`, `/en/`; all work with JS disabled | `static-verification.json`, `live-checks.json` |
+| Native rank-only JS | PASS; 1 inline module, 3,522 bytes; 0 external JS files or script requests | Static and browser evidence |
+| No framework or network fonts | PASS; runtime deps remain Astro + sitemap only; no prohibited framework packages, font assets/references or font requests | `verify-dist.py`, `static-verification.json`, browser request records |
+| No forbidden terms in built HTML | PASS across all four complete HTML files, decoded attributes and live post-interaction DOM | Static and browser forbiddenTerms checks |
+| Generated sitemap | PASS; build log records `@astrojs/sitemap`; 4 distinct routes; zh-CN/en alternates on both home URLs; 4 hreflang entries | `static-verification.json`, `live-checks.json` |
+| No handcrafted sitemap | PASS; no tracked sitemap XML; robots points to the generated sitemap index | `verify-dist.py` |
+| Local links/assets | PASS; every local href/src resolves within the preview build; all 6 PNGs decode with matching intrinsic dimensions | Static and browser evidence |
+| Source/live byte identity | PASS; 15/15 dist files match both SSH target and public HTTPS responses | `containment.json`, `live-checks.json` |
+| Containment | PASS; all 37 remote sibling files, top-level paths, and 33 legacy checkout files unchanged | Before/after manifests and `containment.json` |
+| Git/no push | PASS; branch is feat/astro-batch1, candidate has no remote, legacy refs and GitHub main unchanged | Git snapshots and `containment.json` |
+| Desktop/mobile rendering | PASS for observed layout checks; no horizontal overflow at 390px; no card/score collisions seen | `live-screens/`; no taste approval claimed |
+
+### Live browser measurements
+
+Fresh headless Chromium contexts at 1440 × 900. Initial transfer includes the navigation document, not just subresources. LCP uses a buffered PerformanceObserver installed by the test, not by the shipped site.
+
+| Route | HTTP | Main text chars | Document bytes | Resource bytes | Total initial bytes | LCP ms | Shipped scripts |
+|---|---:|---:|---:|---:|---:|---:|---:|
+| `/` | 200 | 628 | 1,564 | 2,197 | 3,761 | 112 | 0 |
+| `/method/` | 200 | 1,292 | 2,622 | 2,197 | 4,819 | 100 | 0 |
+| `/rank/` | 200 | 359 before selection | 4,460 | 2,197 | 6,657 | 100 | 1 |
+| `/en/` | 200 | 3,593 | 4,225 | 2,671,364 | 2,675,589 | 264 | 0 |
+
+All four routes recorded zero console messages, console errors, page errors, failed requests, HTTP errors, network-font requests and external script requests. Mobile viewport overflow checks were false for all four routes.
+
+The initial English transfer includes several original PNGs within Chromium's native lazy-load distance. The six PNGs total 2,827,002 bytes; this migration does not claim the English page is below 200 KB. The work-order homepage budget was measured on `/`.
+
+### Regression sequence
+
+Each required repair had a failing real-browser check before its implementation:
+
+- `red-method.log`: both cards incorrectly W36 and composite explanation absent; `green-method.log`: passed.
+- `red-rank.log`: shipped/rendered `Kimi 官方 coding coding`; `green-rank.log`: passed with canonical data preserved.
+- `red-en.log`: 0 result cards, no migrated sections/images; `green-en.log`: all required content present.
+- `pre-final-local.log`: stricter full-lead parity caught lost whitespace around an inline bold element. Explicit spaces fixed it; final local/live runs pass.
+
+Intermediate logs use the older resource-only metric and are not the final performance evidence. Use `final-local.log` and `final-live.log` for the final test script and artifact.
+
+## 3. Reproduction and full artifacts
+
+Commands actually exercised:
+
+```text
+NODE_OPTIONS=--max-old-space-size=2560 npm run build
+node --check scripts/acceptance.mjs
+node --check scripts/live-checks.mjs
+python3 scripts/verify-dist.py
+npm run acceptance
+ACCEPTANCE_SCREENSHOT_DIR=evidence/r2/live-screens npm run acceptance -- --live
+node scripts/live-checks.mjs
+python3 scripts/verify-containment.py
+git diff --check
+```
+
+`--live` derives the URL from the existing Astro site/base configuration. Local mode serves only the built dist using a bounded Node server and shuts it down afterward; no dev watcher was run. Node v22.22.2, npm 10.9.7. No package or lockfile changes were made.
+
+The shell rejected an earlier inline `.dev` URL invocation. That invocation did not run. The subsequent source-configured `--live` verifier and the explicit live-check script ran successfully; no approval or security settings were changed.
+
+Evidence files:
+
+- `evidence/r2/build-start.txt`, `build.log`: exact final application build timestamp and full output.
+- `.gitattributes` exempts only captured `evidence/r2/*.log` files from whitespace checks so the raw Astro output keeps its original trailing spaces; source files remain checked.
+- `evidence/r2/dist-manifest.json`: complete final dist listing with sizes and SHA-256.
+- `evidence/r2/static-verification.json`: parsed built cards, JS count/size, source/asset identity and sitemap assertions.
+- `evidence/r2/final-local.log`, `final-live.log`: complete per-route browser JSON, including content, requests and assertions.
+- `evidence/r2/browser-summary.txt`: compact local/live results.
+- `evidence/r2/live-checks.json`: all 15 public file hashes, JS-disabled content checks, and browser sitemap/robots visits.
+- `evidence/r2/deploy-start.txt`, `deploy.log`: actual deployment time and itemized changes.
+- `evidence/r2/remote-{before,after}.json`, `legacy-{before,after}.json`, Git snapshots and `containment.json`: containment checks.
+- `evidence/r2/live-screens/`: final desktop and mobile screenshots for all four routes. Intermediate local screenshots are ignored scratch, not final evidence.
+- `evidence/r2/design-detector.json`: mechanical detector returned `[]`; final screenshot review also used original-resolution crops.
+
+Complete final dist file listing (all SHA-256 values are in the manifest):
+
+```text
+_astro/BaseLayout.Bc8_lLlO.css 5459
+assets/completion-matrix-7way.en.png 722723
+assets/effort-curves-20260911.en.png 408709
+assets/score-vs-tokens-2026-w37.en.png 492800
+assets/top5-2026-w38.en.png 973588
+assets/trust-chain.en.png 69847
+assets/wallclock-strip-2026-w37.en.png 159335
+en/index.html 14149
+favicon.svg 284
+index.html 2886
+method/index.html 6124
+rank/index.html 17093
+robots.txt 85
+sitemap-0.xml 925
+sitemap-index.xml 196
+```
+
+## 4. Deployment and protected state
+
+A read-only SSH snapshot and local rollback archive preceded deployment. The only remote write command was:
+
+```text
+rsync -az --delete --delay-updates --itemize-changes dist/ 26430:/var/www/askclaw-site/astro-preview/
+```
+
+A dry run was inspected first. The actual deployment added the six English images and changed three HTML files; no preview files were removed. Other preview files had timestamps refreshed but unchanged bytes. All root-level and recursive sibling file hashes and the top-level path set stayed identical.
+
+Old checkout status before and after, exactly:
+
+```text
+## main...origin/main [ahead 1]
+ M index.html
+ M sitemap.xml
+```
+
+GitHub main stayed at `90b9798b3ccbe1092bfa58ef3d48fb4fffa47f2d`; the legacy local refs are unchanged. The Astro repository has no configured remotes. No push occurred.
+
+Rollback archive, verified readable: `/home/computebox/2609/askclaw.dev-astro/.astro/preview-r2-before.tar.gz`. It contains only the prior `astro-preview/` subtree. Rollback, if separately requested, can restore that subtree using the same destination fence; no rollback was performed.
+
+## 5. Remaining limitations and boundary statement
+
+- `/` is intentionally still the batch-2 visual placeholder. `/en/` is now the real content migration, not a placeholder.
+- Original English PNGs are preserved, not recompressed. Native lazy loading does not promise that every below-fold image waits until it is visible. Static images have no Vega hover interactions; full-size/source links are available.
+- No Lighthouse run was performed. The LCP and transfer values above are single-host, unthrottled Chromium observations, not a Lighthouse score or a universal weak-network guarantee.
+- Only the home pair has translated sitemap alternates; method and rank remain single-language routes.
+- This run cannot claim the requested luna/max model override; actual runtime identity is stated above.
+- No red-lane approval, owner taste approval, merge approval or main publication is claimed.
+
+BREAK-CONTRACT §8 triage: this repairs public wording and an already-required static content migration inside the existing preview fence; it adds no authorization, data-access or deployment privileges, changes no approved resource boundary, and does not modify the contract or review gates. Fresh reviewers must still check that assessment independently.
diff --git a/astro.config.mjs b/astro.config.mjs
new file mode 100644
index 0000000..bdbca9a
--- /dev/null
+++ b/astro.config.mjs
@@ -0,0 +1,21 @@
+import { defineConfig } from 'astro/config';
+import sitemap from '@astrojs/sitemap';
+
+export default defineConfig({
+ site: 'https://askclaw.dev',
+ base: '/astro-preview/',
+ trailingSlash: 'always',
+ output: 'static',
+ integrations: [
+ sitemap({
+ i18n: {
+ defaultLocale: 'zh-CN',
+ locales: {
+ 'zh-CN': 'zh-CN',
+ en: 'en',
+ },
+ },
+ namespaces: { xhtml: true },
+ }),
+ ],
+});
diff --git a/evidence/HOME-CSS-EVIDENCE.md b/evidence/HOME-CSS-EVIDENCE.md
new file mode 100644
index 0000000..99ddb8e
--- /dev/null
+++ b/evidence/HOME-CSS-EVIDENCE.md
@@ -0,0 +1,198 @@
+# HOME-CSS-EVIDENCE — askclaw 首页 CSS 补齐 / 构建 / 部署 / 真浏览器验收
+
+任务: kanban `t_01cae686`
+工作区: `/home/computebox/2609/askclaw.dev-astro` (branch `feat/astro-batch2`)
+观察时间: 2026-09-19 UTC (所有时间戳见下方命令日志)
+部署目标: `26430:/var/www/askclaw-site/astro-preview/`
+公开预览: `https://askclaw.dev/astro-preview/`
+
+真源 (直接读取,未修改):
+
+| 文件 | sha256 |
+|---|---|
+| `~/2609/askclaw-design-05/mockups/01-hero-questions-4-desktop.svg` | `95cf0dbfbb5ef05b3a5127204a0491bc8ece99a1ea7da5fec4268a794a82ef28` |
+| `~/2609/askclaw-design-05/mockups/02-hero-questions-4-mobile.svg` | `daaa9a92ec99a8189c353b25029df5a4c4bfdb6a2504f38bc779e4ef2f9732fe` |
+| `~/2609/askclaw-design-05/mockups/03-pending-section.svg` | `71d6ecfb1b4fd494ff18a15dec6103e64c826d9a31b1a945754ece4c24c118f3` |
+
+## 1. 追加-only 证明
+
+`git diff --numstat -- src/styles/global.css` → `771 0 src/styles/global.css`
+= **新增 771 行,删除 0 行**。`git diff` 中 `^-[^-]` 计数 = **0**。
+
+前 493 行与原文件字节相同 (cmp 通过):
+
+```
+head -493 src/styles/global.css > /tmp/head493.css
+cmp /tmp/head493.css /tmp/global.css.bak-before-home-append → FIRST_493_LINES_BYTE_IDENTICAL
+```
+
+追加块前 493 行 → 1264 行。追加块自身 sha256: `b3d0d9a1cf8099f35d56b96c8ddb379916b4e1f3d5139c42cf76b4429e1acfe9`
+
+禁止改动的文件,sha256 与追加前基线完全一致 (见 `evidence/baseline-sha256.txt`):
+
+| 文件 | 基线 sha256 | 完成时 sha256 | 结论 |
+|---|---|---|---|
+| `src/pages/index.astro` | `2f05502d…3773ec` | `2f05502d…3773ec` | 未改 |
+| `src/components/SiteHeader.astro` | `8bd4b562…365022` | `8bd4b562…365022` | 未改 |
+| `src/layouts/BaseLayout.astro` | `29a5f4e5…f0d0d8` | `29a5f4e5…f0d0d8` | 未改 |
+| `src/pages/en/index.astro` | `7c806e6f…0608c5c` | `7c806e6f…0608c5c` | 未改 |
+| 三个 SVG 真源 | 见上表 | 见上表 | 未改 |
+
+本任务只改了 `src/styles/global.css` 一个文件。
+
+## 2. CSS 覆盖与取色(SVG 真源)
+
+32 个必需类全部覆盖,且出现在构建产物 `dist/_astro/BaseLayout.CFGrA3-V.css` 中。
+取色全部来自三个 SVG 里的实际 `fill` / `stroke` 值:
+
+| 项 | 值 | SVG 出处 |
+|---|---|---|
+| 页面底 | `#FBFCF8` | 三个 SVG 的首个 `` |
+| A 卡 | `#E6F4F0` | `01-…desktop.svg` L49 |
+| B 卡 | `#FFF3D2` | L60 |
+| C 卡 | `#E5E9FF` | L70 |
+| D 卡 | `#FFF7DE` | L81 |
+| 描边 | `#D7EAE5` | L49/60/70/81 `stroke` |
+| 圆角 | `20px` | L49/60/70/81 `rx="20"` |
+| 蟹按钮 | `#123C46` | L94 `fill="#123C46"` (bubble) |
+| 蟹底框 | `#FFF6DE` / `#F0E4C2` | L90 |
+| E 徽章 | `#FFF3D2` 底 / `#F7B83E` 边字 | `03-…svg` L37-38 |
+| F 徽章 | `#E5E9FF` 底 / `#6C73D9` 边字 | L46-47 |
+| E 状态丸 | `#FFF3D2` / `#EEDCA9` | L41 |
+| F 状态丸 | `#E5E9FF` / `#CDD4F5` | L50 |
+| 五席并列点 | `#149C9B` `#6C73D9` `#78A9C8` `#EF7569` `#9DCFC1` | `01-…desktop.svg` L118-134 |
+
+桌面卡高 96px 落在要求的 **92–104px** 区间内;间距列 16px / 行 14px,落在 **12–16px** 区间内。
+
+## 3. 每条命令的原始退出码
+
+| # | 命令 | 退出码 | 日志 |
+|---|---|---|---|
+| 1 | `cd ~/2609/askclaw.dev-astro && NODE_OPTIONS=--max-old-space-size=2560 npm run build` | **0** | `evidence/build-home.log` |
+| 2 | `scp -r dist/* 26430:/var/www/askclaw-site/astro-preview/` | **0** | `evidence/deploy-home.log` |
+| 2b | 远端核对 `ssh 26430 sha256sum …` | **0** | `evidence/final-home-run.log` |
+| 3 | Playwright 真浏览器 (`node /tmp/home-check.mjs`) | **0** | `evidence/home-browser-summary.txt`, `evidence/home-browser-report.json` |
+
+构建输出: `4 page(s) built`,页面 `/`、`/en/`、`/method/`、`/rank/`。
+
+远端 `index.html` sha256 = 本地 `dist/index.html` sha256 = `7286dc28a80df8df387042db7c11c6a0faf549d53cf42a1e0dda7199bad52807`
+远端 CSS `BaseLayout.CFGrA3-V.css` sha256 = 本地 `dist/_astro/BaseLayout.CFGrA3-V.css` sha256 = `d1e538112584d49cba703f64839b6605b2574a584349c11855b0cf66a4646b74`
+
+部署范围: 只写了 `astro-preview/` 内部。父目录 `/var/www/askclaw-site/` 的
+`README.md / SECURITY.md / amber/ / assets/ / axes.html / axes.json / en.html / index.html / robots.txt / sitemap.xml`
+时间戳全部保持 09-18T01:12 ~ 09-19T05:56,未被触碰。
+
+## 4. 真浏览器读数 (https://askclaw.dev/astro-preview/)
+
+截图绝对路径:
+- `/home/computebox/2609/askclaw.dev-astro/evidence/home-1440.png` (1440×1000)
+- `/home/computebox/2609/askclaw.dev-astro/evidence/home-390.png` (390×900)
+- 附加: `evidence/home-pending-1440.png`、`evidence/home-pending-390.png`、`evidence/home-full-{1440,390}.png`
+
+页面 URL 由 Playwright `page.url()` 记录为 `https://askclaw.dev/astro-preview/`,HTTP **200**。
+
+### 1440 四卡 boundingBox + background-color
+
+| 卡 | 文案 | x | y | w | h | background-color |
+|---|---|---|---|---|---|---|
+| A | 同一个模型,官方端点和第三方有差吗? | 140 | 216.28 | 390.58 | **96** | `rgb(230, 244, 240)` = #E6F4F0 |
+| B | 新出的模型能不能打? | 546.58 | 216.28 | 390.59 | **96** | `rgb(255, 243, 210)` = #FFF3D2 |
+| C | 我干这个活该用谁? | 140 | 326.28 | 390.58 | **96** | `rgb(229, 233, 255)` = #E5E9FF |
+| D | 这榜自己可信吗? | 546.58 | 326.28 | 390.59 | **96** | `rgb(255, 247, 222)` = #FFF7DE |
+
+- 2×2 确认: 两列 x ∈ {140, 546.58},两行 y ∈ {216.28, 326.28}
+- 卡高 96px ∈ [92,104] ✔
+- 列间距 16px,行间距 14px ∈ [12,16] ✔
+- 圆角 `20px` ✔ · 描边 `rgb(215, 234, 229)` = #D7EAE5 ✔
+
+### 1440 其它
+
+- 页面底 `html/body/.home-page` 全部 `rgb(251, 252, 248)` = **#FBFCF8** ✔
+- 蟹 bubble 背景 `rgb(18, 60, 70)` = **#123C46**,文字白色,`先问一句,我把路递给你。` ✔
+- 蟹底框 `#FFF6DE` / 边框 `#F0E4C2` / 圆角 28px ✔
+- `scrollWidth 1440 == clientWidth 1440` ✔ 无横向溢出
+
+### 390 卡底边 y / banner 顶边 y
+
+| 卡 | x | y | w | h | background-color |
+|---|---|---|---|---|---|
+| A | 20 | 241.30 | 167 | 128.90 | #E6F4F0 |
+| B | 203 | 241.30 | 167 | 128.90 | #FFF3D2 |
+| C | 20 | 384.20 | 167 | 118.00 | #E5E9FF |
+| D | 203 | 384.20 | 167 | 118.00 | #FFF7DE |
+
+- 移动端仍 **2×2**(两列 x ∈ {20, 203},两行 y ∈ {241.3, 384.2}) ✔
+- 下排卡片底边 y = **502.16**
+- 蟹 banner 顶边 y = **520.16**
+- 间隙 = **18px** ≥ 7px,且 **不重叠**(502.16 < 520.16) ✔
+- `scrollWidth 390 == clientWidth 390 == bodyScrollWidth 390` ✔ 无横向溢出
+ (追加前基线为 **溢出**,见第 5 节)
+
+### 传输字节数
+
+| 项 | 1440 | 390 |
+|---|---|---|
+| 首页文档 transferSize | 3117 | 3117 |
+| 首页总传输字节数 | **26322** | **26322** |
+| 其中 CSS | 4307 | 4307 |
+| 其中图片 (crab webp) | 18898 | 18898 |
+| **其中 JS 字节数** | **0** | **0** |
+
+- JS = 0 ✔ · `', text, re.S)
+ assert len(scripts) == (1 if relative == 'rank/index.html' else 0), relative
+ parsed = Page(text)
+ for ref in parsed.refs:
+ url = urlparse(ref)
+ if url.scheme or not url.path:
+ continue
+ assert url.path.startswith('/astro-preview/'), ref
+ target = dist / url.path.removeprefix('/astro-preview/')
+ if url.path.endswith('/'):
+ target /= 'index.html'
+ assert target.is_file(), ref
+ report['pages'][relative] = {'bytes': len(text.encode()), 'script_count': len(scripts), 'inline_js_bytes': sum(len(s.encode()) for s in scripts), 'forbidden_terms': [], 'repo_cards': parsed.cards}
+ if relative == 'method/index.html':
+ assert len(parsed.cards) == 11
+ for repo, score in [('amber-ollama', '17/23'), ('amber-crof', '16/23')]:
+ card = next(c for c in parsed.cards if c['href'].endswith('/' + repo))
+ assert score in card['text'] and 'W37' in card['text'] and 'W36' not in card['text']
+ if relative == 'en/index.html':
+ assert len(parsed.cards) == 12
+ assert sum('/amber-' in c['href'] for c in parsed.cards) == 11
+ assert 'placeholder' not in text
+ for phrase in ['23 cases / 26 papers', 'Snapshot 2026-W38', 'scored in W37', 'public hash index', 'Three counterintuitive findings']:
+ assert phrase in text, phrase
+ if relative == 'rank/index.html':
+ assert 'Kimi official coding' in text and 'coding coding' not in text
+
+assets = sorted((dist / 'assets').glob('*'))
+assert len(assets) == 6
+for path in assets:
+ data = path.read_bytes()
+ assert data == (legacy / 'assets' / path.name).read_bytes(), path.name
+ assert data == (root / 'public/assets' / path.name).read_bytes(), path.name
+ report['assets'][path.name] = {'bytes': len(data), 'dimensions': struct.unpack('>II', data[16:24]), 'sha256': hashlib.sha256(data).hexdigest()}
+
+ns = {'s': 'http://www.sitemaps.org/schemas/sitemap/0.9', 'x': 'http://www.w3.org/1999/xhtml'}
+sitemap = ET.parse(dist / 'sitemap-0.xml')
+urls = sitemap.findall('s:url', ns)
+locations = [u.findtext('s:loc', namespaces=ns) for u in urls]
+assert len(locations) == 4 and set(locations) == {base, base + 'en/', base + 'rank/', base + 'method/'}
+for url in urls:
+ location = url.findtext('s:loc', namespaces=ns)
+ alternates = {a.attrib['hreflang']: a.attrib['href'] for a in url.findall('x:link', ns)}
+ assert alternates == ({'zh-CN': base, 'en': base + 'en/'} if location in {base, base + 'en/'} else {})
+assert ET.parse(dist / 'sitemap-index.xml').findtext('s:sitemap/s:loc', namespaces=ns) == base + 'sitemap-0.xml'
+assert base + 'sitemap-index.xml' in (dist / 'robots.txt').read_text()
+tracked = subprocess.check_output(['git', 'ls-files'], cwd=root, text=True).splitlines()
+assert not any(Path(p).name.startswith('sitemap') and p.endswith('.xml') for p in tracked)
+config = (root / 'astro.config.mjs').read_text()
+assert "import sitemap from '@astrojs/sitemap'" in config and 'sitemap({' in config
+assert 'sitemap-index.xml' in (root / 'evidence/r2/build.log').read_text()
+report['sitemap'] = {'routes': locations, 'hreflang_count': len(sitemap.findall('.//x:link', ns)), 'generated': True}
+assert not list(dist.rglob('*.js'))
+for path in [*dist.rglob('*.html'), *dist.rglob('*.css')]:
+ assert not re.search(r'@font-face|fonts\.(?:googleapis|gstatic)\.com|\.(?:woff2?|ttf|otf)\b', path.read_text()), path
+package = json.loads((root / 'package.json').read_text())
+assert set(package['dependencies']) == {'astro', '@astrojs/sitemap'}
+lock = json.loads((root / 'package-lock.json').read_text())
+for name in lock['packages']:
+ assert not re.search(r'node_modules/(react(?:-dom)?|vue|svelte|solid-js|@solidjs/start|@sveltejs/kit)(/|$)', name), name
+report['frameworks'] = []
+report['external_js_files'] = []
+report['network_fonts'] = []
+report['dist'] = {str(p.relative_to(dist)): {'bytes': p.stat().st_size, 'sha256': hashlib.sha256(p.read_bytes()).hexdigest()} for p in sorted(dist.rglob('*')) if p.is_file()}
+print(json.dumps(report, indent=2, ensure_ascii=False))
diff --git a/src/components/SiteFooter.astro b/src/components/SiteFooter.astro
new file mode 100644
index 0000000..9aa7cee
--- /dev/null
+++ b/src/components/SiteFooter.astro
@@ -0,0 +1,16 @@
+---
+interface Props {
+ lang?: string;
+}
+
+const { lang = 'zh-CN' } = Astro.props;
+const base = import.meta.env.BASE_URL;
+const route = (path: string) => `${base}${path.replace(/^\/+/, '')}`;
+const isEnglish = lang === 'en';
+---
+
diff --git a/src/components/SiteHeader.astro b/src/components/SiteHeader.astro
new file mode 100644
index 0000000..6024575
--- /dev/null
+++ b/src/components/SiteHeader.astro
@@ -0,0 +1,43 @@
+---
+interface Props {
+ lang?: string;
+ currentPath?: string;
+}
+
+const { lang = 'zh-CN', currentPath = '/' } = Astro.props;
+const base = import.meta.env.BASE_URL;
+const route = (path: string) => `${base}${path.replace(/^\/+/, '')}`;
+const isEnglish = lang === 'en';
+const items = isEnglish
+ ? [
+ ['home', 'Home', '/'],
+ ['matrix', 'Axis matrix', '/rank/'],
+ ['repos', 'Results', '/method/#repos-title'],
+ ['method', 'Method', '/method/#verify-title'],
+ ]
+ : [
+ ['home', '总榜', '/'],
+ ['matrix', '九轴矩阵', '/rank/'],
+ ['repos', '成绩仓', '/method/#repos-title'],
+ ['method', '规范', '/method/#verify-title'],
+ ];
+---
+
+
+ We take real, auditable incidents and freeze them at the moment before the answer was revealed.
+ Models must redo the work with only what was knowable then, against a rubric frozen before any output existed.{' '}
+ The cases are never published. The scores always are.
+
+
+
23 cases / 26 papersprivate library, hash-sealed
+
11 result reposone per vendor × endpoint
+
Updated weeklysame library, same band, public hash index
+
+
+
+
+
The board right now
+
+ Same band (high), same 23 cases, same public hash index. Five rank tiers; ties are labeled as ties.
+ Glossary: case = one task (from a real incident); paper = one sitting; band = reasoning-effort level.
+ These are static chart snapshots: open an image at full size, or follow its source details.
+
+
+
+
+
+
+ Snapshot 2026-W38 · leader swe-2-max @ Devin at 18/23 (scored in W37); five-way tie at 17/23.{' '}
+ Board details →
+ Correction 2026-09-18:
+ the bar now labeled "swe-2-high @ Devin (re-run)" was originally published as swe-2-low —
+ that model does not exist; the server silently routed to swe-2-high.
+
+
+
+
+
+
Same score, different shape
+
+ The nine-axis completion matrix: each cell is a face's pin-level completion.
+ Tied totals hide completely different profiles — the matrix shows what the sum can't.{' '}
+ Rank by work uses eight work types and preserves each record's own week and case count.
+
+
+
+
+
+ Five lanes tied at 17/23, plus doubao 16/23 and gp27b 14/23. Matrix details →
+
+
+
+
+
Why the scores can be trusted
+
+ Every weekly issue runs like an exam: cases sealed in advance, a clean-room sitting,
+ per-paper wire audits, anonymized publication, and a public index anyone can re-check.
+
Each comes with named boundaries and counterexamples in the original writeups.
+
+
+
+
+ "Think longer ≠ score better": most families backfire at top bands; swe-2 is monotone. Effort findings →
+
+
+
+
+
+ Same band, same library: output-token bills span 17× while scores differ by one case. Token findings →
+
+
+
+
+
+ A vendor's high TPS only holds on easy problems; hard ones slow the token stream down.
+
+
+
+
+
Result repos
+
One repo per lane (model × endpoint × band), one matrix per week, wire audits and hash cross-checks included.
+
+ The published glm-5.3-flash 17/23 and qwen3.8-27b 16/23 totals are W37 composites:
+ W36 results of 15/21 and 14/21 plus two new ops cases each. The axis picker retains their W36 records.{' '}
+ Read the method and score-period notes.
+