From 6116dce02fe49ddcfc70b4d12e06ec3f9109e133 Mon Sep 17 00:00:00 2001 From: Vesper Date: Sat, 19 Sep 2026 12:13:20 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20Astro=20rebuild=20=E2=80=94=20four-ques?= =?UTF-8?q?tion=20hero,=20zero-JS=20static=20site?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把 askclaw.dev 从手写 HTML 老站迁到纯 Astro 全静态站(owner 09-18 定案, 09-19 裁 B:全站一起做)。本提交把已有 Astro 项目接到 main 历史上。 - 四路由:/(四卡首屏)、/en/、/method/、/rank/ - @astrojs/sitemap 构建时生成 sitemap(带 hreflang),替换手写版 - 零 JS 默认:内容页 JS 0 字节 - 四卡首屏按 owner 09-19 已终审(good)的 design-05 样张落地 - 六张图表 PNG -> WebP + 缩到 1400px(英文页 2.19MB -> 233KB,降 89%) owner 09-19 裁定:首屏只挂有数据的四句;「降智了吗」「找平替」移出首屏、 进「在补什么」次级区标「数据待发布」——现在要的是可信,不是齐全。 实测(Playwright 真浏览器):首页 41.5KB / JS 0B / 零报错; 四卡 2x2 色值与样张逐一对上;移动端卡片底 502 / 蟹 banner 顶 520(间隙 18px,不重叠)。 Co-Authored-By: Hermes Agent --- .gitattributes | 2 + .gitignore | 5 + WRITER-EVIDENCE.md | 202 + astro.config.mjs | 21 + evidence/HOME-CSS-EVIDENCE.md | 198 + evidence/baseline-sha256.txt | 10 + evidence/build-home.log | 26 + evidence/deploy-home.log | 5 + evidence/final-home-run.log | 56 + evidence/home-1440.png | Bin 0 -> 192124 bytes evidence/home-390.png | Bin 0 -> 124823 bytes evidence/home-browser-report.json | 477 ++ evidence/home-browser-summary.txt | 317 ++ evidence/home-full-1440.png | Bin 0 -> 242649 bytes evidence/home-full-390.png | Bin 0 -> 220462 bytes evidence/home-pending-1440.png | Bin 0 -> 41325 bytes evidence/home-pending-390.png | Bin 0 -> 37963 bytes evidence/r2/browser-summary.txt | 10 + evidence/r2/build-start.txt | 1 + evidence/r2/build.log | 26 + evidence/r2/containment.json | 36 + evidence/r2/deploy-start.txt | 1 + evidence/r2/deploy.log | 21 + evidence/r2/design-detector.json | 1 + evidence/r2/dist-manifest.json | 78 + evidence/r2/final-check-time.txt | 1 + evidence/r2/final-live.log | 8 + evidence/r2/final-local.log | 8 + evidence/r2/green-en.log | 5 + evidence/r2/green-method.log | 5 + evidence/r2/green-rank.log | 5 + evidence/r2/legacy-after.json | 148 + evidence/r2/legacy-before.json | 148 + evidence/r2/legacy-refs-after.txt | 15 + evidence/r2/legacy-refs-before.txt | 15 + evidence/r2/legacy-status-after.txt | 3 + evidence/r2/legacy-status-before.txt | 3 + evidence/r2/live-checks.json | 121 + evidence/r2/live-screens/en-desktop.png | Bin 0 -> 942152 bytes evidence/r2/live-screens/en-mobile.png | Bin 0 -> 542003 bytes evidence/r2/live-screens/home-desktop.png | Bin 0 -> 93768 bytes evidence/r2/live-screens/home-mobile.png | Bin 0 -> 94628 bytes evidence/r2/live-screens/method-desktop.png | Bin 0 -> 263250 bytes evidence/r2/live-screens/method-mobile.png | Bin 0 -> 265840 bytes evidence/r2/live-screens/rank-desktop.png | Bin 0 -> 249622 bytes evidence/r2/live-screens/rank-mobile.png | Bin 0 -> 182360 bytes evidence/r2/pre-final-local.log | 8 + evidence/r2/red-en.log | 5 + evidence/r2/red-method.log | 5 + evidence/r2/red-rank.log | 5 + evidence/r2/remote-after.json | 227 + evidence/r2/remote-before.json | 203 + evidence/r2/remote-main-after.txt | 1 + evidence/r2/remote-main-before.txt | 1 + evidence/r2/static-verification.json | 252 + evidence/route-stats-after.json | 58 + package-lock.json | 4215 +++++++++++++++++ package.json | 18 + public/assets/completion-matrix-7way.en.webp | Bin 0 -> 52790 bytes public/assets/crab-hero.webp | Bin 0 -> 18598 bytes public/assets/effort-curves-20260911.en.webp | Bin 0 -> 46160 bytes .../assets/score-vs-tokens-2026-w37.en.webp | Bin 0 -> 42602 bytes public/assets/top5-2026-w38.en.webp | Bin 0 -> 68752 bytes public/assets/trust-chain.en.webp | Bin 0 -> 45652 bytes .../assets/wallclock-strip-2026-w37.en.webp | Bin 0 -> 39888 bytes public/favicon.svg | 4 + public/robots.txt | 4 + scripts/acceptance.mjs | 298 ++ scripts/live-checks.mjs | 52 + scripts/summarize-acceptance.py | 16 + scripts/tree-manifest.py | 21 + scripts/verify-containment.py | 38 + scripts/verify-dist.py | 114 + src/components/SiteFooter.astro | 16 + src/components/SiteHeader.astro | 43 + src/data/axes.json | 542 +++ src/layouts/BaseLayout.astro | 53 + src/pages/en/index.astro | 197 + src/pages/index.astro | 187 + src/pages/method/index.astro | 79 + src/pages/rank/index.astro | 242 + src/styles/global.css | 1264 +++++ 82 files changed, 10146 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 WRITER-EVIDENCE.md create mode 100644 astro.config.mjs create mode 100644 evidence/HOME-CSS-EVIDENCE.md create mode 100644 evidence/baseline-sha256.txt create mode 100644 evidence/build-home.log create mode 100644 evidence/deploy-home.log create mode 100644 evidence/final-home-run.log create mode 100644 evidence/home-1440.png create mode 100644 evidence/home-390.png create mode 100644 evidence/home-browser-report.json create mode 100644 evidence/home-browser-summary.txt create mode 100644 evidence/home-full-1440.png create mode 100644 evidence/home-full-390.png create mode 100644 evidence/home-pending-1440.png create mode 100644 evidence/home-pending-390.png create mode 100644 evidence/r2/browser-summary.txt create mode 100644 evidence/r2/build-start.txt create mode 100644 evidence/r2/build.log create mode 100644 evidence/r2/containment.json create mode 100644 evidence/r2/deploy-start.txt create mode 100644 evidence/r2/deploy.log create mode 100644 evidence/r2/design-detector.json create mode 100644 evidence/r2/dist-manifest.json create mode 100644 evidence/r2/final-check-time.txt create mode 100644 evidence/r2/final-live.log create mode 100644 evidence/r2/final-local.log create mode 100644 evidence/r2/green-en.log create mode 100644 evidence/r2/green-method.log create mode 100644 evidence/r2/green-rank.log create mode 100644 evidence/r2/legacy-after.json create mode 100644 evidence/r2/legacy-before.json create mode 100644 evidence/r2/legacy-refs-after.txt create mode 100644 evidence/r2/legacy-refs-before.txt create mode 100644 evidence/r2/legacy-status-after.txt create mode 100644 evidence/r2/legacy-status-before.txt create mode 100644 evidence/r2/live-checks.json create mode 100644 evidence/r2/live-screens/en-desktop.png create mode 100644 evidence/r2/live-screens/en-mobile.png create mode 100644 evidence/r2/live-screens/home-desktop.png create mode 100644 evidence/r2/live-screens/home-mobile.png create mode 100644 evidence/r2/live-screens/method-desktop.png create mode 100644 evidence/r2/live-screens/method-mobile.png create mode 100644 evidence/r2/live-screens/rank-desktop.png create mode 100644 evidence/r2/live-screens/rank-mobile.png create mode 100644 evidence/r2/pre-final-local.log create mode 100644 evidence/r2/red-en.log create mode 100644 evidence/r2/red-method.log create mode 100644 evidence/r2/red-rank.log create mode 100644 evidence/r2/remote-after.json create mode 100644 evidence/r2/remote-before.json create mode 100644 evidence/r2/remote-main-after.txt create mode 100644 evidence/r2/remote-main-before.txt create mode 100644 evidence/r2/static-verification.json create mode 100644 evidence/route-stats-after.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/assets/completion-matrix-7way.en.webp create mode 100644 public/assets/crab-hero.webp create mode 100644 public/assets/effort-curves-20260911.en.webp create mode 100644 public/assets/score-vs-tokens-2026-w37.en.webp create mode 100644 public/assets/top5-2026-w38.en.webp create mode 100644 public/assets/trust-chain.en.webp create mode 100644 public/assets/wallclock-strip-2026-w37.en.webp create mode 100644 public/favicon.svg create mode 100644 public/robots.txt create mode 100644 scripts/acceptance.mjs create mode 100644 scripts/live-checks.mjs create mode 100644 scripts/summarize-acceptance.py create mode 100644 scripts/tree-manifest.py create mode 100644 scripts/verify-containment.py create mode 100644 scripts/verify-dist.py create mode 100644 src/components/SiteFooter.astro create mode 100644 src/components/SiteHeader.astro create mode 100644 src/data/axes.json create mode 100644 src/layouts/BaseLayout.astro create mode 100644 src/pages/en/index.astro create mode 100644 src/pages/index.astro create mode 100644 src/pages/method/index.astro create mode 100644 src/pages/rank/index.astro create mode 100644 src/styles/global.css 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'], + ]; +--- + diff --git a/src/data/axes.json b/src/data/axes.json new file mode 100644 index 0000000..d5ef57b --- /dev/null +++ b/src/data/axes.json @@ -0,0 +1,542 @@ +[ + { + "id": "devin", + "name": "swe-2-max", + "vendor": "Devin", + "wk": "W37", + "cases": 23, + "repo": "amber-devin", + "file": "amber-devin/results/2026-W37.md", + "total": 18, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 6, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 1, + "n": 1 + }, + "vision": { + "p": 1, + "n": 1 + } + } + }, + { + "id": "kimi", + "name": "k3", + "vendor": "Kimi 官方 coding 端点", + "wk": "W38", + "cases": 23, + "repo": "amber-kimi", + "file": "amber-kimi/results/2026-W38.md", + "total": 17, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 6, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 0, + "n": 1 + }, + "vision": { + "p": 1, + "n": 1 + } + } + }, + { + "id": "cc", + "name": "deepseek-v4.1-flash", + "vendor": "CommandCode", + "wk": "W37", + "cases": 23, + "repo": "amber-commandcode", + "file": "amber-commandcode/results/2026-W37.md", + "total": 17, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 6, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 1, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + }, + { + "id": "wb", + "name": "hy4-preview-f", + "vendor": "WorkBuddy ACP", + "wk": "W37", + "cases": 23, + "repo": "amber-workbuddy", + "file": "amber-workbuddy/results/2026-W37.md", + "total": 17, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 6, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 1, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + }, + { + "id": "gpt-luna", + "name": "gpt-5.6-luna-900k (max 档)", + "vendor": "OpenAI Codex", + "wk": "W38", + "cases": 23, + "repo": "amber-gpt", + "file": "amber-gpt/results/2026-W38.md", + "total": 16, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 5, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 0, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 1, + "n": 1 + }, + "vision": { + "p": 1, + "n": 1 + } + } + }, + { + "id": "ds", + "name": "deepseek-flash (GA)", + "vendor": "DeepSeek 官方", + "wk": "W37", + "cases": 23, + "repo": "amber-deepseek", + "file": "amber-deepseek/results/2026-W37.md", + "total": 16, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 6, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 0, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + }, + { + "id": "ocgo", + "name": "deepseek-flash", + "vendor": "OpenCode Go", + "wk": "W37", + "cases": 23, + "repo": "amber-opencode", + "file": "amber-opencode/results/2026-W37.md", + "total": 16, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 6, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 0, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + }, + { + "id": "doubao", + "name": "doubao-seed-evolving", + "vendor": "火山方舟 Agent Plan", + "wk": "W38", + "cases": 23, + "repo": "amber-doubao", + "file": "amber-doubao/results/2026-W38.md", + "total": 16, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 6, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 0, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + }, + { + "id": "gpt-sol", + "name": "gpt-5.6-sol-900k (high 档)", + "vendor": "OpenAI Codex", + "wk": "W38", + "cases": 23, + "repo": "amber-gpt", + "file": "amber-gpt/results/2026-W38.md", + "total": 15, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 5, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 0, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 1, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + }, + { + "id": "ollama", + "name": "glm-5.3-flash", + "vendor": "Ollama Cloud", + "wk": "W36", + "cases": 21, + "repo": "amber-ollama", + "file": "amber-ollama/results/2026-W36.md", + "total": 15, + "n": 21, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 4, + "n": 4 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 0, + "n": 1 + }, + "vision": { + "p": 1, + "n": 1 + } + } + }, + { + "id": "gp", + "name": "Qwen3.8-27B", + "vendor": "社区自部署 3×V100", + "wk": "W38", + "cases": 23, + "repo": "amber-goldenpotato", + "file": "amber-goldenpotato/results/2026-W38.md", + "total": 14, + "n": 23, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 5, + "n": 6 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 0, + "n": 3 + }, + "review": { + "p": 0, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 0, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + }, + { + "id": "crof", + "name": "qwen3.8-27b", + "vendor": "CrofAI", + "wk": "W36", + "cases": 21, + "repo": "amber-crof", + "file": "amber-crof/results/2026-W36.md", + "total": 14, + "n": 21, + "axis": { + "build": { + "p": 5, + "n": 6 + }, + "ops": { + "p": 3, + "n": 4 + }, + "text": { + "p": 3, + "n": 3 + }, + "verify": { + "p": 1, + "n": 3 + }, + "review": { + "p": 1, + "n": 2 + }, + "req-drift": { + "p": 1, + "n": 1 + }, + "ui-build": { + "p": 0, + "n": 1 + }, + "vision": { + "p": 0, + "n": 1 + } + } + } +] \ No newline at end of file diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro new file mode 100644 index 0000000..57df4ce --- /dev/null +++ b/src/layouts/BaseLayout.astro @@ -0,0 +1,53 @@ +--- +import '../styles/global.css'; +import SiteHeader from '../components/SiteHeader.astro'; +import SiteFooter from '../components/SiteFooter.astro'; + +interface Props { + title: string; + description: string; + lang?: string; + canonicalPath?: string; + languagePair?: boolean; + pageClass?: string; +} + +const { + title, + description, + lang = 'zh-CN', + canonicalPath = '/', + languagePair = false, + pageClass = '', +} = Astro.props; + +const site = 'https://askclaw.dev'; +const base = import.meta.env.BASE_URL; +const route = (path: string) => `${base}${path.replace(/^\/+/, '')}`; +const canonical = new URL(route(canonicalPath), site).href; +const zhHome = new URL(route('/'), site).href; +const enHome = new URL(route('/en/'), site).href; +const favicon = route('/favicon.svg'); +--- + + + + + + + {title} + + + {languagePair && } + {languagePair && } + {languagePair && } + + + + +
+ +
+ + + diff --git a/src/pages/en/index.astro b/src/pages/en/index.astro new file mode 100644 index 0000000..e62d8eb --- /dev/null +++ b/src/pages/en/index.astro @@ -0,0 +1,197 @@ +--- +import BaseLayout from '../../layouts/BaseLayout.astro'; + +const base = import.meta.env.BASE_URL; +const asset = (file: string) => `${base}assets/${file}`; +// Published repository summaries from the legacy English home, not axes.json: +// the axis picker deliberately retains older W36 21-case records for two lanes. +const repos = [ + ['amber', 'spec', 'Method spec + public hash index + cross-repo weekly board'], + ['amber-devin', '18/23', 'swe-2-max @ Devin — current leader'], + ['amber-kimi', '17/23', 'k3 @ Kimi official coding endpoint + the K2.8 duel'], + ['amber-ollama', '17/23', 'glm-5.3-flash / d41f @ Ollama Cloud'], + ['amber-commandcode', '17/23', 'd41f @ CommandCode — five-band ladder'], + ['amber-workbuddy', '17/23', 'hy4-preview-f @ WorkBuddy ACP'], + ['amber-gpt', '16/23', 'gpt-6-astra / gpt-5.6 family @ OpenAI Codex'], + ['amber-crof', '16/23', 'qwen3.8-27b @ CrofAI — the $1.15 value king'], + ['amber-deepseek', '16/23', 'deepseek-flash @ DeepSeek official'], + ['amber-opencode', '16/23', 'deepseek-flash @ OpenCode Go'], + ['amber-doubao', '16/23', 'doubao-seed-evolving @ Volcengine Ark Agent Plan'], + ['amber-goldenpotato', '14/23', 'Qwen3.8-27B @ community self-hosted (3× V100)'], +]; +--- + +
+
+

