diff --git a/site/public/fonts/bricolage-grotesque-latin.woff2 b/site/public/fonts/bricolage-grotesque-latin.woff2 new file mode 100644 index 000000000..82152a408 Binary files /dev/null and b/site/public/fonts/bricolage-grotesque-latin.woff2 differ diff --git a/site/public/robots.txt b/site/public/robots.txt index 2ea7a6ce4..942651758 100644 --- a/site/public/robots.txt +++ b/site/public/robots.txt @@ -65,10 +65,12 @@ Disallow: / User-agent: Meta-ExternalAgent Disallow: / -# Undeclared bulk crawlers +# ByteDance crawler — allowed: it powers Doubao search (a major CN AI search surface) +# and does not separate retrieval from training, so blocking it drops us from CN AI search. User-agent: Bytespider -Disallow: / +Allow: / +# Undeclared bulk crawlers User-agent: PetalBot Disallow: / diff --git a/site/public/sitemap.xml b/site/public/sitemap.xml index e04926153..f7696005d 100644 --- a/site/public/sitemap.xml +++ b/site/public/sitemap.xml @@ -1,9 +1,22 @@ - + https://pawwork.ai/ - 2026-06-05 + + + + 2026-06-06 weekly 1.0 + + https://pawwork.ai/zh-CN/ + + + + 2026-06-06 + weekly + 0.9 + diff --git a/site/src/components/Home.astro b/site/src/components/Home.astro new file mode 100644 index 000000000..68a07d474 --- /dev/null +++ b/site/src/components/Home.astro @@ -0,0 +1,243 @@ +--- +// Homepage body, shared by both language pages. `lang` selects the dictionary; +// the page renders fully server-side in that language. The language toggle is a +// plain link to the other locale's URL (no client-side innerHTML swap), so each +// page is independently crawlable. Theme toggle and the R2 download-link swap +// stay client-side. +import { I18N, type Lang } from "../i18n"; +import { DOWNLOAD, DOWNLOAD_MANIFEST_URL, REPO_URL, RELEASES_URL } from "../config"; + +interface Props { + lang: Lang; +} + +const { lang } = Astro.props; +const t = I18N[lang]; +const otherHref = lang === "cn" ? "/" : "/zh-CN/"; +const README_URL = lang === "cn" ? `${REPO_URL}/blob/dev/README_CN.md` : `${REPO_URL}#readme`; +const LICENSE_URL = `${REPO_URL}/blob/dev/LICENSE`; +--- + + + + + + + + + + + +
+
+ PawWork + +
+ + {/* HERO */} +
+
+ +

+

+
+
+ + + +
+ +

+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
invoices.xlsx
+
+
+ +
+
+ + {/* DEFINITION STRIP — answer-first, crawlable */} +
+ + +
+ + {/* WHAT IT SHIPS — bento of product artifacts */} +
+
+

+ +
+
+
+ +
+
+
+
Acme Co.
Mar 3
$1,240.00
+
Globex
Mar 5
$880.50
+
Initech
Mar 9
$2,310.00
+
+
+
+
+
+ +
+
+ DOC Word + XLS Excel + PPT PowerPoint +
+ +
+
+
+ +
+
+
+
Globex
+
Initech
+
+
+
+
+
+ +
+
+
+
sync.ts:42
+
parse()
+
+
+
+
+
+ + {/* MODELS — picker UI */} +
+
+

+
+
+
+
75+
+

+
+
+
+
Z
OpenCode Zen
+
OOpenAI
+
CClaude
+
GGemini
+
DDeepSeek
+
KKimi
+
+
+
+
+ + {/* COMPARE */} +
+
+

+ +
+
+ + + + + + + + + + + +
PawWorkCodex App
Apache-2.0
ChatGPT OAuth
OpenCode Zen
Ollama, LM Studio
OfficeCLI
+
+
+
+ +{/* GET */} +
+
+

+

+
+
+
+ + + +
+
+
+
+
+

