diff --git a/.github/brand/brand.lock.json b/.github/brand/brand.lock.json index 0897d7f..90371d9 100644 --- a/.github/brand/brand.lock.json +++ b/.github/brand/brand.lock.json @@ -1,15 +1,15 @@ { "schema_version": 2, "authority": "https://github.com/computer-mcp/.github", - "revision": "9042c987ef8b3482f63e3a037ae0d0d2fdeffb9a7768c03295c9a6a6c5a43ae2", + "revision": "2d9913a442afcb22faca90f5272d3988eb961be6e858b71c5067303cf7c627d6", "consumer": "computer-mcp.github.io", "files": { "public/brand/icon.svg": "28250027a8aeafb3ec79defabd89d2279c4329fd2fd64cfc923b8803a78416f9", "public/brand/favicon.svg": "a60dff8e1adb06eb431d09b113b12f5e47b75a5f759fcbcc91083ddf1305d292", "public/brand/favicon-32.png": "50ca36c37a8b480d4081fd4bcb7b9fdc1be10272ca8e51f554adcf343999900f", "public/brand/apple-touch-icon.png": "198e9dfabecc73bfcc2608cb0ff963694e0811bbfa23337cadcfd7a4da38e0af", - "public/brand/social-en.png": "2dcb1c201e9ae2d6358b2d893c315d4291f28597eea5753bda7d26a101cbb93d", - "public/brand/social-zh-CN.png": "ec008afcda87f8bc5957eb45060072a317d5f09b380ba896186f8a965bca7f00", + "public/brand/social-en.png": "574a4ddb9e0787880af0db87a611e81f101280cf0588176ffcdbf15d303e4c69", + "public/brand/social-zh-CN.png": "7f5b90e73ec27078796db3e20b339d850cb0afb24bdb17d738d26ce185ccc744", "public/brand/icons/plugin-codex.svg": "c482350f0ebd76536cd54da6ebb3e4a86cb2529319bb6492dbe0352ac5b63569", "public/brand/icons/plugin-computer-use.svg": "1d848bfa746345d91cf4b5eb9c72b8867b9b8b7c6ce87b3289b85aac7bf42448", "public/brand/icons/plugin-claude.svg": "a3b8c20af24a0043ff6e4739e3915b523684347a693121e435a1c7501767e7e1", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e9275f..14e79a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,9 +36,6 @@ jobs: - name: Validate catalog publisher policy run: npm run catalog:check-policy - - name: Verify bundled fonts - run: npm run fonts:check - - name: Check formatting run: npm run format:check diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 399caa1..b83d25e 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -67,7 +67,6 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - npm run fonts:check npm run release:check npm run catalog:check-policy npm run catalog:check diff --git a/.prettierignore b/.prettierignore index bd8a21e..5bb202b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,7 +6,5 @@ test-results # Brand files and their lock are delivered by the organization brand sync. .github/brand/ public/brand/ -# Generated by scripts/fonts.py. -src/fonts/ # Canonical bytes are generated and validated by plugin_catalog.py. public/plugins/index.json diff --git a/AGENTS.md b/AGENTS.md index 2cd74fa..db405dd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -136,8 +136,7 @@ instead of a literal value. - `public/brand/` and `.github/brand/brand.lock.json` are organization imports; update them only with the organization's `Brand/brand.py sync`. The lock also requires the tagline in both languages, the social image and the favicon in `index.html`. -- `src/fonts/` is generated by `scripts/fonts.py update` from pinned sources. Regenerate it after - copy changes; keep `THIRD_PARTY_NOTICES.md` aligned with the font sources. +- Text uses the system font stacks; do not bundle web fonts. - Chinese is the default page text. Every visible string, link target and metadata value that differs by language carries its English counterpart in `data-en`, `data-en-href` or `data-en-content`. diff --git a/README.md b/README.md index 4900ba5..833af7c 100644 --- a/README.md +++ b/README.md @@ -101,14 +101,10 @@ directly. Update them from an organization checkout with `python3 Brand/brand.py sync ` and commit the result. CI verifies the lock with the organization's shared brand check. -`src/fonts/` holds WOFF2 subsets of Bricolage Grotesque, JetBrains Mono and Noto Sans SC. After a -copy change, regenerate them from their pinned sources with -`uv run --no-project --with fonttools --with brotli python3 scripts/fonts.py update`; -`npm run fonts:check` fails when a page uses a character the subset lacks. -[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) carries the font licenses. +Text uses the visitor's system fonts: SF Pro, SF Mono and PingFang SC on Apple devices. The site +bundles no font files. ## License Computer MCP-owned website code and content use the -[Functional Source License 1.1, Apache 2.0 Future License](LICENSE) (FSL-1.1-ALv2). The bundled -fonts keep their own licenses; see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). +[Functional Source License 1.1, Apache 2.0 Future License](LICENSE) (FSL-1.1-ALv2). diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md deleted file mode 100644 index 5625c8e..0000000 --- a/THIRD_PARTY_NOTICES.md +++ /dev/null @@ -1,108 +0,0 @@ -# Third-party notices - -The published site bundles subsets of three fonts licensed under the SIL Open Font License, Version -1.1. [`scripts/fonts.py`](scripts/fonts.py) builds them from the pinned -[google/fonts](https://github.com/google/fonts/tree/9710da1eacb3be272583c3224dcb70f9da6eadbb/ofl) -sources: each is subset to the characters the pages use and converted to WOFF2, and the Noto Sans SC -weight axis is limited to 400–800. The font files keep their original names, copyright and license -metadata. - -| Font | Files | Copyright | -| ------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------- | -| Bricolage Grotesque | `src/fonts/bricolage-grotesque.woff2` | Copyright 2022 The Bricolage Grotesque Project Authors (https://github.com/ateliertriay/bricolage) | -| JetBrains Mono | `src/fonts/jetbrains-mono.woff2` | Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) | -| Noto Sans SC | `src/fonts/noto-sans-sc.woff2` | Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source' | - -Development dependencies used to build and test the site are not part of the published artifact and -keep their own licenses. - -## SIL Open Font License, Version 1.1 - -```text ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. -``` diff --git a/package.json b/package.json index 4925bf0..22b7e4e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "format:check": "prettier --check .", "check:html": "html-validate index.html guide/index.html", "check:links": "node scripts/check-links.mjs", - "fonts:check": "python3 scripts/fonts.py check", "test": "npm run catalog:test && node --test scripts/release.test.mjs scripts/check-links.test.mjs && playwright test", "catalog:test": "python3 -m unittest discover -s scripts -p 'test_plugin_catalog*.py'", "catalog:check": "python3 scripts/plugin_catalog.py check", @@ -21,7 +20,7 @@ "release:update": "node scripts/release.mjs update", "release:verify-public": "node scripts/release.mjs verify-public", "test:install": "playwright install chromium", - "check": "npm run fonts:check && npm run release:check && npm run catalog:check-policy && npm run format:check && npm run check:html && npm run build && npm run check:links && npm run test" + "check": "npm run release:check && npm run catalog:check-policy && npm run format:check && npm run check:html && npm run build && npm run check:links && npm run test" }, "engines": { "node": ">=22" diff --git a/public/brand/social-en.png b/public/brand/social-en.png index 7d8a4d6..e2f32e5 100644 Binary files a/public/brand/social-en.png and b/public/brand/social-en.png differ diff --git a/public/brand/social-zh-CN.png b/public/brand/social-zh-CN.png index f044453..5cf345f 100644 Binary files a/public/brand/social-zh-CN.png and b/public/brand/social-zh-CN.png differ diff --git a/scripts/fonts.py b/scripts/fonts.py deleted file mode 100644 index 7b10359..0000000 --- a/scripts/fonts.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python3 -"""Build and check the bundled web fonts. - -update subset the pinned OFL sources into src/fonts and rewrite the lock - (requires fontTools and brotli: - uv run --no-project --with fonttools --with brotli scripts/fonts.py update) -check verify the lock, the committed files and the page text (standard library only) -""" - -import hashlib -import json -import sys -import urllib.request -from pathlib import Path - -ROOT = Path(__file__).resolve().parents[1] -FONTS = ROOT / "src/fonts" -LOCK = FONTS / "fonts.lock.json" -CACHE = ROOT / ".cache/fonts" -PAGES = ["index.html", "guide/index.html", "src/main.js"] -GOOGLE_FONTS = "https://raw.githubusercontent.com/google/fonts/9710da1eacb3be272583c3224dcb70f9da6eadbb/ofl" -LATIN = "U+0020-007E,U+00A0-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2010-2027,U+2030-203A,U+2190-2193,U+2212,U+2215" -SOURCES = [ - { - "file": "bricolage-grotesque.woff2", - "family": "Bricolage Grotesque", - "url": f"{GOOGLE_FONTS}/bricolagegrotesque/BricolageGrotesque%5Bopsz%2Cwdth%2Cwght%5D.ttf", - "sha256": "413e7357809ddd12fd80a96a8a396de0e401638d4acd3cb3e37532f0472ac682", - "unicodes": LATIN, - }, - { - "file": "jetbrains-mono.woff2", - "family": "JetBrains Mono", - "url": f"{GOOGLE_FONTS}/jetbrainsmono/JetBrainsMono%5Bwght%5D.ttf", - "sha256": "48715a42ec242c21e9f02692891e147d022299a52e48d5e413e1a942193ffeda", - "unicodes": LATIN, - }, - { - "file": "noto-sans-sc.woff2", - "family": "Noto Sans SC", - "url": f"{GOOGLE_FONTS}/notosanssc/NotoSansSC%5Bwght%5D.ttf", - "sha256": "a3041811a78c361b1de50f953c805e0244951c21c5bd412f7232ef0d899af0da", - "unicodes": "page", - "weights": [400, 800], - }, -] - - -def sha256(data): - return hashlib.sha256(data).hexdigest() - - -def page_characters(): - """CJK characters and full-width punctuation used by the pages.""" - text = "".join((ROOT / name).read_text() for name in PAGES) - return "".join(sorted({char for char in text if ord(char) >= 0x2E80})) - - -def source(font): - path = CACHE / f"{font['sha256']}.ttf" - if not path.is_file(): - CACHE.mkdir(parents=True, exist_ok=True) - with urllib.request.urlopen(font["url"], timeout=120) as response: - path.write_bytes(response.read()) - if sha256(path.read_bytes()) != font["sha256"]: - path.unlink() - sys.exit(f"Source digest mismatch: {font['family']}") - return path - - -def update(): - from fontTools import subset - from fontTools.ttLib import TTFont - from fontTools.varLib import instancer - - characters = page_characters() - files = {} - for font in SOURCES: - ttf = TTFont(source(font)) - options = subset.Options() - options.flavor = "woff2" - options.layout_features = ["*"] - options.name_IDs = ["*"] - options.name_languages = ["*"] - options.notdef_outline = True - subsetter = subset.Subsetter(options) - if font["unicodes"] == "page": - subsetter.populate(text=characters) - else: - subsetter.populate(unicodes=subset.parse_unicodes(font["unicodes"])) - subsetter.subset(ttf) - if "weights" in font: - low, high = font["weights"] - ttf = instancer.instantiateVariableFont(ttf, {"wght": (low, high)}) - output = FONTS / font["file"] - FONTS.mkdir(parents=True, exist_ok=True) - ttf.flavor = "woff2" - ttf.save(output) - files[font["file"]] = sha256(output.read_bytes()) - print(f"{font['file']}: {output.stat().st_size // 1024} KiB") - lock = { - "schema_version": 1, - "sources": {font["file"]: font["sha256"] for font in SOURCES}, - "files": files, - "page_characters": characters, - } - LOCK.write_text(json.dumps(lock, indent=2, ensure_ascii=False) + "\n") - - -def check(): - lock = json.loads(LOCK.read_text()) - errors = [] - if lock.get("sources") != {font["file"]: font["sha256"] for font in SOURCES}: - errors.append("Font sources changed; run the update command.") - for name, expected in lock.get("files", {}).items(): - path = FONTS / name - if not path.is_file() or sha256(path.read_bytes()) != expected: - errors.append(f"{name} differs from fonts.lock.json.") - missing = sorted(set(page_characters()) - set(lock.get("page_characters", ""))) - if missing: - errors.append(f"Noto Sans SC subset lacks {''.join(missing)}; run the update command.") - print("\n".join(errors) or "Bundled fonts match their lock and the page text.") - return 1 if errors else 0 - - -if __name__ == "__main__": - command = sys.argv[1] if len(sys.argv) == 2 else "" - if command == "update": - update() - elif command == "check": - sys.exit(check()) - else: - sys.exit(__doc__) diff --git a/src/fonts/bricolage-grotesque.woff2 b/src/fonts/bricolage-grotesque.woff2 deleted file mode 100644 index 904bd2a..0000000 Binary files a/src/fonts/bricolage-grotesque.woff2 and /dev/null differ diff --git a/src/fonts/fonts.lock.json b/src/fonts/fonts.lock.json deleted file mode 100644 index e09370a..0000000 --- a/src/fonts/fonts.lock.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "schema_version": 1, - "sources": { - "bricolage-grotesque.woff2": "413e7357809ddd12fd80a96a8a396de0e401638d4acd3cb3e37532f0472ac682", - "jetbrains-mono.woff2": "48715a42ec242c21e9f02692891e147d022299a52e48d5e413e1a942193ffeda", - "noto-sans-sc.woff2": "a3041811a78c361b1de50f953c805e0244951c21c5bd412f7232ef0d899af0da" - }, - "files": { - "bricolage-grotesque.woff2": "73797a2f1d5732ece7bd34472df9475870a5c2fb1b868353b8f63173ee26c5ee", - "jetbrains-mono.woff2": "a2f1d0779ba091809fde00d8cf0cf727f932100c0d0e476b58627d4fc97cfbb4", - "noto-sans-sc.woff2": "258f52bcf95ffb47594eb7388ee7f1819a6894d49a395065972916d8dbd6c43e" - }, - "page_characters": "、。一三上下不与且两个中串为主久么义之也了予事于云互些交享人什仅介仍从他代令以们件任份优会但低体何作你使例供依侧保修做停储允先免兜入全公共关其具兼内册再写决准几凭出切列创判别到制刷前剪力功加务动助包化匙匹区单南即厂原参及发取受变口另只可台号各合同名后吗否含启周命和哪商回围在地址型域填备复外多天夹好如始委存它安完官定实审客容宿密察对导少就层屏属工差己已布希带常幕并序应底度建开异式引归当录径待得必忆态怎性意成我或户所手打执扫批把护拖择括持指按换据授排接控描提插搜摘操支收改放数整文料新方无时明是显普暴更最有服望期未本机权束条来板构果架查栏校核格桌档检模次欢款止正此步每比求沙没沿法注派流测消添清源然版牌状独现理生用电界留略的盖目直相看真码确示票私秒称移程窗立站端第等策签算管箱类系索级组终绍经结给统绪续编缺网置考者聊联能脑脚自范获菜行表装要覆观览解计认让记许设访证试话说请读调负责账贴费资赖走起超跑跟跨路跳身载辅辑输边迁过迎运返还这进远连述适选途通遍那部都配里重量钥链错问间阅际降限险随隐集需露面页项预题风驻验骤高默,:;?" -} diff --git a/src/fonts/jetbrains-mono.woff2 b/src/fonts/jetbrains-mono.woff2 deleted file mode 100644 index a2a82c5..0000000 Binary files a/src/fonts/jetbrains-mono.woff2 and /dev/null differ diff --git a/src/fonts/noto-sans-sc.woff2 b/src/fonts/noto-sans-sc.woff2 deleted file mode 100644 index 1d2ee97..0000000 Binary files a/src/fonts/noto-sans-sc.woff2 and /dev/null differ diff --git a/src/styles.css b/src/styles.css index 3c2f043..5fbb0d1 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,26 +1,3 @@ -@font-face { - font-family: "Bricolage Grotesque"; - src: url("./fonts/bricolage-grotesque.woff2") format("woff2"); - font-weight: 200 800; - font-stretch: 75% 100%; - font-display: swap; -} - -@font-face { - font-family: "JetBrains Mono"; - src: url("./fonts/jetbrains-mono.woff2") format("woff2"); - font-weight: 100 800; - font-display: swap; -} - -@font-face { - font-family: "Noto Sans SC"; - src: url("./fonts/noto-sans-sc.woff2") format("woff2"); - font-weight: 400 800; - font-display: swap; - unicode-range: U+2E80-FFFF; -} - :root { color-scheme: light dark; --ink: #16181d; @@ -49,8 +26,9 @@ --shadow: 0 1px 0 rgba(0, 0, 0, 0.05), 0 22px 40px -14px rgba(10, 16, 30, 0.3); --packet-shadow: 0 6px 14px -6px rgba(10, 16, 30, 0.25); --font-sans: - "Bricolage Grotesque", "Noto Sans SC", "PingFang SC", "Hiragino Sans GB", system-ui, sans-serif; - --font-mono: "JetBrains Mono", "Noto Sans SC", ui-monospace, "SF Mono", Menlo, monospace; + -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", "PingFang SC", + "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei", system-ui, sans-serif; + --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; --offset: 48px; --header: 64px; } @@ -92,9 +70,8 @@ body { background: var(--page); color: var(--text); font-family: var(--font-sans); - font-size: 16px; - line-height: 1.6; - font-variation-settings: "opsz" 14; + font-size: 17px; + line-height: 1.53; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } @@ -132,6 +109,10 @@ a:hover { border-radius: 4px; } +html:lang(en) body { + letter-spacing: -0.022em; +} + h1:lang(zh-CN), h2:lang(zh-CN) { word-break: keep-all; @@ -165,7 +146,7 @@ h2:lang(zh-CN) { border-radius: 12px; background: var(--ink); color: var(--paper); - font: 600 14px/1.2 var(--font-mono); + font: 600 14px/1.2 var(--font-sans); transform: translateY(-160%); } @@ -177,9 +158,7 @@ h2:lang(zh-CN) { .capability-kind, .path-kind { color: var(--accent-text); - font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.06em; - text-transform: uppercase; + font: 600 15px/1.3 var(--font-sans); } /* Header */ @@ -211,8 +190,8 @@ h2:lang(zh-CN) { align-items: center; gap: 10px; font-size: 18px; - font-weight: 650; - letter-spacing: -0.01em; + font-weight: 600; + letter-spacing: -0.015em; text-decoration: none; white-space: nowrap; } @@ -231,8 +210,9 @@ h2:lang(zh-CN) { padding: 8px 12px; border-radius: 10px; color: var(--muted); - font-size: 15px; + font-size: 14px; text-decoration: none; + white-space: nowrap; } .primary-nav a:hover, @@ -256,8 +236,9 @@ h2:lang(zh-CN) { border-radius: 12px; background: var(--raised); color: var(--text); - font: 600 13px/1 var(--font-mono); + font: 500 14px/1 var(--font-sans); cursor: pointer; + white-space: nowrap; } .menu-toggle { @@ -273,8 +254,7 @@ h2:lang(zh-CN) { min-height: 48px; padding: 0 20px; border-radius: 12px; - font: 600 14px/1.2 var(--font-mono); - letter-spacing: 0.02em; + font: 500 15px/1.2 var(--font-sans); text-decoration: none; transition: background-color 140ms ease, @@ -313,7 +293,7 @@ h2:lang(zh-CN) { .text-link { display: inline-block; margin-top: 20px; - font: 600 14px/1.4 var(--font-mono); + font: 500 15px/1.4 var(--font-sans); text-decoration-color: var(--vermilion); } @@ -333,33 +313,28 @@ h2:lang(zh-CN) { } .hero-meta { - letter-spacing: 0.02em; text-transform: none; } .hero h1 { margin-top: 20px; - font-size: 88px; - font-weight: 700; - line-height: 0.98; - letter-spacing: -0.035em; - font-variation-settings: - "opsz" 96, - "wdth" 88; + font-size: 80px; + font-weight: 600; + line-height: 1.05; + letter-spacing: -0.015em; } .hero h1:lang(zh-CN) { - font-size: 68px; - font-weight: 800; - line-height: 1.12; - letter-spacing: -0.01em; + font-size: clamp(52px, 5vw, 64px); + font-weight: 600; + line-height: 1.14; + letter-spacing: 0; } .hero-lede { max-width: 34em; margin-top: 28px; font-size: 18px; - font-variation-settings: "opsz" 18; } .hero-support { @@ -389,8 +364,7 @@ h2:lang(zh-CN) { border: 1px solid var(--line); border-radius: 6px; background: var(--chip); - font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.04em; + font: 500 13px/1.2 var(--font-sans); } /* Hero scene: chat card high, stack low, one link bending into the stack. */ @@ -417,8 +391,7 @@ h2:lang(zh-CN) { .chat-title { margin-bottom: 10px; color: var(--muted); - font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.06em; + font: 600 13px/1.2 var(--font-sans); } .chat-request { @@ -479,7 +452,6 @@ h2:lang(zh-CN) { background: var(--raised); box-shadow: var(--packet-shadow); font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.02em; white-space: nowrap; transform: translateX(50%); } @@ -527,7 +499,6 @@ h2:lang(zh-CN) { align-items: flex-end; padding: 0 18px 14px; font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.03em; white-space: nowrap; } @@ -546,6 +517,10 @@ h2:lang(zh-CN) { box-shadow: var(--shadow); } +.plane-capabilities { + font-family: var(--font-sans); +} + .plane-result { bottom: calc(2 * var(--offset)); left: calc(2 * var(--offset)); @@ -554,7 +529,7 @@ h2:lang(zh-CN) { border: 1px solid var(--line); background: var(--raised); box-shadow: var(--shadow); - font: 450 13px/1.6 var(--font-mono); + font: 400 13px/1.6 var(--font-mono); } .result-head { @@ -563,8 +538,7 @@ h2:lang(zh-CN) { gap: 12px; margin-bottom: 8px; color: var(--muted); - font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.02em; + font: 600 13px/1.2 var(--font-sans); } .result-host { @@ -701,26 +675,22 @@ h2:lang(zh-CN) { .closing h2 { margin-top: 14px; font-size: 56px; - font-weight: 700; - line-height: 1.02; - letter-spacing: -0.03em; - font-variation-settings: - "opsz" 72, - "wdth" 90; + font-weight: 600; + line-height: 1.07; + letter-spacing: -0.005em; } .section-heading h2:lang(zh-CN) { font-size: 44px; - font-weight: 800; + font-weight: 600; line-height: 1.18; - letter-spacing: -0.01em; + letter-spacing: 0; } .section-heading > p:not(.eyebrow) { margin-top: 18px; color: var(--muted); font-size: 18px; - font-variation-settings: "opsz" 18; } .section-note { @@ -733,9 +703,9 @@ h2:lang(zh-CN) { h3 { font-size: 22px; - font-weight: 650; + font-weight: 600; line-height: 1.2; - letter-spacing: -0.01em; + letter-spacing: 0.004em; } /* Capabilities */ @@ -804,7 +774,7 @@ h3 { .capability > a, .capability-links { margin-top: auto; - font: 600 14px/1.4 var(--font-mono); + font: 500 15px/1.4 var(--font-sans); } .capability-links { @@ -858,7 +828,7 @@ h3 { border-radius: 20px; background: var(--raised); box-shadow: var(--shadow); - font: 600 13px/1.2 var(--font-mono); + font: 600 13px/1.2 var(--font-sans); text-align: center; } @@ -903,7 +873,7 @@ h3 { .host p { color: var(--muted); - font: 600 12px/1.2 var(--font-mono); + font: 600 13px/1.2 var(--font-sans); } .mini-stack { @@ -1001,7 +971,7 @@ h3 { content: "0" counter(level); grid-row: span 2; color: var(--accent-text); - font: 600 13px/1.7 var(--font-mono); + font: 600 13px/1.7 var(--font-sans); } .levels p { @@ -1023,7 +993,7 @@ h3 { align-items: center; justify-content: space-between; gap: 12px; - font: 600 13px/1.3 var(--font-mono); + font: 600 14px/1.3 var(--font-sans); } .badge-caution { @@ -1031,8 +1001,7 @@ h3 { border-radius: 6px; background: var(--caution); color: var(--ink); - font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.04em; + font: 600 12px/1.2 var(--font-sans); } .approval-choices { @@ -1047,7 +1016,7 @@ h3 { border: 1px solid var(--line); border-radius: 12px; color: var(--muted); - font: 600 13px/1.2 var(--font-mono); + font: 500 13px/1.2 var(--font-sans); } .choice-selected { @@ -1111,7 +1080,7 @@ thead th, thead td { border-top: 0; font-size: 18px; - font-weight: 650; + font-weight: 600; } thead th.own { @@ -1129,9 +1098,7 @@ tbody th { width: 150px; background: var(--raised); color: var(--muted); - font: 600 12px/1.5 var(--font-mono); - letter-spacing: 0.04em; - text-transform: uppercase; + font: 600 13px/1.5 var(--font-sans); } .sources { @@ -1166,12 +1133,9 @@ tbody th { .steps li::before { content: "0" counter(step); font-size: 44px; - font-weight: 700; + font-weight: 600; line-height: 1; - letter-spacing: -0.03em; - font-variation-settings: - "opsz" 72, - "wdth" 90; + letter-spacing: -0.005em; } .steps p { @@ -1181,7 +1145,7 @@ tbody th { .steps a { margin-top: auto; - font: 600 14px/1.4 var(--font-mono); + font: 500 15px/1.4 var(--font-sans); } .first-call { @@ -1217,7 +1181,7 @@ pre { border-radius: 12px; background: var(--code-bg); color: var(--code-text); - font: 450 13px/1.6 var(--font-mono); + font: 400 13px/1.6 var(--font-mono); } pre code { @@ -1239,7 +1203,7 @@ pre button { border-radius: 10px; background: transparent; color: var(--code-text); - font: 600 12px/1 var(--font-mono); + font: 500 12px/1 var(--font-sans); cursor: pointer; } @@ -1266,7 +1230,7 @@ summary { min-height: 64px; padding: 12px 0; font-size: 19px; - font-weight: 650; + font-weight: 600; line-height: 1.3; list-style: none; cursor: pointer; @@ -1280,7 +1244,7 @@ summary::after { content: "+"; flex: none; color: var(--accent-text); - font: 500 22px/1 var(--font-mono); + font: 300 24px/1 var(--font-sans); transition: rotate 160ms ease; } @@ -1300,7 +1264,7 @@ details > :last-child { details a { margin-top: 12px; - font: 600 14px/1.4 var(--font-mono); + font: 500 15px/1.4 var(--font-sans); } /* Closing and footer */ @@ -1317,9 +1281,9 @@ details a { .closing h2:lang(zh-CN) { max-width: none; font-size: 56px; - font-weight: 800; + font-weight: 600; line-height: 1.15; - letter-spacing: -0.01em; + letter-spacing: 0; } .site-footer { @@ -1342,9 +1306,7 @@ details a { .site-footer h2 { margin-bottom: 14px; color: var(--muted); - font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.06em; - text-transform: uppercase; + font: 600 12px/1.3 var(--font-sans); } .site-footer ul { @@ -1400,7 +1362,7 @@ details a { border-radius: 12px; background: var(--ink); color: var(--paper); - font: 600 13px/1.3 var(--font-mono); + font: 500 13px/1.3 var(--font-sans); opacity: 0; pointer-events: none; transform: translate(-50%, 8px); @@ -1425,19 +1387,16 @@ details a { .doc h1 { margin-top: 16px; font-size: 56px; - font-weight: 700; - line-height: 1.02; - letter-spacing: -0.03em; - font-variation-settings: - "opsz" 72, - "wdth" 90; + font-weight: 600; + line-height: 1.07; + letter-spacing: -0.005em; } .doc h1:lang(zh-CN) { font-size: 44px; - font-weight: 800; + font-weight: 600; line-height: 1.18; - letter-spacing: -0.01em; + letter-spacing: 0; } .doc-lede { @@ -1456,9 +1415,7 @@ details a { .toc h2 { color: var(--muted); - font: 600 12px/1.2 var(--font-mono); - letter-spacing: 0.06em; - text-transform: uppercase; + font: 600 13px/1.3 var(--font-sans); } .toc ol { @@ -1470,7 +1427,7 @@ details a { .toc li { padding: 4px 0; - font-family: var(--font-mono); + font-family: var(--font-sans); font-size: 14px; } @@ -1480,14 +1437,14 @@ details a { .doc section h2 { font-size: 32px; - font-weight: 650; + font-weight: 600; line-height: 1.1; - letter-spacing: -0.02em; + letter-spacing: 0.004em; } .doc section h2:lang(zh-CN) { font-size: 30px; - font-weight: 800; + font-weight: 600; letter-spacing: 0; } @@ -1526,7 +1483,7 @@ details a { border: 1px solid var(--line); border-radius: 50%; background: var(--chip); - font: 600 12px/1 var(--font-mono); + font: 600 12px/1 var(--font-sans); } .doc-terms { @@ -1585,7 +1542,7 @@ details a { } .hero h1:lang(zh-CN) { - font-size: 56px; + font-size: 50px; } }