From 513c3c3cfe90394ad342f9d87661303f45b92b38 Mon Sep 17 00:00:00 2001 From: Shahaf Antwarg Date: Sun, 23 Aug 2026 11:44:35 +0300 Subject: [PATCH 1/2] Add static site generator for aips.antseed.com --- .gitignore | 2 + README.md | 18 +++ package-lock.json | 157 ++++++++++++++++++++++++ package.json | 15 +++ scripts/build-site.mjs | 273 +++++++++++++++++++++++++++++++++++++++++ site/style.css | 272 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 737 insertions(+) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 scripts/build-site.mjs create mode 100644 site/style.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a799fb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +_site/ diff --git a/README.md b/README.md index ec28047..a3bf5ea 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,24 @@ locally: node scripts/validate.mjs ``` +## Website + +The site at [aips.antseed.com](https://aips.antseed.com) is generated straight +from `AIPS/*.md` — one page per proposal plus an index grouped by status. No +CMS, no server: `scripts/build-site.mjs` renders the markdown with the +templates and styles in `site/`, and Cloudflare Pages builds and deploys on +every merge to `main`. + +Build locally: + +```bash +npm install +npm run build # validates, then renders to _site/ +``` + +Cloudflare Pages settings: build command `npm run build`, output directory +`_site`, production branch `main`. + ## Copyright All AIPs, and this repository's documentation, are released under diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..243fba6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,157 @@ +{ + "name": "antseed-aips", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "antseed-aips", + "dependencies": { + "js-yaml": "^4.1.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^9.2.0" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/markdown-it": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-NoQ2yGlLWj4wpxMs+TYmRKk3thDrQ97agr7sFqfLsAlvoS8SNQuTrlObhFqG9iugdTtgOE9jpJ6FNM4ZGsa5xQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT", + "peer": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/linkify-it": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/markdown-it": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz", + "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.5.0", + "linkify-it": "^5.0.2", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-9.2.1.tgz", + "integrity": "sha512-p6APiLJDFAW2GEvaavDvhIBn7jrX2jLv77NkBGgNacFTurbORYc4pyYySg/mI6mpR6cHQuAtzKtmqgQr4K8dsQ==", + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/mdurl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", + "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", + "license": "MIT" + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..aa4fb2c --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "antseed-aips", + "private": true, + "type": "module", + "description": "AntSeed Improvement Proposals — validator and static site generator", + "scripts": { + "validate": "node scripts/validate.mjs", + "build": "node scripts/validate.mjs && node scripts/build-site.mjs" + }, + "dependencies": { + "js-yaml": "^4.1.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^9.2.0" + } +} diff --git a/scripts/build-site.mjs b/scripts/build-site.mjs new file mode 100644 index 0000000..8525595 --- /dev/null +++ b/scripts/build-site.mjs @@ -0,0 +1,273 @@ +// Static site generator for aips.antseed.com. +// Reads AIPS/*.md, renders one page per AIP plus an index grouped by status. +// Output: _site/ (deployed by Cloudflare Pages on merges to main). + +import { readdirSync, readFileSync, writeFileSync, mkdirSync, cpSync, existsSync } from 'node:fs'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import yaml from 'js-yaml'; +import MarkdownIt from 'markdown-it'; +import anchor from 'markdown-it-anchor'; + +const root = join(dirname(fileURLToPath(import.meta.url)), '..'); +const out = join(root, '_site'); +const REPO = 'https://github.com/AntSeed/AIPs'; + +const STATUS_ORDER = ['Living', 'Final', 'Last Call', 'Review', 'Draft', 'Stagnant', 'Withdrawn']; +const STATUS_BLURB = { + Living: 'Continually updated; never reaches finality.', + Final: 'The accepted standard.', + 'Last Call': 'Final review window before Final.', + Review: 'Author has requested peer review.', + Draft: 'Well-formed and formally tracked; content still changing.', + Stagnant: 'Inactive for six months or more.', + Withdrawn: 'Withdrawn by the author.', +}; + +const md = new MarkdownIt({ html: true, linkify: true, typographer: true }).use(anchor, { + permalink: anchor.permalink.linkInsideHeader({ symbol: '#', placement: 'after', class: 'h-anchor' }), +}); + +// Rewrite intra-repo markdown links to site routes. +const defaultLinkOpen = + md.renderer.rules.link_open ?? ((tokens, idx, options, env, self) => self.renderToken(tokens, idx, options)); +md.renderer.rules.link_open = (tokens, idx, options, env, self) => { + const href = tokens[idx].attrGet('href'); + if (href) { + const aip = href.match(/^(?:\.\/|\.\.\/AIPS\/|AIPS\/)?aip-(\d+)(?:\.md)?(#.*)?$/); + if (aip) tokens[idx].attrSet('href', `/aip-${aip[1]}${aip[2] ?? ''}`); + else if (/^(\.\.\/)?LICENSE$/.test(href)) tokens[idx].attrSet('href', `${REPO}/blob/main/LICENSE`); + else if (/^(\.\/|\.\.\/)?aip-template\.md$/.test(href)) tokens[idx].attrSet('href', `${REPO}/blob/main/aip-template.md`); + else if (/^(\.\.\/)?CONTRIBUTING\.md$/.test(href)) tokens[idx].attrSet('href', `${REPO}/blob/main/CONTRIBUTING.md`); + else if (href.startsWith('../assets/') || href.startsWith('assets/')) + tokens[idx].attrSet('href', `/${href.replace(/^\.\.\//, '')}`); + } + return defaultLinkOpen(tokens, idx, options, env, self); +}; + +const esc = (s) => + String(s).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); + +function parse(file) { + const raw = readFileSync(join(root, 'AIPS', file), 'utf8'); + const m = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/); + if (!m) throw new Error(`${file}: missing frontmatter`); + return { front: yaml.load(m[1]), body: m[2], file }; +} + +// Render "FirstName LastName (@user)" with the handle linked. +const renderAuthors = (author) => + esc(author).replace(/\(@([A-Za-z0-9-]+)\)/g, '(@$1)'); + +const statusClass = (s) => `status-${s.toLowerCase().replace(/\s+/g, '-')}`; + +function tocFor(body) { + const items = []; + for (const t of md.parse(body, {})) { + if (t.type === 'heading_open' && t.tag === 'h2') items.push({ open: true }); + else if (t.type === 'inline' && items.length && items[items.length - 1].open) { + const it = items[items.length - 1]; + it.text = t.content; + it.id = t.content.toLowerCase().replace(/[^\w\s-]/g, '').trim().replace(/\s+/g, '-'); + it.open = false; + } + } + return items.filter((i) => i.text); +} + +const css = readFileSync(join(root, 'site', 'style.css'), 'utf8'); + +const page = ({ title, description, canonicalPath, content, extraClass = '' }) => ` + + + + +${esc(title)} + + +' +)}"> + + + + + + + +
+ +
+${content} + + +`; + +// ── collect ────────────────────────────────────────────────────────── +const aips = readdirSync(join(root, 'AIPS')) + .filter((f) => /^aip-\d+\.md$/.test(f)) + .map(parse) + .sort((a, b) => a.front.aip - b.front.aip); + +mkdirSync(out, { recursive: true }); +if (existsSync(join(root, 'assets'))) cpSync(join(root, 'assets'), join(out, 'assets'), { recursive: true }); + +// ── per-AIP pages ──────────────────────────────────────────────────── +const PREAMBLE_ROWS = [ + ['description', 'Description'], + ['author', 'Author'], + ['discussions-to', 'Discussion'], + ['status', 'Status'], + ['type', 'Type'], + ['category', 'Category'], + ['created', 'Created'], + ['requires', 'Requires'], +]; + +for (const { front, body, file } of aips) { + const n = front.aip; + const rows = PREAMBLE_ROWS.filter(([k]) => front[k] != null) + .map(([k, label]) => { + let v; + if (k === 'author') v = renderAuthors(front.author); + else if (k === 'discussions-to') v = `${esc(front[k])}`; + else if (k === 'status') v = `${esc(front.status)}`; + else if (k === 'requires') + v = String(front.requires) + .split(/,\s*/) + .map((r) => `AIP-${r.trim()}`) + .join(', '); + else if (k === 'created') v = ``; + else v = esc(front[k]); + return `
${label}
${v}
`; + }) + .join('\n'); + + const toc = tocFor(body); + const tocHtml = toc.length + ? `` + : ''; + + const content = ` +
+ + ${tocHtml} +
`; + + mkdirSync(join(out, `aip-${n}`), { recursive: true }); + writeFileSync( + join(out, `aip-${n}`, 'index.html'), + page({ + title: `AIP-${n}: ${front.title} — AntSeed Improvement Proposals`, + description: front.description, + canonicalPath: `/aip-${n}`, + content, + extraClass: 'is-doc', + }) + ); +} + +// ── index ──────────────────────────────────────────────────────────── +const groups = STATUS_ORDER.map((status) => ({ + status, + items: aips.filter((a) => a.front.status === status), +})).filter((g) => g.items.length); + +const tables = groups + .map( + ({ status, items }) => ` +
+
+