+
+
+
+
+ + + + diff --git a/site/src/i18n.ts b/site/src/i18n.ts index f6928fcd3..5586d683e 100644 --- a/site/src/i18n.ts +++ b/site/src/i18n.ts @@ -1,7 +1,8 @@ -// EN/CN copy dictionary: single source of truth. -// The server renders EN on first paint (basic SEO); the client swaps to the -// chosen language. Values carry a few inline tags (
) and are -// injected as HTML. +// EN/CN copy dictionary: single source of truth for both language pages. +// Each language renders as its own static page (/ and /zh-CN/) — the server +// renders the full localized HTML at build time, there is no client-side +// language swap. Values carry a few inline tags ( ) injected as +// HTML via set:html, so keep markup balanced and escape bare ampersands. export type Lang = "en" | "cn"; @@ -10,9 +11,10 @@ export type Dict = Record; export const I18N: Record = { en: { title: "PawWork — Real work, done on your desktop", + desc: "Free, open-source AI desktop app for macOS and Windows. No terminal, no API key, no paid plan — open PawWork, choose a folder, and ask in plain language.", brand: "PawWork", "nav.feat": "What it does", - tag: "Open-source · Free to use", + tag: "Open-source, free to use", h1: 'Real work, done on your desktop', sub: "No terminal. No API key. No paid plan. Open PawWork, choose a folder, and ask in plain language.", "dl.mac.t": "Download for macOS", @@ -21,9 +23,9 @@ export const I18N: Record = { "dl.intel.s": "Intel", "dl.win.t": "Windows", "dl.win.s": "x64", - gh2: "On GitHub? Grab the latest release →", + gh2: "On GitHub? Grab the latest release", wnote: - 'Windows: If SmartScreen shows a warning on first launch, click "More info" → "Run anyway". The macOS build is signed and notarized — just open and go.', + 'Windows: If SmartScreen shows a warning on first launch, click "More info", then "Run anyway". The macOS build is signed and notarized — just open and go.', shotnote: "Illustration, not a screenshot", "mock.title": "PawWork — new task", "mock.you": "Turn these 12 invoices into a spreadsheet I can review.", @@ -32,31 +34,79 @@ export const I18N: Record = { "mock.s2": "Extracted vendor, date, total", "mock.s3": "Building spreadsheet…", "mock.rd": "ready to review", - "feat.h2": "What PawWork does", - "cap1.h": "Documents & data", - "cap1.p": "Extract invoice fields into a spreadsheet, generate a CSV summary, merge multiple PDFs.", - "cap2.h": "Research & writing", - "cap2.p": "Search the web, compare multiple pages and compile a memo, turn rough notes into a clean draft.", - "cap3.h": "Code & technical", - "cap3.p": "Understand a codebase, review a pull request, debug issues using logs and source code.", - foot: "Apache-2.0 · Built on OpenCode", + "def.d1": 'PawWork is a free, open-source desktop AI agent for macOS and Windows.', + "def.d2": "An open alternative to Codex App and Claude Desktop (Cowork) — for everyday work, not just browser chat or IDE coding.", + "can.h": "See what it ships", + "can.hint": "Real outputs from plain-language tasks, across files, the web, and code.", + "t1.lab": "12 invoices into one spreadsheet", + "t1.h1": "Vendor", + "t1.h2": "Date", + "t1.h3": "Total", + "t1.foot": "+ 9 more rows, exported to invoices.xlsx", + "t4.lab": "Office files, handled locally", + "t4.badge": "Read & edit on your machine via bundled OfficeCLI", + "t2.lab": "Research into a decision memo", + "t2.mt": "Vendor comparison", + "t2.l1": "18% lower quote, same SLA tier.", + "t2.l2": "Cheapest, but slow support response.", + "t2.pt": "Recommendation: Globex, on price and support", + "t3.lab": "Review a PR, flag the risks", + "t3.rh": "PR #214, 7 files changed", + "t3.f1a": "Unbounded retry loop in", + "t3.f1b": "— can hammer the API.", + "t3.f2a": "Missing null check in", + "t3.f2b": "— minor.", + "m.h": "Your models, your accounts", + "m.num": "model providers supported", + "m.lead": + "Start free with the built-in OpenCode Zen plan and web search. Or connect your own: API keys, ChatGPT OAuth, OpenAI-compatible, and local models.", + "m.search": "Search models", + "m.zen": "Free, web search included", + "m.free": "FREE", + "m.foot": "GLM, Ollama, LM Studio, and 70+ more", + "c.h": "How PawWork compares", + "c.hint": "Next to Codex App and Claude Desktop (Cowork).", + "c.claude": "Claude Desktop", + "c.r1": "Open-source", + "c.r2": "Bring your own key", + "c.r2pw": "75+ providers", + "c.r2cx": "OpenAI only", + "c.r2cl": "Anthropic only", + "c.r4": "Free, no subscription", + "c.r4cx": "Limited", + "c.r4cl": "Pro $20/mo", + "c.r5": "Local models", + "c.r5cx": "CLI only", + "c.r5cl": "Via gateway", + "c.r6": "Office files", + yes: "Yes", + no: "No", + "g.h": "Get PawWork", + "g.sub": "Free and open-source. Download for macOS or Windows and start in minutes.", + "g.mac": "macOS — Apple Silicon and Intel, signed and notarized.", + "g.win": "Windows — x64, currently unsigned installer, so SmartScreen may appear on first launch.", + "g.privacy": + "Your files stay on your machine. You choose the workspace, review every action before it runs, and the code is open-source and auditable.", + "f.readme": "README", + foot: "Apache-2.0, built on OpenCode", }, cn: { title: "爪印 — 真能干活,跑在你电脑上", + desc: "免费开源的桌面 AI 工作助手,支持 macOS 和 Windows。不用终端、不用 API key、不用付费。打开爪印,选个文件夹,说一声就行。", brand: "爪印", "nav.feat": "功能", - tag: "开源 · 下载即用", - h1: '真能干活
跑在你电脑上', - sub: "不用终端,不用 API key,不用付费。打开爪印,选个文件夹,直接告诉它你要什么。", + tag: "开源,下载即用", + h1: '真能干活,跑在你电脑上', + sub: "不用终端,不用 API key,不用付费。打开爪印,选个文件夹,说一声就行。", "dl.mac.t": "下载 macOS 版", "dl.mac.s": "Apple 芯片", "dl.intel.t": "macOS", "dl.intel.s": "Intel", "dl.win.t": "Windows", "dl.win.s": "x64", - gh2: "有 GitHub?去 Releases 下最新版 →", + gh2: "有 GitHub?去 Releases 下载最新版", wnote: - "Windows 用户首次打开时如果弹出 SmartScreen 提示,点「更多信息」→「仍要运行」。macOS 版已签名公证,不会出现此提示。", + "Windows 用户首次打开时如果弹出 SmartScreen 提示,点「更多信息」,再点「仍要运行」。macOS 版已签名公证,不会出现此提示。", shotnote: "示意,非实拍", "mock.title": "爪印 — 新任务", "mock.you": "帮我把这 12 张发票整理成一张表格,方便逐笔核对。", @@ -65,13 +115,59 @@ export const I18N: Record = { "mock.s2": "抽出供应商、日期、金额", "mock.s3": "正在生成表格…", "mock.rd": "待核对", - "feat.h2": "爪印能做什么", - "cap1.h": "文档与数据", - "cap1.p": "从发票提取信息填入表格、为 CSV 生成摘要、合并多个 PDF。", - "cap2.h": "研究与写作", - "cap2.p": "上网查资料、对比多篇网页整理成备忘、把零散笔记写成一篇稿子。", - "cap3.h": "代码与技术", - "cap3.p": "理解一个项目、review 他人的 PR、根据日志和源码定位错误。", - foot: "Apache-2.0 · 基于 OpenCode", + "def.d1": '爪印是一款免费、开源的桌面 AI agent,支持 macOS 和 Windows。', + "def.d2": "Codex App 和 Claude Desktop(Cowork)的开源替代,为日常工作设计,不止是聊天或写代码的工具。", + "can.h": "看看它能做什么", + "can.hint": "用大白话说一声,文件、网页、代码,直接出结果。", + "t1.lab": "12 张发票,变成一张表", + "t1.h1": "供应商", + "t1.h2": "日期", + "t1.h3": "金额", + "t1.foot": "还有 9 行,已导出 invoices.xlsx", + "t4.lab": "Office 文件,本地处理", + "t4.badge": "通过内置 OfficeCLI 在你电脑上读写", + "t2.lab": "调研写成一份决策备忘", + "t2.mt": "供应商对比", + "t2.l1": "报价低 18%,SLA 同档。", + "t2.l2": "最便宜,但支持响应慢。", + "t2.pt": "建议:选 Globex,价格和支持更好", + "t3.lab": "review PR,标出风险", + "t3.rh": "PR #214,改了 7 个文件", + "t3.f1a": "", + "t3.f1b": "存在无限重试循环,可能把 API 打爆。", + "t3.f2a": "", + "t3.f2b": "缺空值检查,是次要问题。", + "m.h": "你的模型,你的账号", + "m.num": "家模型供应商", + "m.lead": + "免费就能用:内置 OpenCode Zen 免费版和联网搜索。想用自己的也行:API key、ChatGPT OAuth、OpenAI 兼容服务、本地模型都接得上。", + "m.search": "搜索模型", + "m.zen": "免费,含联网搜索", + "m.free": "免费", + "m.foot": "GLM、Ollama、LM Studio,还有 70+ 家", + "c.h": "同类对比", + "c.hint": "对比 Codex App 和 Claude Desktop(Cowork)。", + "c.claude": "Claude Desktop", + "c.r1": "开源", + "c.r2": "自带 key", + "c.r2pw": "75+ 家", + "c.r2cx": "仅 OpenAI", + "c.r2cl": "仅 Anthropic", + "c.r4": "免订阅可用", + "c.r4cx": "有限", + "c.r4cl": "需 Pro($20/月)", + "c.r5": "本地模型", + "c.r5cx": "仅 CLI", + "c.r5cl": "经网关", + "c.r6": "Office 文件", + yes: "是", + no: "否", + "g.h": "下载爪印", + "g.sub": "免费、开源。下载 macOS 或 Windows 版,几分钟就能上手。", + "g.mac": "macOS,支持 Apple 芯片与 Intel,已签名公证。", + "g.win": "Windows,x64,当前为未签名安装包,首次打开可能弹出 SmartScreen。", + "g.privacy": "文件留在你电脑上。工作目录你选,每个动作执行前你都能审,代码开源、可审计。", + "f.readme": "说明文档", + foot: "Apache-2.0,基于 OpenCode", }, }; diff --git a/site/src/layouts/Base.astro b/site/src/layouts/Base.astro index c9f3d818e..476868961 100644 --- a/site/src/layouts/Base.astro +++ b/site/src/layouts/Base.astro @@ -1,26 +1,35 @@ --- -// Page shell: basic SEO tags in plus the anti-flash theme script. -// Language switching happens on the client; first paint renders English. +// Page shell: head SEO/meta tags plus the anti-flash theme script. +// Language is fixed per static route: the `lang` prop sets html lang, +// canonical, hreflang, and og:locale. There is no client-side swap. import "../styles/global.css"; +import type { Lang } from "../i18n"; interface Props { title: string; description: string; + lang?: Lang; image?: string; } -const { title, description, image = "/og-image.png" } = Astro.props; +const { title, description, lang = "en", image = "/og-image.png" } = Astro.props; +const htmlLang = lang === "cn" ? "zh-CN" : "en"; const canonical = new URL(Astro.url.pathname, Astro.site).href; const ogImage = new URL(image, Astro.site).href; +const enUrl = new URL("/", Astro.site).href; +const cnUrl = new URL("/zh-CN/", Astro.site).href; --- - + + + + {title} @@ -30,6 +39,8 @@ const ogImage = new URL(image, Astro.site).href; + + @@ -47,6 +58,7 @@ const ogImage = new URL(image, Astro.site).href; "name": "PawWork", "applicationCategory": "BusinessApplication", "operatingSystem": "macOS, Windows", + "inLanguage": lang === "cn" ? "zh-CN" : "en", "description": description, "url": "https://pawwork.ai", "downloadUrl": "https://github.com/Astro-Han/pawwork/releases/latest", diff --git a/site/src/pages/index.astro b/site/src/pages/index.astro index e52ea3262..2749acf45 100644 --- a/site/src/pages/index.astro +++ b/site/src/pages/index.astro @@ -1,172 +1,11 @@ --- import Base from "../layouts/Base.astro"; +import Home from "../components/Home.astro"; import { I18N } from "../i18n"; -import { DOWNLOAD, DOWNLOAD_MANIFEST_URL, REPO_URL, RELEASES_URL } from "../config"; -// First paint renders English (basic SEO); the client then switches by browser -// language or the user's toggle. const t = I18N.en; - -const seoTitle = t["title"]; -const seoDesc = - "Free, open-source AI desktop app for macOS and Windows. No terminal, no API key, no paid plan — open PawWork, choose a folder, and ask in plain language."; --- - - - - - - - - - -
-
- PawWork - -
- -
-
- -