AMBER — real history,
sealed in amber, replayed

+

+ 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. +

+
+ + AMBER board: five rank tiers (2026-W38) + +
+ 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. +

+
+ + Nine-axis completion matrix + +
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. +

+
+ + How a result is produced + +
+
+ +
+

Three counterintuitive findings

+

Each comes with named boundaries and counterexamples in the original writeups.

+
+ + Effort curves + +
"Think longer ≠ score better": most families backfire at top bands; swe-2 is monotone. Effort findings →
+
+
+ + Score vs thinking budget + +
Same band, same library: output-token bills span 17× while scores differ by one case. Token findings →
+
+
+ + Per-case wall clock + +
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. +

+
+ {repos.map(([repo, score, description]) => ( + + {repo} + {score} + {description} + + ))} +
+
+ +
+

The rules

+
+
Private side, never public: the case library, oracles, transcripts, internal case IDs and variant names.
+
Public side, always checkable: scores, aggregates, verdicts, the hash index — anyone can verify the library didn't change and the scores add up.
+
Historical outcomes are evidence, not the only correct answer; runtime sealing ≠ clean training data. Both warnings are printed on every issue.
+
+ +
+
+
+ + diff --git a/src/pages/index.astro b/src/pages/index.astro new file mode 100644 index 0000000..b64bc9e --- /dev/null +++ b/src/pages/index.astro @@ -0,0 +1,187 @@ +--- +import BaseLayout from '../layouts/BaseLayout.astro'; + +const base = import.meta.env.BASE_URL; +const route = (path: string) => `${base}${path.replace(/^\/+/, '')}`; +const crabAsset = `${base}assets/crab-hero.webp`; + +const questions = [ + { + code: 'A', + tone: 'teal', + question: '同一个模型,官方端点和第三方有差吗?', + preview: '同模型,分 lane 对照。', + cue: '看 lane', + href: route('/method/#repos-title'), + ariaLabel: '同一个模型,官方端点和第三方有差吗?同模型,分 lane 对照。查看成绩仓。', + }, + { + code: 'B', + tone: 'amber', + question: '新出的模型能不能打?', + preview: '同一套 23 案,进榜即见。', + cue: '看 W38', + href: route('/#leaderboard'), + ariaLabel: '新出的模型能不能打?同一套 23 案,进榜即见。查看 2026-W38 总榜。', + }, + { + code: 'C', + tone: 'cobalt', + question: '我干这个活该用谁?', + preview: '按活挑轴,不看总分。', + cue: '按轴排', + href: route('/rank/'), + ariaLabel: '我干这个活该用谁?按活挑轴,不看总分。按工作类型查看九轴排行。', + }, + { + code: 'D', + tone: 'gold', + question: '这榜自己可信吗?', + preview: '封存、净室、hash 可查。', + cue: '看规范', + href: route('/method/#verify-title'), + ariaLabel: '这榜自己可信吗?封存、净室、hash 可查。查看规范和证据链。', + }, +] as const; + +const tiedLanes = [ + ['glm-5.3-flash @ Ollama Cloud', 'teal'], + ['deepseek-v4.1-flash @ CommandCode', 'cobalt'], + ['deepseek-v4.1-flash @ Ollama Cloud', 'sky'], + ['k3 @ Kimi 官方 coding', 'coral'], + ['hy4-preview-f @ WorkBuddy', 'mint'], +] as const; +--- + +
+
+
+
+