${esc(status)}

+

${esc(STATUS_BLURB[status] ?? '')}

+
+ + + + ${items + .map(({ front }) => { + const type = front.category ? `${front.type} · ${front.category}` : front.type; + return ` + + + + + `; + }) + .join('\n')} + +
NumberTitleTypeAuthor
${front.aip}${esc(front.title)}${esc(front.description)}${esc(type)}${renderAuthors(front.author)}
+
` + ) + .join('\n'); + +const indexContent = ` +
+
+

AntSeed
Improvement
Proposals

+

Design documents for the AntSeed peer-to-peer AI services network — + protocol standards, contract specifications, and process. Anyone may author one: + start from AIP-1 and open a pull request against + AntSeed/AIPs.

+
${aips.length} proposal${aips.length === 1 ? '' : 's'} · ${groups + .map((g) => `${g.items.length} ${g.status.toLowerCase()}`) + .join(' · ')}
+
+
+
+${tables} +
`; + +writeFileSync( + join(out, 'index.html'), + page({ + title: 'AntSeed Improvement Proposals', + description: 'Design documents for the AntSeed peer-to-peer AI services network.', + canonicalPath: '/', + content: indexContent, + }) +); + +writeFileSync( + join(out, 'index.json'), + JSON.stringify( + aips.map(({ front }) => ({ ...front, url: `https://aips.antseed.com/aip-${front.aip}` })), + null, + 2 + ) +); + +// Cloudflare Pages: clean-URL 404 fallback. +writeFileSync( + join(out, '404.html'), + page({ + title: 'Not found — AntSeed Improvement Proposals', + description: 'No such proposal.', + canonicalPath: '/404', + content: `