-

-
-
- - - -
- -

-
-
- -
- -
-
-
- -
-
-
-
-
-
-
invoices.xlsx
-
-
- -
-
- -
-

-

-

-

-
-
- -
- PawWork - -
- - + + diff --git a/site/src/pages/zh-CN/index.astro b/site/src/pages/zh-CN/index.astro new file mode 100644 index 000000000..34bc4694e --- /dev/null +++ b/site/src/pages/zh-CN/index.astro @@ -0,0 +1,11 @@ +--- +import Base from "../../layouts/Base.astro"; +import Home from "../../components/Home.astro"; +import { I18N } from "../../i18n"; + +const t = I18N.cn; +--- + + + + diff --git a/site/src/styles/global.css b/site/src/styles/global.css index a7e30d810..694d817d9 100644 --- a/site/src/styles/global.css +++ b/site/src/styles/global.css @@ -1,611 +1,249 @@ /* - PawWork download landing styles. Ported from the approved design at - docs/design/scratch/2026-05-30-download-landing-pawwork-final.html. - Plain CSS + custom properties; light/dark via [data-theme], CN/EN via [data-lang]. - System fonts, warm neutrals, soft shadows, rounded corners, orange as a - restrained accent; dark mode borrows the product's warm-coffee tones. + PawWork homepage v2 styles (#1191 + #1192). Single source: the approved + mockup at docs/design/scratch/2026-06-05-homepage-v2b.html. Plain CSS + custom + properties; light/dark via [data-theme], EN/CN via [data-lang]. Warm neutrals, + orange as a restrained accent; Bricolage Grotesque (self-hosted, Latin subset) + for display headings, system fonts for body and CJK. */ -:root, -[data-theme="light"] { - --brand: #ff5910; - --brand-hover: #e04e0e; - --peach: #fff1e8; - --bg: #faf9f7; - --surface: #ffffff; - --surface-2: #f9f4ee; - --ink: #1a1613; - --ink-2: #4a4138; - --ink-3: #8c817a; - --ink-4: #b6ada7; - --border: #ece6df; - --ring: rgba(11, 6, 0, 0.14); +@font-face { + font-family: "Bricolage Grotesque"; + src: url("/fonts/bricolage-grotesque-latin.woff2") format("woff2"); + font-weight: 200 800; + font-display: swap; +} +:root, [data-theme="light"] { + --brand: #ff5910; --brand-hover: #e04e0e; --peach: #fff1e8; + --bg: #faf9f7; --surface: #ffffff; --surface-2: #f9f4ee; + --ink: #1a1613; --ink-2: #4a4138; --ink-3: #8c817a; --ink-4: #b6ada7; + --border: #ece6df; --ring: rgba(11, 6, 0, 0.14); --raised: 0 6px 24px rgba(26, 22, 19, 0.06), 0 1px 2px rgba(26, 22, 19, 0.05); --float: 0 18px 48px -14px rgba(26, 22, 19, 0.18), 0 4px 12px rgba(26, 22, 19, 0.06); - --onbrand: #fff; + --onbrand: #fff; --green: #1f9d57; } - [data-theme="dark"] { - --brand: #ff6a26; - --brand-hover: #ff7a3a; - --peach: #2b1f19; - --bg: #1a1714; - --surface: #221f1c; - --surface-2: #16130f; - --ink: #f3ede4; - --ink-2: #c5beb4; - --ink-3: #8a8278; - --ink-4: #6b645c; - --border: #2c2823; - --ring: rgba(243, 237, 228, 0.14); + --brand: #ff6a26; --brand-hover: #ff7a3a; --peach: #2b1f19; + --bg: #1a1714; --surface: #221f1c; --surface-2: #16130f; + --ink: #f3ede4; --ink-2: #c5beb4; --ink-3: #8a8278; --ink-4: #6b645c; + --border: #2c2823; --ring: rgba(243, 237, 228, 0.14); --raised: 0 6px 24px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3); --float: 0 24px 60px -16px rgba(0, 0, 0, 0.6), 0 4px 12px rgba(0, 0, 0, 0.4); - --onbrand: #1a1005; -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; + --onbrand: #1a1005; --green: #43c07e; } -html { - scroll-behavior: smooth; +:root { + --display: "Bricolage Grotesque", system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; + --sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; + --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; } +* { box-sizing: border-box; margin: 0; padding: 0; } +html { scroll-behavior: smooth; background: var(--bg); } body { - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; - background: var(--bg); - color: var(--ink); - line-height: 1.5; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - transition: background 0.25s, color 0.25s; - overflow-x: hidden; -} -img { - display: block; - max-width: 100%; -} -a { - color: inherit; - text-decoration: none; -} -.in { - max-width: 1140px; - margin: 0 auto; - padding: 0 40px; -} -@keyframes rise { - from { - opacity: 0; - transform: translateY(18px); - } - to { - opacity: 1; - transform: translateY(0); - } -} -@keyframes spin { - to { - transform: rotate(360deg); - } -} -@keyframes floaty { - 0%, - 100% { - transform: translateY(0) rotate(-7deg); - } - 50% { - transform: translateY(-7px) rotate(-7deg); - } -} + font-family: var(--sans); background: var(--bg); color: var(--ink); line-height: 1.5; + -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + transition: background 0.25s, color 0.25s; overflow-x: hidden; +} +img { display: block; max-width: 100%; } +a { color: inherit; text-decoration: none; } +.in { max-width: 1140px; margin: 0 auto; padding: 0 40px; } +@keyframes rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } } +@keyframes spin { to { transform: rotate(360deg); } } +@keyframes floaty { 0%, 100% { transform: translateY(0) rotate(-7deg); } 50% { transform: translateY(-7px) rotate(-7deg); } } -.bar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 24px 0; -} -.mark { - display: flex; - align-items: center; - gap: 11px; - font-weight: 700; - font-size: 19px; - letter-spacing: -0.015em; -} -.mark img { - width: 32px; - height: 32px; - border-radius: 9px; -} -.nav { - display: flex; - align-items: center; - gap: 16px; -} -.nav a.lk { - font-size: 14px; - font-weight: 500; - color: var(--ink-2); -} -.nav a.lk:hover { - color: var(--brand); -} -.nav .gh { - display: inline-flex; - align-items: center; - gap: 7px; -} -.nav .gh svg { - width: 17px; - height: 17px; -} -.toggle { - height: 36px; - min-width: 36px; - padding: 0 9px; - border: 1px solid var(--border); - border-radius: 10px; - background: var(--surface); - display: inline-grid; - place-items: center; - cursor: pointer; - box-shadow: var(--raised); - transition: transform 0.1s, color 0.15s; - font-size: 13px; - font-weight: 600; - color: var(--ink-2); -} -.toggle:hover { - color: var(--brand); -} -.toggle svg { - width: 17px; - height: 17px; -} -[data-theme="light"] .toggle .moon { - display: none; -} -[data-theme="dark"] .toggle .sun { - display: none; -} -[data-lang="cn"] .toggle .ll-cn { - display: none; -} -[data-lang="en"] .toggle .ll-en { - display: none; -} +/* bar */ +.bar { display: flex; justify-content: space-between; align-items: center; padding: 24px 0; } +.mark { display: flex; align-items: center; gap: 11px; font-weight: 700; font-size: 19px; letter-spacing: -0.015em; font-family: var(--display); } +.mark img { width: 32px; height: 32px; border-radius: 9px; } +.nav { display: flex; align-items: center; gap: 16px; } +.nav a.lk { font-size: 14px; font-weight: 500; color: var(--ink-2); } +.nav a.lk:hover { color: var(--brand); } +.nav .gh { display: inline-flex; align-items: center; gap: 7px; } +.nav .gh svg { width: 17px; height: 17px; } +.toggle { height: 36px; min-width: 36px; padding: 0 9px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); display: inline-grid; place-items: center; cursor: pointer; box-shadow: var(--raised); transition: transform 0.1s, color 0.15s; font-size: 13px; font-weight: 600; color: var(--ink-2); } +.toggle:hover { color: var(--brand); } +.toggle svg { width: 17px; height: 17px; } +[data-theme="light"] .toggle .moon { display: none; } +[data-theme="dark"] .toggle .sun { display: none; } +[data-lang="cn"] .toggle .ll-cn { display: none; } +[data-lang="en"] .toggle .ll-en { display: none; } -.hero { - padding: 58px 0 0; - display: grid; - grid-template-columns: 1.02fr 0.98fr; - gap: 60px; - align-items: center; -} -.tag { - display: inline-flex; - align-items: center; - gap: 9px; - font-size: 13px; - font-weight: 600; - color: var(--ink-2); - background: var(--peach); - border-radius: 999px; - padding: 7px 15px; - animation: rise 0.6s both; -} -.tag .dot { - width: 7px; - height: 7px; - border-radius: 50%; - background: var(--brand); - flex: 0 0 auto; -} -h1 { - font-weight: 800; - font-size: clamp(42px, 3vw + 1.3rem, 72px); - line-height: 1.04; - letter-spacing: -0.035em; - margin-top: 22px; - color: var(--ink); - animation: rise 0.6s 0.05s both; -} -h1 .o { - color: var(--brand); -} -[data-lang="cn"] h1 { - letter-spacing: 0.005em; - line-height: 1.16; -} -.sub { - margin-top: 24px; - font-size: 18px; - line-height: 1.55; - color: var(--ink-2); - max-width: 42ch; - animation: rise 0.6s 0.1s both; -} -.sub b { - color: var(--ink); - font-weight: 600; -} +/* hero (unchanged) */ +.hero { padding: 58px 0 0; display: grid; grid-template-columns: 1.02fr 0.98fr; gap: 60px; align-items: center; } +.tag { display: inline-flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 600; color: var(--ink-2); background: var(--peach); border-radius: 999px; padding: 7px 15px; animation: rise 0.6s both; } +.tag .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--brand); flex: 0 0 auto; } +h1 { font-family: var(--display); font-weight: 800; font-size: clamp(42px, 3vw + 1.3rem, 70px); line-height: 1.04; letter-spacing: -0.035em; margin-top: 22px; color: var(--ink); animation: rise 0.6s 0.05s both; } +h1 .o { color: var(--brand); } +[data-lang="cn"] h1 { letter-spacing: 0.005em; line-height: 1.16; } +.sub { margin-top: 24px; font-size: 18px; line-height: 1.55; color: var(--ink-2); max-width: 42ch; animation: rise 0.6s 0.1s both; } +.sub b { color: var(--ink); font-weight: 600; } +.dlblock { margin-top: 30px; display: flex; flex-direction: column; gap: 14px; align-items: flex-start; animation: rise 0.6s 0.16s both; } +.dl { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; width: 100%; max-width: 430px; } +.dlbtn { display: inline-flex; align-items: center; justify-content: center; gap: 11px; height: 54px; padding: 0 16px; border-radius: 13px; background: var(--surface); box-shadow: 0 0 0 1px var(--ring), var(--raised); color: var(--ink); transition: transform 0.12s, box-shadow 0.12s, background 0.12s; } +.dlbtn:hover { transform: translateY(-2px); box-shadow: 0 0 0 1px var(--brand), 0 12px 26px -10px rgba(255, 89, 16, 0.34); } +.dlbtn svg { width: 20px; height: 20px; flex: 0 0 auto; } +.dlbtn .t { display: flex; flex-direction: column; line-height: 1.18; text-align: left; } +.dlbtn .t b { font-weight: 600; font-size: 14px; } +.dlbtn .t span { font-size: 11px; color: var(--ink-3); } +.dlbtn.lead { grid-column: 1 / -1; background: var(--brand); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 10px 26px -10px rgba(255, 89, 16, 0.5); color: var(--onbrand); } +.dlbtn.lead .t span { color: var(--onbrand); opacity: 0.85; } +.dlbtn.lead:hover { background: var(--brand-hover); transform: translateY(-2px); } +.meta { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; } +.gh2 { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--ink-2); } +.gh2 u { border-bottom: 1px solid var(--ink-4); padding-bottom: 1px; } +.gh2:hover, .gh2:hover u { color: var(--brand); border-color: var(--brand); } +.gh2 svg { width: 15px; height: 15px; flex: 0 0 auto; } +.wnote { font-size: 12.5px; color: var(--ink-3); line-height: 1.55; max-width: 50ch; } +.wnote b { color: var(--ink-2); font-weight: 600; } +.stage { position: relative; animation: rise 0.7s 0.2s both; } +.mock { position: relative; z-index: 2; background: var(--surface); border: 1px solid var(--border); border-radius: 18px; box-shadow: var(--float); overflow: hidden; } +.mock .top { display: flex; align-items: center; gap: 8px; padding: 13px 16px; border-bottom: 1px solid var(--border); background: var(--surface-2); } +.mock .dots { display: flex; gap: 6px; } +.mock .dots i { width: 10px; height: 10px; border-radius: 50%; background: var(--ink-4); opacity: 0.5; } +.mock .dots i:first-child { background: var(--brand); opacity: 1; } +.mock .ttl { font-size: 12.5px; color: var(--ink-3); margin-left: 5px; font-weight: 500; } +.mock .body { padding: 18px; } +.mock .you { display: inline-block; background: var(--peach); border-radius: 14px; border-bottom-right-radius: 5px; padding: 11px 14px; font-size: 13.5px; font-weight: 500; color: var(--ink); max-width: 90%; } +.mock .card { margin-top: 14px; border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--surface); } +.mock .card .ch { display: flex; align-items: center; gap: 9px; padding: 11px 14px; font-weight: 600; font-size: 13px; border-bottom: 1px solid var(--border); } +.mock .card .ch .sp { width: 14px; height: 14px; border: 2px solid var(--brand); border-top-color: transparent; border-radius: 50%; animation: spin 0.9s linear infinite; flex: 0 0 auto; } +.mock .step { display: flex; align-items: center; gap: 10px; padding: 9px 14px; font-size: 13px; color: var(--ink-2); } +.mock .step + .step { border-top: 1px solid var(--border); } +.mock .step .ck { width: 16px; height: 16px; flex: 0 0 auto; color: var(--brand); } +.mock .step.run { color: var(--ink-3); } +.mock .step.run .rb { width: 14px; height: 14px; flex: 0 0 auto; border: 2px dashed var(--ink-4); border-radius: 50%; } +.mock .out { display: flex; align-items: center; gap: 10px; margin: 14px; padding: 11px 14px; border-radius: 12px; background: var(--peach); font-size: 13px; font-weight: 600; } +.mock .out .x { width: 18px; height: 18px; flex: 0 0 auto; color: var(--brand); } +.mock .out .rd { margin-left: auto; font-size: 11px; color: var(--ink-3); font-weight: 500; } +.pawchip { position: absolute; z-index: 3; left: -22px; bottom: -18px; width: 58px; height: 58px; border-radius: 18px; background: var(--brand); display: grid; place-items: center; box-shadow: 0 12px 26px -8px rgba(255, 89, 16, 0.5); animation: floaty 5s ease-in-out infinite; } +.pawchip svg { width: 34px; height: 34px; color: #fff; } +.shotnote { position: absolute; right: 4px; top: -22px; z-index: 2; font-size: 11px; color: var(--ink-4); } -.dlblock { - margin-top: 30px; - display: flex; - flex-direction: column; - gap: 14px; - align-items: flex-start; - animation: rise 0.6s 0.16s both; -} -.dl { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 12px; - width: 100%; - max-width: 430px; -} -.dlbtn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 11px; - height: 54px; - padding: 0 16px; - border-radius: 13px; - background: var(--surface); - box-shadow: 0 0 0 1px var(--ring), var(--raised); - color: var(--ink); - transition: transform 0.12s, box-shadow 0.12s, background 0.12s; -} -.dlbtn:hover { - transform: translateY(-2px); - box-shadow: 0 0 0 1px var(--brand), 0 12px 26px -10px rgba(255, 89, 16, 0.34); -} -.dlbtn svg { - width: 20px; - height: 20px; - flex: 0 0 auto; -} -.dlbtn .t { - display: flex; - flex-direction: column; - line-height: 1.18; - text-align: left; -} -.dlbtn .t b { - font-weight: 600; - font-size: 14px; -} -.dlbtn .t span { - font-size: 11px; - color: var(--ink-3); -} -.dlbtn.lead { - grid-column: 1 / -1; - background: var(--brand); - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 10px 26px -10px rgba(255, 89, 16, 0.5); - color: var(--onbrand); -} -.dlbtn.lead .t span { - color: var(--onbrand); - opacity: 0.74; -} -.dlbtn.lead:hover { - background: var(--brand-hover); - transform: translateY(-2px); -} -.meta { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 18px; -} -.gh2 { - display: inline-flex; - align-items: center; - gap: 8px; - font-size: 13.5px; - color: var(--ink-2); -} -.gh2 u { - border-bottom: 1px solid var(--ink-4); - padding-bottom: 1px; -} -.gh2:hover { - color: var(--brand); -} -.gh2:hover u { - border-color: var(--brand); -} -.gh2 svg { - width: 15px; - height: 15px; - flex: 0 0 auto; -} -.wnote { - font-size: 12.5px; - color: var(--ink-3); - line-height: 1.55; - max-width: 50ch; -} -.wnote b { - color: var(--ink-2); - font-weight: 600; -} +/* definition strip */ +.defstrip { margin-top: 60px; padding: 20px 24px; border: 1px solid var(--border); border-radius: 16px; background: var(--surface-2); display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; } +.defstrip .d1 { font-size: 17px; color: var(--ink); line-height: 1.5; } +.defstrip .d1 b { font-weight: 700; } +.defstrip .d1 .o { color: var(--brand); font-weight: 700; } +.defstrip .d2 { font-size: 14px; color: var(--ink-3); line-height: 1.5; } -.stage { - position: relative; - animation: rise 0.7s 0.2s both; -} -.mock { - position: relative; - z-index: 2; - background: var(--surface); - border: 1px solid var(--border); - border-radius: 18px; - box-shadow: var(--float); - overflow: hidden; -} -.mock .top { - display: flex; - align-items: center; - gap: 8px; - padding: 13px 16px; - border-bottom: 1px solid var(--border); - background: var(--surface-2); -} -.mock .dots { - display: flex; - gap: 6px; -} -.mock .dots i { - width: 10px; - height: 10px; - border-radius: 50%; - background: var(--ink-4); - opacity: 0.5; -} -.mock .dots i:first-child { - background: var(--brand); - opacity: 1; -} -.mock .ttl { - font-size: 12.5px; - color: var(--ink-3); - margin-left: 5px; - font-weight: 500; -} -.mock .body { - padding: 18px; -} -.mock .you { - display: inline-block; - background: var(--peach); - border-radius: 14px; - border-bottom-right-radius: 5px; - padding: 11px 14px; - font-size: 13.5px; - font-weight: 500; - color: var(--ink); - max-width: 90%; -} -.mock .card { - margin-top: 14px; - border: 1px solid var(--border); - border-radius: 14px; - overflow: hidden; - background: var(--surface); -} -.mock .card .ch { - display: flex; - align-items: center; - gap: 9px; - padding: 11px 14px; - font-weight: 600; - font-size: 13px; - border-bottom: 1px solid var(--border); -} -.mock .card .ch .sp { - width: 14px; - height: 14px; - border: 2px solid var(--brand); - border-top-color: transparent; - border-radius: 50%; - animation: spin 0.9s linear infinite; - flex: 0 0 auto; -} -.mock .step { - display: flex; - align-items: center; - gap: 10px; - padding: 9px 14px; - font-size: 13px; - color: var(--ink-2); -} -.mock .step + .step { - border-top: 1px solid var(--border); -} -.mock .step .ck { - width: 16px; - height: 16px; - flex: 0 0 auto; - color: var(--brand); -} -.mock .step.run { - color: var(--ink-3); -} -.mock .step.run .rb { - width: 14px; - height: 14px; - flex: 0 0 auto; - border: 2px dashed var(--ink-4); - border-radius: 50%; -} -.mock .out { - display: flex; - align-items: center; - gap: 10px; - margin: 14px; - padding: 11px 14px; - border-radius: 12px; - background: var(--peach); - font-size: 13px; - font-weight: 600; -} -.mock .out .x { - width: 18px; - height: 18px; - flex: 0 0 auto; - color: var(--brand); -} -.mock .out .rd { - margin-left: auto; - font-size: 11px; - color: var(--ink-3); - font-weight: 500; -} -.pawchip { - position: absolute; - z-index: 3; - left: -22px; - bottom: -18px; - width: 58px; - height: 58px; - border-radius: 18px; - background: var(--brand); - display: grid; - place-items: center; - box-shadow: 0 12px 26px -8px rgba(255, 89, 16, 0.5); - animation: floaty 5s ease-in-out infinite; -} -.pawchip svg { - width: 34px; - height: 34px; - color: #fff; -} -.shotnote { - position: absolute; - right: 4px; - top: -22px; - z-index: 2; - font-size: 11px; - color: var(--ink-4); -} +/* section heads */ +.sec { padding-top: clamp(54px, 6vw, 80px); } +.sechead { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; } +.sec h2 { font-family: var(--display); font-weight: 700; font-size: clamp(28px, 1.8vw + 1rem, 40px); line-height: 1.06; letter-spacing: -0.025em; color: var(--ink); } +[data-lang="cn"] .sec h2 { letter-spacing: 0; } +.sec .hint { font-size: 14px; color: var(--ink-3); max-width: 40ch; } -.caps { - padding: 88px 0 0; - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 16px; -} -.cap { - border: 1px solid var(--border); - border-radius: 16px; - background: var(--surface); - box-shadow: var(--raised); - padding: 22px 22px 24px; - transition: transform 0.14s, box-shadow 0.14s; -} -.cap:hover { - transform: translateY(-3px); - box-shadow: var(--float); -} -.cap .ic { - width: 40px; - height: 40px; - border-radius: 11px; - display: grid; - place-items: center; - color: var(--brand); - background: var(--peach); - margin-bottom: 14px; -} -.cap .ic svg { - width: 21px; - height: 21px; -} -.cap h3 { - font-weight: 700; - font-size: 15.5px; - margin-bottom: 7px; - letter-spacing: -0.01em; -} -.cap p { - font-size: 13.5px; - color: var(--ink-2); - line-height: 1.55; -} +/* bento */ +.bento { margin-top: 36px; display: grid; grid-template-columns: repeat(12, 1fr); gap: 16px; } +.tile { grid-column: span 6; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); box-shadow: var(--raised); padding: 22px; display: flex; flex-direction: column; min-height: 220px; transition: transform 0.14s, box-shadow 0.14s; overflow: hidden; } +.tile:hover { transform: translateY(-3px); box-shadow: var(--float); } +.tile.wide { grid-column: span 7; } +.tile.narrow { grid-column: span 5; } +.tile .lab { font-family: var(--display); font-weight: 700; font-size: 17px; letter-spacing: -0.01em; } +[data-lang="cn"] .tile .lab { letter-spacing: 0; } +.tile .art { margin-top: 16px; flex: 1; display: flex; flex-direction: column; justify-content: center; } -footer { - margin-top: 80px; - border-top: 1px solid var(--border); -} -.foot { - max-width: 1140px; - margin: 0 auto; - padding: 28px 40px 60px; - display: flex; - justify-content: space-between; - align-items: center; - flex-wrap: wrap; - gap: 14px; - font-size: 13px; - color: var(--ink-3); -} -.foot .mark { - font-size: 15px; -} -.foot .mark img { - width: 26px; - height: 26px; -} -@media (max-width: 860px) { - .hero, - .caps { - grid-template-columns: 1fr; - } - .stage { - order: -1; - margin-bottom: 8px; - } -} +/* artifact: spreadsheet */ +.sheet { border: 1px solid var(--border); border-radius: 11px; overflow: hidden; font-size: 12.5px; background: var(--surface); } +.sheet .r { display: grid; grid-template-columns: 1.5fr 1fr 0.9fr; } +.sheet .r > div { padding: 8px 12px; border-bottom: 1px solid var(--border); color: var(--ink-2); } +.sheet .r > div + div { border-left: 1px solid var(--border); } +.sheet .head > div { background: var(--surface-2); font-weight: 600; color: var(--ink-3); } +.sheet .r:last-child > div { border-bottom: none; } +.sheet .num { font-variant-numeric: tabular-nums; color: var(--ink); font-weight: 600; } +.sheetfoot { margin-top: 9px; font-size: 12px; color: var(--ink-4); } -/* Phones: tighten the header so brand, GitHub, language and theme controls - all fit on one row down to ~320px. The secondary "What it does" anchor is - dropped (the section is just below) and the brand shrinks slightly. */ -@media (max-width: 600px) { - .in { - padding: 0 18px; - } - .bar { - padding: 18px 0; - } - .mark { - gap: 9px; - font-size: 17px; - } - .mark img { - width: 28px; - height: 28px; - } - .nav { - gap: 10px; - } - .nav a.lk { - display: none; - } -} +/* artifact: memo */ +.memo { border: 1px solid var(--border); border-radius: 11px; background: var(--surface); padding: 16px; } +.memo .mt { font-weight: 700; font-size: 13.5px; color: var(--ink); } +.memo .row { display: flex; gap: 8px; margin-top: 9px; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; } +.memo .row .k { font-weight: 600; color: var(--ink); flex: 0 0 auto; } +.memo .pt { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 12.5px; color: var(--ink-2); } +.memo .pt svg { width: 13px; height: 13px; color: var(--brand); flex: 0 0 auto; } + +/* artifact: review */ +.review { border: 1px solid var(--border); border-radius: 11px; background: var(--surface); overflow: hidden; } +.review .rh { display: flex; align-items: center; gap: 8px; padding: 10px 13px; border-bottom: 1px solid var(--border); font-size: 12.5px; font-weight: 600; color: var(--ink-2); background: var(--surface-2); } +.review .rh .gh { width: 14px; height: 14px; } +.review .fr { display: flex; align-items: flex-start; gap: 9px; padding: 10px 13px; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; } +.review .fr + .fr { border-top: 1px solid var(--border); } +.review .sev { margin-top: 0; width: 15px; height: 15px; flex: 0 0 auto; color: var(--brand); } +.review .sev.low { color: var(--ink-4); } +.review .fr code { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); } + +/* artifact: office files */ +.files { display: flex; flex-wrap: wrap; gap: 10px; } +.fchip { display: inline-flex; align-items: center; gap: 8px; padding: 9px 13px; border: 1px solid var(--border); border-radius: 11px; background: var(--surface); box-shadow: var(--raised); font-size: 12.5px; font-weight: 600; color: var(--ink-2); } +.fchip .ext { font-family: var(--display); font-weight: 700; font-size: 11px; color: var(--onbrand); background: var(--brand); border-radius: 5px; padding: 2px 6px; letter-spacing: 0.02em; } +.oclibadge { margin-top: 14px; display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ink-3); } +.oclibadge svg { width: 13px; height: 13px; color: var(--green); flex: 0 0 auto; } -.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; +/* models */ +.models { margin-top: 36px; display: grid; grid-template-columns: 0.92fr 1.08fr; gap: 40px; align-items: center; } +.models .mlead { font-size: 16px; color: var(--ink-2); line-height: 1.6; max-width: 38ch; } +.models .mlead b { color: var(--ink); font-weight: 600; } +.bignum { font-family: var(--display); font-weight: 800; font-size: clamp(48px, 5vw, 76px); line-height: 1; letter-spacing: -0.03em; color: var(--brand); padding-bottom: 18px; border-bottom: 1px solid var(--border); } +.bignum span { display: block; font-size: 14px; font-weight: 600; letter-spacing: 0; color: var(--ink-3); margin-top: 8px; } +.picker { border: 1px solid var(--border); border-radius: 16px; background: var(--surface); box-shadow: var(--float); overflow: hidden; } +.picker .psearch { display: flex; align-items: center; gap: 9px; padding: 13px 15px; border-bottom: 1px solid var(--border); color: var(--ink-4); font-size: 13px; background: var(--surface-2); } +.picker .psearch svg { width: 15px; height: 15px; } +.prow { display: flex; align-items: center; gap: 11px; padding: 11px 15px; font-size: 13.5px; } +.prow + .prow { border-top: 1px solid var(--border); } +.prow .av { width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; font-family: var(--display); font-weight: 700; font-size: 13px; color: var(--ink); background: var(--surface-2); flex: 0 0 auto; } +.prow .nm { font-weight: 600; color: var(--ink); } +.prow .ds { color: var(--ink-3); font-size: 12px; } +.prow.free { background: var(--peach); } +.prow.free .av { background: var(--brand); color: var(--onbrand); } +.prow .pill { margin-left: auto; font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; color: var(--brand); background: var(--surface); border: 1px solid var(--brand); border-radius: 999px; padding: 3px 9px; } +.prow .check { margin-left: auto; width: 15px; height: 15px; color: var(--green); } +.pfoot { padding: 11px 15px; border-top: 1px solid var(--border); font-size: 12px; color: var(--ink-3); background: var(--surface-2); } + +/* compare */ +.cmpwrap { margin-top: 36px; border: 1px solid var(--border); border-radius: 18px; overflow: hidden; box-shadow: var(--raised); background: var(--surface); } +table.cmp { width: 100%; border-collapse: collapse; font-size: 14px; } +table.cmp th, table.cmp td { text-align: left; padding: 14px 18px; border-bottom: 1px solid var(--border); vertical-align: middle; } +table.cmp thead th { font-family: var(--display); font-weight: 700; font-size: 14.5px; color: var(--ink-3); background: var(--surface-2); } +table.cmp thead th.pw { color: var(--ink); background: var(--peach); } +table.cmp td.pw { background: color-mix(in srgb, var(--peach) 55%, transparent); } +table.cmp tbody tr:last-child td { border-bottom: none; } +table.cmp .rowh { font-weight: 600; color: var(--ink-2); } +table.cmp td { color: var(--ink-4); } +table.cmp .yes { display: inline-flex; align-items: center; gap: 7px; color: var(--ink); font-weight: 600; } +table.cmp .yes svg { width: 15px; height: 15px; color: var(--brand); flex: 0 0 auto; } +.cmp colgroup col.c-pw { width: 25%; } + +/* get */ +.get { margin-top: clamp(70px, 8vw, 104px); border-top: 1px solid var(--border); padding: clamp(56px, 7vw, 88px) 0 0; } +.geth { font-family: var(--display); font-weight: 800; font-size: clamp(30px, 2vw + 1rem, 46px); letter-spacing: -0.03em; color: var(--ink); } +[data-lang="cn"] .geth { letter-spacing: 0; } +.getsub { margin-top: 12px; font-size: 16px; color: var(--ink-2); } +.getsub b { color: var(--ink); font-weight: 600; } +.getgrid { margin-top: 30px; display: grid; grid-template-columns: minmax(0, 430px) 1fr; gap: 52px; align-items: start; } +.getright { display: flex; flex-direction: column; gap: 14px; padding-top: 2px; } +.platline { display: flex; align-items: flex-start; gap: 11px; font-size: 14px; color: var(--ink-2); line-height: 1.55; } +.platline svg { margin-top: 1px; width: 16px; height: 16px; flex: 0 0 auto; } +.platline .ico-ok { color: var(--green); } +.platline .ico-warn { color: var(--brand); } +.platline b { color: var(--ink); font-weight: 600; } +.getprivacy { margin-top: 6px; font-size: 13px; color: var(--ink-3); line-height: 1.6; } +.getprivacy b { color: var(--ink-2); font-weight: 600; } + +/* footer */ +footer { margin-top: clamp(64px, 7vw, 96px); border-top: 1px solid var(--border); } +.foot { max-width: 1140px; margin: 0 auto; padding: 28px 40px 56px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px; font-size: 13px; color: var(--ink-3); } +.foot .mark { font-size: 15px; } +.foot .mark img { width: 26px; height: 26px; } +.foot .flinks { display: flex; gap: 18px; flex-wrap: wrap; } +.foot .flinks a:hover { color: var(--brand); } + +@media (max-width: 900px) { + .hero, .models, .getgrid { grid-template-columns: 1fr; gap: 40px; } + .stage { order: -1; } + .tile, .tile.wide, .tile.narrow { grid-column: span 12; } + .cmpwrap { overflow-x: auto; } + table.cmp { min-width: 620px; } +} +@media (max-width: 600px) { + .in { padding: 0 18px; } + .nav a.lk { display: none; } + .foot { padding: 24px 18px 44px; } } +@media (prefers-reduced-motion: reduce) { *, html { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; } .dlbtn:hover, .dlbtn.lead:hover, .tile:hover { transform: none !important; } }