AMBER / PUBLIC BENCHMARK

+ +

你想先问哪一句?

+ +
+ + +
+ +
+
+
+

当前总榜

+

真实公开成绩 · 2026-W38

+
+ 23 案 · 11 个成绩仓 +
+ +
+
+
#1 · 当前榜首
+
+
+

swe-2-max @ Devin

+

考于 W37 · W38 未重考

+
+ 18/23 +
+

榜首成绩 · 23 案题库

+
+ + 通过案数 / 题库总案数 +
+
+ +
+

#2 · 五席并列 · 均为 17/23

+
    + {tiedLanes.map(([name, tone]) => ( +
  1. + + {name} + 17/23 +
  2. + ))} +
+
+
+ +
+ 同分 ≠ 同款 + 榜单先给结果,详情页保留证据 +
+
+ +
+
+

在补什么

+

先补齐证据,再回到首屏。

+
+
+
+ +
+

AI 模型降智了吗?

+

跨家复测还未齐,暂不声称能力回退。

+
+ 数据待发布 +
+
+ +
+

在我关注的方面,有更好的平替吗?

+

便宜候选需要成体系的价格 / 成本源。

+
+ 价格待发布 +
+
+

次级区只记缺口,不替数据提前下结论。

+
+
+
+
diff --git a/src/pages/method/index.astro b/src/pages/method/index.astro new file mode 100644 index 0000000..0780a0b --- /dev/null +++ b/src/pages/method/index.astro @@ -0,0 +1,79 @@ +--- +import BaseLayout from '../../layouts/BaseLayout.astro'; + +const resultRepos = [ + ['amber-devin', '18/23', 'swe-2-max @ Devin', 'W37'], + ['amber-kimi', '17/23', 'k3 @ Kimi official coding', 'W38'], + ['amber-ollama', '17/23', 'glm-5.3-flash / d41f @ Ollama Cloud', 'W37'], + ['amber-commandcode', '17/23', 'd41f @ CommandCode', 'W37'], + ['amber-workbuddy', '17/23', 'hy4-preview-f @ WorkBuddy ACP', 'W37'], + ['amber-gpt', '16/23', 'gpt-6-astra / gpt-5.6 family @ OpenAI Codex', 'W38'], + ['amber-crof', '16/23', 'qwen3.8-27b @ CrofAI', 'W37'], + ['amber-deepseek', '16/23', 'deepseek-flash @ DeepSeek official', 'W37'], + ['amber-opencode', '16/23', 'deepseek-flash @ OpenCode Go', 'W37'], + ['amber-doubao', '16/23', 'doubao-seed-evolving @ Volcengine Ark Agent Plan', 'W38'], + ['amber-goldenpotato', '14/23', 'Qwen3.8-27B @ community self-hosted', 'W38'], +]; +--- + +
+
+