Not found

+

No proposal lives at this address. Browse the index.

`, + }) +); + +console.log(`built ${aips.length} AIP page(s) + index → _site/`); diff --git a/site/style.css b/site/style.css new file mode 100644 index 0000000..c30e54d --- /dev/null +++ b/site/style.css @@ -0,0 +1,272 @@ +/* aips.antseed.com — "protocol ledger" + Deep-forest chrome, mint paper, emerald accent. General Sans for display, + Source Serif 4 for normative prose, Geist Mono for data. */ + +:root { + --forest-950: #001408; + --forest-900: #001e12; + --forest-800: #06281b; + --forest-700: #143226; + --emerald: #10b981; + --emerald-bright: #24cd95; + --emerald-deep: #008359; + --mint: #e2fff0; + + --paper: #f7fbf8; + --paper-raised: #ffffff; + --ink: #0b1f16; + --ink-soft: #46584e; + --hairline: #d3e2d8; + --hairline-soft: #e4efe7; + --accent: var(--emerald-deep); + --accent-soft: rgba(16, 185, 129, 0.12); + + --font-display: 'General Sans', system-ui, sans-serif; + --font-prose: 'Source Serif 4', Georgia, serif; + --font-mono: 'Geist Mono', ui-monospace, 'Fira Code', monospace; +} + +@media (prefers-color-scheme: dark) { + :root { + --paper: #041b10; + --paper-raised: #06281b; + --ink: #dcefe4; + --ink-soft: #8fa89a; + --hairline: #17382a; + --hairline-soft: #0f2e21; + --accent: var(--emerald-bright); + --accent-soft: rgba(36, 205, 149, 0.14); + } +} + +* { box-sizing: border-box; } +html { scroll-behavior: smooth; } +body { + margin: 0; + background: var(--paper); + color: var(--ink); + font-family: var(--font-display); + font-weight: 500; + line-height: 1.55; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} +a { color: var(--accent); text-decoration: none; } +a:hover { text-decoration: underline; text-underline-offset: 3px; } +.mono { font-family: var(--font-mono); font-size: 0.92em; } +.shell { max-width: 76rem; margin: 0 auto; padding: 0 clamp(1.1rem, 4vw, 2.5rem); } + +/* ── masthead ─────────────────────────────────────────────────────── */ +.masthead { + background: var(--forest-900); + color: var(--mint); + border-bottom: 3px solid var(--emerald-bright); +} +.masthead-row { + display: flex; align-items: center; justify-content: space-between; + gap: 1.5rem; padding-top: 1.05rem; padding-bottom: 1.05rem; +} +.wordmark { + color: #fff; font-weight: 700; letter-spacing: -0.01em; + display: inline-flex; align-items: baseline; gap: 0.55rem; font-size: 1.02rem; +} +.wordmark em { font-style: normal; font-weight: 500; color: var(--emerald-bright); } +.wordmark:hover { text-decoration: none; } +.seed { + width: 0.62rem; height: 0.62rem; border-radius: 999px; + background: var(--emerald-bright); align-self: center; + box-shadow: 0 0 0 4px rgba(36, 205, 149, 0.22); +} +.mast-nav { display: flex; gap: 1.6rem; } +.mast-nav a { + color: var(--mint); font-family: var(--font-mono); font-size: 0.8rem; + text-transform: uppercase; letter-spacing: 0.09em; +} +.mast-nav a:hover { color: var(--emerald-bright); text-decoration: none; } + +/* ── hero ─────────────────────────────────────────────────────────── */ +.hero { + background: + radial-gradient(52rem 26rem at 85% -30%, rgba(36, 205, 149, 0.16), transparent 65%), + var(--forest-950); + color: var(--mint); + padding: clamp(3rem, 7vw, 5.5rem) 0 clamp(2.6rem, 5vw, 4rem); + border-bottom: 1px solid var(--forest-700); +} +.hero h1 { + margin: 0; + font-size: clamp(2.6rem, 7vw, 4.6rem); + line-height: 0.98; letter-spacing: -0.03em; font-weight: 700; color: #fff; +} +.hero-sub { + max-width: 44rem; margin: 1.4rem 0 0; font-size: 1.06rem; + line-height: 1.65; color: #b9d9c8; +} +.hero-sub a { color: var(--emerald-bright); } +.hero-meta { + margin-top: 2rem; font-size: 0.78rem; letter-spacing: 0.08em; + text-transform: uppercase; color: #6f957f; +} + +/* ── index tables ─────────────────────────────────────────────────── */ +.status-group { padding: 2.6rem 0 0.4rem; } +.status-group:last-child { padding-bottom: 3.5rem; } +.group-head { display: flex; align-items: baseline; gap: 1rem; margin-bottom: 0.9rem; } +.group-head h2 { margin: 0; font-size: 1rem; } +.group-head p { margin: 0; color: var(--ink-soft); font-size: 0.86rem; } + +.aip-table { width: 100%; border-collapse: collapse; } +.aip-table th { + text-align: left; font-family: var(--font-mono); font-size: 0.7rem; + text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-soft); + font-weight: 500; padding: 0.45rem 0.9rem; border-bottom: 2px solid var(--ink); +} +.aip-table td { + padding: 0.85rem 0.9rem; border-bottom: 1px solid var(--hairline); + vertical-align: baseline; +} +.aip-table tr:hover td { background: var(--accent-soft); } +.col-num { width: 5.2rem; } +.col-num a { font-weight: 500; } +.col-type { width: 13rem; font-size: 0.8rem; color: var(--ink-soft); } +.col-auth { width: 16rem; font-size: 0.9rem; color: var(--ink-soft); } +.row-title { display: block; font-weight: 600; color: var(--ink); font-size: 1.02rem; } +.row-title:hover { color: var(--accent); text-decoration: none; } +.row-desc { display: block; margin-top: 0.18rem; font-size: 0.86rem; color: var(--ink-soft); } +@media (max-width: 720px) { + .col-type, .col-auth { display: none; } +} + +/* ── status pills ─────────────────────────────────────────────────── */ +.pill { + display: inline-block; padding: 0.14rem 0.62rem; border-radius: 999px; + font-family: var(--font-mono); font-size: 0.72rem; font-weight: 500; + text-transform: uppercase; letter-spacing: 0.08em; + border: 1px solid currentColor; +} +.status-living { color: var(--emerald-deep); background: var(--accent-soft); } +.status-final { color: #fff; background: var(--emerald-deep); border-color: var(--emerald-deep); } +.status-last-call{ color: #8a5a00; background: rgba(212, 160, 23, 0.14); } +.status-review { color: #205e8f; background: rgba(59, 130, 246, 0.12); } +.status-draft { color: var(--ink-soft); background: transparent; } +.status-stagnant { color: var(--ink-soft); background: var(--hairline-soft); border-style: dashed; } +.status-withdrawn{ color: #8f2d2d; background: rgba(190, 60, 60, 0.1); } +@media (prefers-color-scheme: dark) { + .status-living { color: var(--emerald-bright); } + .status-last-call { color: #e3b74a; } + .status-review { color: #7db4e0; } + .status-withdrawn { color: #e08f8f; } +} + +/* ── document pages ───────────────────────────────────────────────── */ +.doc-shell { + display: grid; grid-template-columns: minmax(0, 1fr) 15rem; + gap: 3.5rem; padding-top: 2.8rem; padding-bottom: 4rem; +} +@media (max-width: 940px) { .doc-shell { grid-template-columns: minmax(0, 1fr); } .toc { display: none; } } + +.doc { position: relative; min-width: 0; } +.doc-kicker { + font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.06em; + text-transform: uppercase; color: var(--ink-soft); margin-bottom: 0.7rem; +} +.doc-kicker a { color: var(--ink-soft); } +.doc-kicker a:hover { color: var(--accent); } +.ghost-numeral { + position: absolute; top: -1.4rem; right: -0.5rem; z-index: 0; + font-family: var(--font-display); font-weight: 700; + font-size: clamp(6rem, 16vw, 11rem); line-height: 1; + color: transparent; -webkit-text-stroke: 1.5px var(--hairline); + pointer-events: none; user-select: none; +} +.doc-title { + position: relative; z-index: 1; margin: 0 0 1.6rem; + font-size: clamp(1.9rem, 4.5vw, 2.9rem); line-height: 1.08; + letter-spacing: -0.02em; font-weight: 700; max-width: 46rem; +} + +.preamble { + position: relative; z-index: 1; + margin: 0 0 2.4rem; padding: 0.4rem 0; + border-top: 2px solid var(--ink); border-bottom: 1px solid var(--hairline); + background: transparent; +} +.pre-row { display: grid; grid-template-columns: 8.5rem minmax(0, 1fr); gap: 1rem; padding: 0.42rem 0; } +.pre-row + .pre-row { border-top: 1px solid var(--hairline-soft); } +.preamble dt { + font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase; + letter-spacing: 0.1em; color: var(--ink-soft); padding-top: 0.18rem; +} +.preamble dd { margin: 0; font-size: 0.95rem; overflow-wrap: anywhere; } + +/* ── prose ────────────────────────────────────────────────────────── */ +.prose { + font-family: var(--font-prose); font-weight: 400; + font-size: 1.07rem; line-height: 1.72; max-width: 46rem; +} +.prose h2, .prose h3, .prose h4 { + font-family: var(--font-display); letter-spacing: -0.015em; line-height: 1.2; + margin: 2.6rem 0 0.9rem; font-weight: 600; +} +.prose h2 { + font-size: 1.55rem; padding-top: 1.4rem; border-top: 1px solid var(--hairline); +} +.prose h3 { font-size: 1.18rem; } +.prose h4 { font-size: 1rem; } +.h-anchor { margin-left: 0.45rem; color: var(--hairline); font-family: var(--font-mono); font-size: 0.8em; } +.prose h2:hover .h-anchor, .prose h3:hover .h-anchor, .prose h4:hover .h-anchor { color: var(--accent); } +.prose p { margin: 0 0 1.1rem; } +.prose strong { font-weight: 600; } +.prose ul, .prose ol { padding-left: 1.4rem; margin: 0 0 1.1rem; } +.prose li { margin: 0.35rem 0; } +.prose li::marker { color: var(--accent); font-family: var(--font-mono); font-size: 0.9em; } +.prose blockquote { + margin: 1.4rem 0; padding: 0.9rem 1.2rem; + border-left: 3px solid var(--emerald); background: var(--accent-soft); + font-size: 0.98rem; +} +.prose blockquote p:last-child { margin-bottom: 0; } +.prose code { + font-family: var(--font-mono); font-size: 0.84em; + background: var(--hairline-soft); border-radius: 4px; padding: 0.1em 0.35em; + overflow-wrap: anywhere; +} +.prose pre { + background: var(--forest-950); color: var(--mint); + border-radius: 8px; padding: 1.1rem 1.3rem; overflow-x: auto; + margin: 1.4rem 0; border: 1px solid var(--forest-700); + font-size: 0.83rem; line-height: 1.6; +} +.prose pre code { background: none; padding: 0; font-size: inherit; color: inherit; } +.prose table { border-collapse: collapse; width: 100%; margin: 1.4rem 0; font-size: 0.92rem; display: block; overflow-x: auto; } +.prose th, .prose td { border: 1px solid var(--hairline); padding: 0.5rem 0.8rem; text-align: left; } +.prose th { font-family: var(--font-display); font-size: 0.85rem; background: var(--hairline-soft); } +.prose hr { border: 0; border-top: 1px solid var(--hairline); margin: 2.4rem 0; } +.prose img { max-width: 100%; } +.doc-source { margin-top: 3rem; font-family: var(--font-mono); font-size: 0.8rem; } + +/* ── toc ──────────────────────────────────────────────────────────── */ +.toc { position: sticky; top: 2rem; align-self: start; padding-top: 3.4rem; } +.toc h2 { + margin: 0 0 0.7rem; font-family: var(--font-mono); font-size: 0.7rem; + text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink-soft); font-weight: 500; +} +.toc ol { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--hairline); } +.toc li a { + display: block; padding: 0.28rem 0 0.28rem 0.9rem; font-size: 0.84rem; + color: var(--ink-soft); border-left: 2px solid transparent; margin-left: -1px; +} +.toc li a:hover { color: var(--accent); border-left-color: var(--accent); text-decoration: none; } + +/* ── footer ───────────────────────────────────────────────────────── */ +.colophon { + border-top: 1px solid var(--hairline); margin-top: 2rem; + background: var(--paper-raised); +} +.colophon-row { + display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; + padding-top: 1.3rem; padding-bottom: 1.3rem; + font-family: var(--font-mono); font-size: 0.76rem; color: var(--ink-soft); +} +.colophon a { color: var(--ink-soft); text-decoration: underline; text-underline-offset: 3px; } +.colophon a:hover { color: var(--accent); } From a2af5694337bba11891b519ee3ce257d5a9e3aad Mon Sep 17 00:00:00 2001 From: Shahaf Antwarg Date: Sun, 23 Aug 2026 11:56:57 +0300 Subject: [PATCH 2/2] Simplify site design to plain paper-and-ink --- scripts/build-site.mjs | 40 ++---- site/style.css | 300 +++++++++++++---------------------------- 2 files changed, 104 insertions(+), 236 deletions(-) diff --git a/scripts/build-site.mjs b/scripts/build-site.mjs index 8525595..0d05458 100644 --- a/scripts/build-site.mjs +++ b/scripts/build-site.mjs @@ -14,16 +14,6 @@ const out = join(root, '_site'); const REPO = 'https://github.com/AntSeed/AIPs'; const STATUS_ORDER = ['Living', 'Final', 'Last Call', 'Review', 'Draft', 'Stagnant', 'Withdrawn']; -const STATUS_BLURB = { - Living: 'Continually updated; never reaches finality.', - Final: 'The accepted standard.', - 'Last Call': 'Final review window before Final.', - Review: 'Author has requested peer review.', - Draft: 'Well-formed and formally tracked; content still changing.', - Stagnant: 'Inactive for six months or more.', - Withdrawn: 'Withdrawn by the author.', -}; - const md = new MarkdownIt({ html: true, linkify: true, typographer: true }).use(anchor, { permalink: anchor.permalink.linkInsideHeader({ symbol: '#', placement: 'after', class: 'h-anchor' }), }); @@ -59,7 +49,6 @@ function parse(file) { const renderAuthors = (author) => esc(author).replace(/\(@([A-Za-z0-9-]+)\)/g, '(@$1)'); -const statusClass = (s) => `status-${s.toLowerCase().replace(/\s+/g, '-')}`; function tocFor(body) { const items = []; @@ -91,13 +80,13 @@ const page = ({ title, description, canonicalPath, content, extraClass = '' }) = - +
- AntSeed Improvement Proposals + AntSeed Improvement Proposals