AMBER 方法

+

+ 琥珀评测把真实、可审计的历史事件封存到答案揭晓前,让模型只用当时可得的信息重做一次。 + 评分规则先冻结,题库不公开,分数和校验材料公开。 +

+
+
23 / 26案 / 卷,私有题库
+
11公开成绩仓
+
W38保留的最新快照
+
+
+ +
+

方法原则

+

公开材料可以复核成绩,但不会泄露私有题库。

+
+
私有内容:题库、oracle、transcript、内部案号和变体名不公开。
+
公开内容:成绩、汇总、裁决和哈希索引,任何人都可以重新核对。
+
历史结果是证据,不是唯一正解;运行时封存也不等于训练数据纯净。
+
+
+ +
+

11 个成绩仓

+

每个仓对应一条模型结果记录;名称、分数、期号和链接沿用公开材料。

+

+ Ollama 的 glm-5.3-flash 与 CrofAI 的 qwen3.8-27b 使用 W37 补考合成成绩: + W36 的 15/21、14/21 各加两案,成为 17/23、16/23;d41f 的 17/23 为 W37 全库首考。 + 按轴榜保留这两条 W36 的 21 案记录,不是这份合成总分。 + 原始说明:Ollama W37 ·{' '} + CrofAI W37。 +

+
+ {resultRepos.map(([repo, score, model, week]) => ( + + {score} + {repo} + {model} + {week} · 23 cases + + ))} +
+
+ +
+

公开校验入口

+

这些链接是方法和公开记录的原始入口。

+ +
+
+
diff --git a/src/pages/rank/index.astro b/src/pages/rank/index.astro new file mode 100644 index 0000000..7931902 --- /dev/null +++ b/src/pages/rank/index.astro @@ -0,0 +1,242 @@ +--- +import BaseLayout from '../../layouts/BaseLayout.astro'; +import rawLanes from '../../data/axes.json'; + +const faces = [ + ['build', '施工'], + ['ops', '运维'], + ['text', '文本'], + ['verify', '核验'], + ['review', '审查'], + ['req-drift', '需求漂移'], + ['ui-build', 'UI 搭建'], + ['vision', '视觉审图'], +] as const; + +// Keep the canonical records byte-for-byte. Only this lane's public vendor +// label is mapped; never substring-replace ordinary domain terminology. +const lanes = rawLanes.map((lane) => ({ + ...lane, + vendor: lane.id === 'kimi' ? 'Kimi official coding' : lane.vendor, +})); + +const stats = faces.map(([id, label]) => { + const available = lanes.filter((lane) => lane.axis[id].n > 0); + const full = available.filter((lane) => lane.axis[id].p === lane.axis[id].n); + return { id, label, full: full.length, available: available.length }; +}); +--- + +
+

按轴挑模型 — 别只看总分

+

+ 选择你要做的工作类型,下表先比较所选类型里的最低通过数,再比较合计。 + 这让 12 条公开车道的差异更容易核对。 +

+ +
+

选择工作类型

+

每个 chip 显示该类型里满分车道的数量。默认不选任何类型。

+
+
+ {stats.map(({ id, label, full, available }) => ( + + ))} +
+
+
+ + + + + +
+ +
+
还没有选择。先选一种工作类型。
+
+
+ +
+

短板排序

+

规则:先比最低通过数,再比所选类型的通过总数;并列会保留。

+
+ + + + + + +
AMBER work-type ranking
选择一种工作类型后显示车道。
+
+ +

数据来自公开成绩仓。期号和案数随原始记录保留;方法与公开哈希索引见 方法

+
+
+
+ + diff --git a/src/styles/global.css b/src/styles/global.css new file mode 100644 index 0000000..6d916d6 --- /dev/null +++ b/src/styles/global.css @@ -0,0 +1,1264 @@ +:root { + --ink: #17242b; + --sub: #5a6b73; + --teal: #00a5b5; + --teal-dark: #0b7c88; + --bg: #fafdfe; + --card: #fff; + --line: #e3ecef; + --warning-bg: #fffbe9; + --warning-line: #f0e3b0; +} + +* { + box-sizing: border-box; +} + +html { + background: var(--bg); +} + +body { + margin: 0; + color: var(--ink); + background: var(--bg); + font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + line-height: 1.7; +} + +a { + color: var(--teal-dark); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +:focus-visible { + outline: 3px solid #f4b942; + outline-offset: 3px; +} + +.wrap { + width: min(980px, calc(100% - 40px)); + margin: 0 auto; +} + +.site-header { + border-bottom: 1px solid var(--line); + padding: 18px 0; +} + +.site-header .wrap, +.site-footer .wrap, +.header-nav, +.header-links { + display: flex; + align-items: center; +} + +.site-header .wrap, +.site-footer .wrap { + justify-content: space-between; + gap: 20px; +} + +.logo { + color: var(--ink); + font-size: 20px; + font-weight: 800; + letter-spacing: -0.02em; +} + +.logo span { + color: var(--teal); +} + +.header-nav, +.header-links { + flex-wrap: wrap; + gap: 16px; +} + +.header-nav a, +.header-links a { + color: var(--sub); + font-size: 14px; +} + +main { + min-height: 60vh; +} + +.hero { + padding: 64px 0 38px; +} + +.hero h1, +h1 { + margin: 0; + font-size: clamp(2rem, 5vw, 2.6rem); + line-height: 1.25; + letter-spacing: -0.025em; +} + +.hero h1 em, +h1 em { + color: var(--teal); + font-style: normal; +} + +.hero p, +.lead { + max-width: 760px; + margin: 16px 0 0; + color: var(--sub); + font-size: 1.08rem; +} + +.hero-actions, +.badges, +.stat-grid, +.repo-grid, +.rule-list { + display: grid; + gap: 14px; +} + +.hero-actions { + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + max-width: 620px; + margin-top: 28px; +} + +.action-card, +.badge, +.stat-card, +.repo-card, +.panel, +.rule, +.notice { + border: 1px solid var(--line); + border-radius: 10px; + background: var(--card); +} + +.action-card, +.badge, +.stat-card, +.repo-card, +.panel { + padding: 16px 18px; +} + +.action-card { + display: block; + color: var(--ink); +} + +.action-card:hover { + border-color: var(--teal); + text-decoration: none; +} + +.action-card strong, +.repo-card strong { + color: var(--teal-dark); +} + +.action-card small, +.badge small, +.repo-card small, +.muted, +.hint, +.note { + color: var(--sub); +} + +.action-card small, +.badge small, +.repo-card small { + display: block; + font-size: 0.84rem; +} + +.section { + padding: 34px 0; +} + +.section h2 { + margin: 0 0 6px; + font-size: 1.5rem; +} + +.hint, +.note { + margin: 0 0 18px; + font-size: 0.92rem; +} + +.badges, +.stat-grid { + grid-template-columns: repeat(auto-fit, minmax(175px, 1fr)); + margin-top: 26px; +} + +.badge strong, +.stat-card strong { + display: block; + color: var(--teal-dark); + font-size: 1.35rem; +} + +.badge span, +.stat-card span { + display: block; + color: var(--sub); + font-size: 0.82rem; +} + +.repo-grid { + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); +} + +.repo-card { + display: block; + color: var(--ink); +} + +.repo-card:hover { + border-color: var(--teal); + text-decoration: none; +} + +.repo-card .score { + float: right; + color: var(--ink); + font-weight: 700; +} + +.rule-list { + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); +} + +.rule { + border-left: 3px solid var(--teal); + padding: 10px 14px; + color: var(--sub); +} + +.notice { + border-left: 3px solid var(--teal); + padding: 12px 16px; + color: var(--sub); +} + +.site-footer { + margin-top: 40px; + border-top: 1px solid var(--line); + padding: 26px 0 40px; + color: var(--sub); + font-size: 0.85rem; +} + +.site-footer .wrap { + align-items: flex-start; +} + +.site-footer p { + margin: 0; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.skip-link { + position: absolute; + left: -9999px; + top: 8px; + z-index: 2; + padding: 8px 12px; + color: #fff; + background: var(--ink); +} + +.skip-link:focus { + left: 8px; +} + +/* Rank picker */ +.rank-page h1 { + margin-top: 40px; +} + +.picker { + padding: 18px 20px; +} + +.chips, +.preset-list { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.chip, +.preset { + border: 1px solid var(--line); + border-radius: 999px; + background: #fff; + color: var(--ink); + cursor: pointer; + font: inherit; +} + +.chip { + padding: 7px 14px; + font-size: 0.88rem; +} + +.chip:hover, +.preset:hover, +.chip[aria-pressed="true"] { + border-color: var(--teal); +} + +.chip[aria-pressed="true"] { + color: #fff; + background: var(--teal); + font-weight: 700; +} + +.chip .count { + margin-left: 5px; + font-size: 0.76rem; + opacity: 0.78; +} + +.picker-bar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + flex-wrap: wrap; + margin-top: 16px; + padding-top: 14px; + border-top: 1px dashed var(--line); +} + +.preset { + padding: 5px 11px; + color: var(--teal-dark); + border-color: var(--teal); + font-size: 0.82rem; +} + +.clear-button { + border: 0; + padding: 5px; + color: var(--sub); + background: transparent; + cursor: pointer; + font: inherit; + font-size: 0.82rem; +} + +.verdict { + min-height: 2.6em; + margin-top: 16px; + border-left: 3px solid var(--teal); + padding: 10px 14px; + color: var(--sub); +} + +.verdict strong { + color: var(--ink); +} + +.board-wrap { + overflow-x: auto; + border: 1px solid var(--line); + border-radius: 10px; + background: #fff; +} + +table.board { + width: 100%; + border-collapse: collapse; + font-size: 0.88rem; +} + +table.board th, +table.board td { + padding: 9px 10px; + border-bottom: 1px solid var(--line); + text-align: left; + white-space: nowrap; +} + +table.board th { + color: var(--sub); + background: #f6fafb; + font-size: 0.8rem; + font-weight: 700; +} + +table.board th.num, +table.board td.num { + text-align: right; +} + +table.board tbody tr:hover { + background: #f7fcfd; +} + +.lane { + font-weight: 700; +} + +.lane small { + display: block; + color: var(--sub); + font-size: 0.76rem; + font-weight: 400; +} + +.cell, +.total, +.rank-number { + font-variant-numeric: tabular-nums; +} + +.cell.pass { + color: var(--teal-dark); + font-weight: 700; +} + +.cell.fail, +.min.bad { + color: #c0392b; +} + +.min.good { + color: var(--teal-dark); +} + +.saturation { + margin-top: 14px; + border: 1px solid var(--warning-line); + border-radius: 8px; + padding: 10px 14px; + color: #7a6a2f; + background: var(--warning-bg); + font-size: 0.88rem; +} + +[hidden] { + display: none !important; +} + +@media (max-width: 720px) { + .wrap { + width: min(100% - 28px, 980px); + } + + .site-header .wrap, + .site-footer .wrap { + align-items: flex-start; + flex-direction: column; + } + + .hero { + padding-top: 42px; + } +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + } +} + +/* ------------------------------------------------------------------ + AskClaw home visual batch (appended block, additive only). + Color values and geometry are read from the design sources: + ~/2609/askclaw-design-05/mockups/01-hero-questions-4-desktop.svg + ~/2609/askclaw-design-05/mockups/02-hero-questions-4-mobile.svg + ~/2609/askclaw-design-05/mockups/03-pending-section.svg + Page ground #FBFCF8 · card edges #D7EAE5 · card radius 20px + A #E6F4F0 B #FFF3D2 C #E5E9FF D #FFF7DE · crab bubble #123C46 + ------------------------------------------------------------------ */ + +.home-document { + background-color: #FBFCF8; +} + +html:has(> body.home-document) { + background-color: #FBFCF8; +} + +.home-document .site-header { + border-bottom-color: #DCEBE6; +} + +.home-document .site-footer { + border-top-color: #DCEBE6; +} + +.home-document .site-header .logo { + font-family: "Noto Serif CJK SC", "Noto Serif SC", Georgia, "Songti SC", serif; + color: #123C46; +} + +.home-document .header-nav a { + color: #6C8B91; + font-weight: 500; +} + +.home-document .header-nav a[aria-current="page"] { + color: #149C9B; + font-weight: 600; +} + +.home-document .language-toggle { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 5px 14px; + border: 1px solid #DCEBE6; + border-radius: 16px; + background: #FFFFFF; + color: #6C8B91; + font-size: 13px; + font-weight: 500; +} + +.home-document .language-toggle .language-current { + color: #149C9B; + font-weight: 700; +} + +.home-page { + background-color: #FBFCF8; + color: #123C46; +} + +.home-wrap { + width: min(1160px, calc(100% - 40px)); +} + +/* --- hero ---------------------------------------------------------- */ + +.question-hero { + display: grid; + gap: 18px; + padding: 30px 0 6px; +} + +.question-panel { + min-width: 0; +} + +.eyebrow { + margin: 0; + color: #149C9B; + font-size: 11px; + font-weight: 800; + letter-spacing: 1.7px; + line-height: 1.2; + text-transform: uppercase; +} + +.eyebrow-rule { + width: 204px; + max-width: 62%; + height: 4px; + margin: 9px 0 0; + border: 0; + border-radius: 2px; + background: #F7B83E; +} + +.question-hero h1 { + margin: 18px 0 0; + color: #123C46; + font-size: clamp(1.6rem, 3vw, 2.15rem); + font-weight: 800; + line-height: 1.25; + letter-spacing: -0.01em; +} + +.question-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px 16px; + margin-top: 22px; +} + +.question-entry { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + grid-template-areas: + "meta meta" + "question question" + "preview cue"; + align-items: end; + column-gap: 10px; + row-gap: 6px; + box-sizing: border-box; + min-height: 96px; + padding: 14px 16px 12px; + border: 1px solid #D7EAE5; + border-radius: 20px; + color: #123C46; + text-decoration: none; +} + +.question-entry:hover { + text-decoration: none; + box-shadow: 0 10px 22px rgba(23, 75, 84, 0.1); +} + +.question-entry-teal { + background: #E6F4F0; +} + +.question-entry-amber { + background: #FFF3D2; +} + +.question-entry-cobalt { + background: #E5E9FF; +} + +.question-entry-gold { + background: #FFF7DE; +} + +.question-entry-teal .question-meta, +.question-entry-teal .edge-cue { + color: #149C9B; +} + +.question-entry-amber .question-meta, +.question-entry-amber .edge-cue { + color: #F7B83E; +} + +.question-entry-cobalt .question-meta, +.question-entry-cobalt .edge-cue { + color: #6C73D9; +} + +.question-entry-gold .question-meta, +.question-entry-gold .edge-cue { + color: #D79D2C; +} + +.question-entry-teal .question-dot { + background: #149C9B; +} + +.question-entry-amber .question-dot { + background: #F7B83E; +} + +.question-entry-cobalt .question-dot { + background: #6C73D9; +} + +.question-entry-gold .question-dot { + background: #D79D2C; +} + +.question-meta { + grid-area: meta; + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 10px; + font-weight: 800; + letter-spacing: 1.4px; + line-height: 1.2; +} + +.question-dot { + flex: none; + width: 9px; + height: 9px; + border-radius: 50%; + background: #149C9B; +} + +.question-copy { + display: contents; +} + +.question { + grid-area: question; + display: block; + color: #123C46; + font-size: 14px; + font-weight: 800; + line-height: 1.3; +} + +.preview { + grid-area: preview; + display: block; + color: #6C8B91; + font-size: 10.5px; + font-weight: 500; + line-height: 1.35; + min-width: 0; + overflow-wrap: anywhere; +} + +.edge-cue { + grid-area: cue; + display: inline-flex; + align-items: center; + gap: 5px; + font-size: 12px; + font-weight: 700; + line-height: 1.35; + white-space: nowrap; +} + +.cue-mark { + font-size: 11px; + line-height: 1; +} + +.crab-guide { + display: flex; + flex-direction: column; + gap: 12px; + min-width: 0; +} + +.crab-frame { + overflow: hidden; + border: 1px solid #F0E4C2; + border-radius: 28px; + background: #FFF6DE; +} + +.crab-frame img { + display: block; + width: 100%; + height: auto; +} + +.crab-bubble { + position: relative; + margin: 0; + padding: 11px 20px; + border-radius: 22px; + background: #123C46; + color: #FFFFFF; + font-size: 13px; + font-weight: 700; + line-height: 1.4; + text-align: center; + box-shadow: 0 5px 12px rgba(23, 75, 84, 0.16); +} + +.crab-bubble::before { + content: ""; + position: absolute; + top: -9px; + left: 50%; + margin-left: -9px; + border-right: 9px solid transparent; + border-bottom: 9px solid #123C46; + border-left: 9px solid transparent; +} + +.fact-rail { + display: flex; + align-items: center; + gap: 9px; + min-height: 48px; + padding: 8px 16px; + border: 1px solid #DCEBE6; + border-radius: 24px; + background: #FFFFFF; + color: #123C46; + font-size: 13px; + font-weight: 700; + line-height: 1.4; +} + +.fact-dot { + flex: none; + width: 10px; + height: 10px; + border-radius: 50%; + background: #F7B83E; +} + +/* --- leaderboard --------------------------------------------------- */ + +.leaderboard { + margin-top: 44px; + padding: 24px 26px 0; + border: 1px solid #DCEBE6; + border-radius: 30px; + background: #FFFFFF; + box-shadow: 0 12px 32px rgba(23, 75, 84, 0.1); +} + +.leaderboard-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + flex-wrap: wrap; + padding-bottom: 18px; +} + +.leaderboard-header h2 { + margin: 0; + color: #123C46; + font-family: "Noto Serif CJK SC", "Noto Serif SC", Georgia, "Songti SC", serif; + font-size: 1.5rem; + font-weight: 800; + line-height: 1.25; +} + +.leaderboard-header p { + margin: 4px 0 0; + color: #6C8B91; + font-size: 12px; + font-weight: 600; +} + +.leaderboard-badge { + display: inline-flex; + align-items: center; + padding: 7px 15px; + border-radius: 999px; + background: #E6F4F0; + color: #149C9B; + font-size: 11px; + font-weight: 700; + line-height: 1.3; + white-space: nowrap; +} + +.leaderboard-body { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 18px; +} + +.leaderboard-footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 14px; + flex-wrap: wrap; + margin-top: 20px; + padding: 16px 0 20px; + border-top: 1px solid #DCEBE6; + font-size: 12px; +} + +.leaderboard-footer strong { + color: #335F67; + font-weight: 700; +} + +.leaderboard-footer span { + color: #6C8B91; + font-weight: 500; +} + +.champion-card { + display: flex; + flex-direction: column; + gap: 10px; + min-width: 0; + padding: 22px 24px; + border-radius: 24px; + background: #FFF3D2; +} + +.rank-label { + display: flex; + align-items: center; + gap: 10px; + color: #335F67; + font-size: 11px; + font-weight: 800; + letter-spacing: 0.6px; + line-height: 1.3; +} + +.rank-dot { + flex: none; + width: 14px; + height: 14px; + border-radius: 50%; + background: #F7B83E; +} + +.champion-main { + display: flex; + align-items: flex-end; + justify-content: space-between; + gap: 14px; + flex-wrap: wrap; + min-width: 0; +} + +.champion-main h3 { + margin: 0; + color: #123C46; + font-family: "Noto Serif CJK SC", "Noto Serif SC", Georgia, "Songti SC", serif; + font-size: 1.3rem; + font-weight: 800; + line-height: 1.3; + overflow-wrap: anywhere; +} + +.champion-main p { + margin: 6px 0 0; + color: #6C8B91; + font-size: 12px; + font-weight: 600; + line-height: 1.4; +} + +.champion-score { + color: #123C46; + font-size: clamp(1.7rem, 3.4vw, 2.6rem); + font-weight: 800; + font-variant-numeric: tabular-nums; + line-height: 1; +} + +.champion-detail { + margin: 0; + color: #6C8B91; + font-size: 11px; + font-weight: 600; + line-height: 1.4; +} + +.progress-block { + display: flex; + flex-direction: column; + gap: 8px; + min-width: 0; + color: #6C8B91; + font-size: 11px; + font-weight: 500; + line-height: 1.4; +} + +.progress-track { + display: block; + overflow: hidden; + height: 10px; + border-radius: 5px; + background: #FCE6A9; +} + +.progress-track span { + display: block; + height: 100%; + border-radius: 5px; + background: #F7B83E; +} + +.tied-card { + min-width: 0; + padding: 22px 24px; + border: 1px solid #DCEBE6; + border-radius: 24px; + background: #FBFEFC; +} + +.tied-card h3 { + margin: 0 0 6px; + color: #149C9B; + font-size: 15px; + font-weight: 800; + line-height: 1.35; +} + +.tied-list { + margin: 0; + padding: 0; + list-style: none; +} + +.tied-list li { + display: flex; + align-items: center; + gap: 14px; + padding: 12px 0; + border-bottom: 1px solid #EEF5F2; +} + +.tied-list li:last-child { + border-bottom: 0; +} + +.lane-marker { + flex: none; + width: 10px; + height: 10px; + border-radius: 50%; + background: #149C9B; +} + +.lane-marker-teal { + background: #149C9B; +} + +.lane-marker-cobalt { + background: #6C73D9; +} + +.lane-marker-sky { + background: #78A9C8; +} + +.lane-marker-coral { + background: #EF7569; +} + +.lane-marker-mint { + background: #9DCFC1; +} + +.lane-name { + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + color: #335F67; + font-size: 11px; + font-weight: 600; + text-overflow: ellipsis; + white-space: nowrap; +} + +.tied-list strong { + flex: none; + color: #123C46; + font-size: 11px; + font-weight: 800; + font-variant-numeric: tabular-nums; +} + +/* --- pending section ----------------------------------------------- */ + +.pending-section { + margin: 44px 0 0; + padding: 0 0 40px; +} + +.pending-header h2 { + margin: 0; + color: #123C46; + font-family: "Noto Serif CJK SC", "Noto Serif SC", Georgia, "Songti SC", serif; + font-size: 1.6rem; + font-weight: 800; + line-height: 1.25; +} + +.pending-header p { + margin: 8px 0 0; + color: #6C8B91; + font-size: 13px; + font-weight: 500; + line-height: 1.5; +} + +.pending-list { + margin-top: 20px; + border-top: 1px solid #DCEBE6; +} + +.pending-row { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto; + align-items: center; + gap: 16px; + padding: 20px 0; + border-bottom: 1px solid #DCEBE6; +} + +.pending-letter { + display: inline-flex; + align-items: center; + justify-content: center; + flex: none; + width: 30px; + height: 30px; + border: 1px solid #F7B83E; + border-radius: 50%; + background: #FFF3D2; + color: #F7B83E; + font-size: 12px; + font-weight: 800; + line-height: 1; +} + +.pending-row h3 { + margin: 0; + color: #123C46; + font-size: 21px; + font-weight: 800; + line-height: 1.3; +} + +.pending-row p { + margin: 4px 0 0; + color: #6C8B91; + font-size: 12px; + font-weight: 500; + line-height: 1.5; +} + +.pending-status { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 8px 18px; + border: 1px solid #EEDCA9; + border-radius: 999px; + background: #FFF3D2; + color: #335F67; + font-size: 12px; + font-weight: 700; + line-height: 1.2; + white-space: nowrap; +} + +.pending-row-e .pending-letter { + border-color: #F7B83E; + background: #FFF3D2; + color: #F7B83E; +} + +.pending-row-e .pending-status { + border-color: #EEDCA9; + background: #FFF3D2; + color: #335F67; +} + +.pending-row-f .pending-letter { + border-color: #6C73D9; + background: #E5E9FF; + color: #6C73D9; +} + +.pending-row-f .pending-status { + border-color: #CDD4F5; + background: #E5E9FF; + color: #335F67; +} + +.pending-note { + margin: 18px 0 0; + color: #6C8B91; + font-size: 12px; + font-weight: 600; + line-height: 1.5; +} + +/* --- home breakpoints ---------------------------------------------- */ + +@media (min-width: 1024px) { + .question-hero { + grid-template-columns: minmax(0, 1fr) minmax(280px, 0.42fr); + align-items: start; + gap: 28px; + padding-top: 36px; + } + + .question { + font-size: 15px; + } + + .preview { + font-size: 12px; + } + + .leaderboard-body { + grid-template-columns: minmax(0, 0.5fr) minmax(0, 1fr); + } +} + +@media (min-width: 1280px) { + .question { + font-size: 17px; + } +} + +@media (max-width: 720px) { + .leaderboard { + margin-top: 36px; + border-radius: 24px; + padding: 20px 18px 0; + } + + .question-entry { + padding: 12px 14px 12px; + } + + .crab-frame { + border-radius: 24px; + } +} + +@media (max-width: 640px) { + .pending-row { + grid-template-columns: auto minmax(0, 1fr); + row-gap: 10px; + } + + .pending-status { + grid-column: 2; + justify-self: start; + } + + .pending-row h3 { + font-size: 18px; + } +} + +@media (max-width: 480px) { + .question-hero { + padding-top: 22px; + } + + .question-grid { + margin-top: 18px; + } + + .question-entry { + min-height: 118px; + } + + .champion-score { + font-size: 1.7rem; + } +}