diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
new file mode 100644
index 0000000..e702518
--- /dev/null
+++ b/.github/workflows/pages.yml
@@ -0,0 +1,61 @@
+name: Publish GitHub Pages
+
+env:
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v4
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: npm
+
+ - name: Configure GitHub Pages
+ uses: actions/configure-pages@v5
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build site
+ run: npm run build
+
+ - name: Upload Pages artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ./dist
+
+ deploy:
+ if: github.event_name != 'pull_request'
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index ce89292..9a55258 100644
--- a/.gitignore
+++ b/.gitignore
@@ -256,6 +256,10 @@ ClientBin/
*.publishsettings
orleans.codegen.cs
+# Node-based site build
+node_modules/
+dist/
+
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..2aaa798
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,126 @@
+{
+ "name": "tps-site",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "tps-site",
+ "version": "1.0.0",
+ "dependencies": {
+ "highlight.js": "^11.11.1",
+ "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.1.2",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
+ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
+ "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/highlight.js": {
+ "version": "11.11.1",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
+ "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
+ "node_modules/markdown-it": {
+ "version": "14.1.1",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz",
+ "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.0",
+ "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.0",
+ "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-9.2.0.tgz",
+ "integrity": "sha512-sa2ErMQ6kKOA4l31gLGYliFQrMKkqSO0ZJgGhDHKijPf0pNFM9vghjAh3gn26pS4JDRs7Iwa9S36gxm3vgZTzg==",
+ "license": "Unlicense",
+ "peerDependencies": {
+ "@types/markdown-it": "*",
+ "markdown-it": "*"
+ }
+ },
+ "node_modules/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "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..865c6a8
--- /dev/null
+++ b/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "tps-site",
+ "version": "1.0.0",
+ "private": true,
+ "description": "Build pipeline for the TPS documentation site.",
+ "type": "module",
+ "scripts": {
+ "build": "node scripts/build-site.mjs"
+ },
+ "dependencies": {
+ "highlight.js": "^11.11.1",
+ "markdown-it": "^14.1.0",
+ "markdown-it-anchor": "^9.2.0"
+ }
+}
diff --git a/public/CNAME b/public/CNAME
new file mode 100644
index 0000000..815082c
--- /dev/null
+++ b/public/CNAME
@@ -0,0 +1 @@
+tps.managed-code.com
diff --git a/public/favicon.svg b/public/favicon.svg
new file mode 100644
index 0000000..077c9ae
--- /dev/null
+++ b/public/favicon.svg
@@ -0,0 +1,11 @@
+
diff --git a/scripts/build-site.mjs b/scripts/build-site.mjs
new file mode 100644
index 0000000..4c940ef
--- /dev/null
+++ b/scripts/build-site.mjs
@@ -0,0 +1,218 @@
+import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+
+import hljs from "highlight.js";
+import MarkdownIt from "markdown-it";
+import markdownItAnchor from "markdown-it-anchor";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const rootDir = path.resolve(__dirname, "..");
+const readmePath = path.join(rootDir, "README.md");
+const stylesPath = path.join(rootDir, "website", "site.css");
+const publicDir = path.join(rootDir, "public");
+const distDir = path.join(rootDir, "dist");
+
+const readme = await readFile(readmePath, "utf8");
+const styles = await readFile(stylesPath, "utf8");
+
+const md = new MarkdownIt({
+ html: false,
+ linkify: true,
+ typographer: true,
+ highlight(code, language) {
+ if (language && hljs.getLanguage(language)) {
+ return `
${hljs.highlight(code, { language }).value}
`;
+ }
+
+ return `${md.utils.escapeHtml(code)}
`;
+ }
+}).use(markdownItAnchor, {
+ slugify: slugifyHeading,
+ permalink: markdownItAnchor.permalink.linkInsideHeader({
+ symbol: "#",
+ placement: "after",
+ ariaHidden: true
+ })
+});
+
+const tokens = md.parse(readme, {});
+const title = extractTitle(tokens) ?? "TPS Format Specification";
+const summary = extractSummary(tokens) ?? "Markdown-based teleprompter scripts with timing, pacing, emotion, and styling metadata.";
+const sections = extractSections(tokens);
+const stats = buildStats(readme, sections);
+const articleHtml = md.render(readme);
+const builtAt = new Intl.DateTimeFormat("en", {
+ dateStyle: "long",
+ timeStyle: "short",
+ timeZone: "UTC"
+}).format(new Date());
+
+await rm(distDir, { recursive: true, force: true });
+await mkdir(distDir, { recursive: true });
+await cp(publicDir, distDir, { recursive: true });
+
+const page = `
+
+
+
+
+ ${escapeHtml(title)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Source of truth: README.md
+ Last site build: ${escapeHtml(builtAt)} UTC
+
+
+ ${articleHtml}
+
+
+
+
+
+`;
+
+await writeFile(path.join(distDir, "index.html"), page, "utf8");
+
+function slugifyHeading(value) {
+ return value
+ .trim()
+ .toLowerCase()
+ .replace(/[`~!@#$%^&*()+={}\[\]|\\:;"'<>,.?/]/g, "")
+ .replace(/\s+/g, "-");
+}
+
+function extractTitle(tokenList) {
+ for (let index = 0; index < tokenList.length; index += 1) {
+ if (tokenList[index].type === "heading_open" && tokenList[index].tag === "h1") {
+ return tokenList[index + 1]?.content ?? null;
+ }
+ }
+
+ return null;
+}
+
+function extractSummary(tokenList) {
+ for (let index = 0; index < tokenList.length; index += 1) {
+ if (tokenList[index].type !== "paragraph_open") {
+ continue;
+ }
+
+ const content = tokenList[index + 1]?.content?.trim();
+ if (!content) {
+ continue;
+ }
+
+ return content;
+ }
+
+ return null;
+}
+
+function extractSections(tokenList) {
+ const sectionList = [];
+
+ for (let index = 0; index < tokenList.length; index += 1) {
+ const token = tokenList[index];
+ if (token.type !== "heading_open") {
+ continue;
+ }
+
+ if (token.tag !== "h2" && token.tag !== "h3") {
+ continue;
+ }
+
+ const titleToken = tokenList[index + 1];
+ const content = titleToken?.content?.trim();
+ if (!content) {
+ continue;
+ }
+
+ sectionList.push({
+ depth: Number.parseInt(token.tag.replace("h", ""), 10),
+ title: content,
+ slug: slugifyHeading(content)
+ });
+ }
+
+ return sectionList;
+}
+
+function buildStats(markdown, sectionList) {
+ const textOnly = markdown
+ .replace(/```[\s\S]*?```/g, " ")
+ .replace(/`[^`]+`/g, " ")
+ .replace(/\[[^\]]+\]\([^)]+\)/g, " ")
+ .replace(/[#>*_\-\n\r|]/g, " ");
+
+ const words = textOnly.match(/\b[\p{L}\p{N}'-]+\b/gu) ?? [];
+ const segments = sectionList.filter((section) => section.depth === 2).length;
+ const subSections = sectionList.filter((section) => section.depth === 3).length;
+
+ return [
+ { label: "Sections", value: String(segments) },
+ { label: "Subsections", value: String(subSections) },
+ { label: "Words", value: new Intl.NumberFormat("en").format(words.length) }
+ ];
+}
+
+function renderSections(sectionList) {
+ return sectionList
+ .map((section) => {
+ const className = section.depth === 3 ? "toc-item toc-subitem" : "toc-item";
+ return `${escapeHtml(section.title)}`;
+ })
+ .join("");
+}
+
+function escapeHtml(value) {
+ return value
+ .replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+ .replaceAll("'", "'");
+}
diff --git a/website/site.css b/website/site.css
new file mode 100644
index 0000000..6723a31
--- /dev/null
+++ b/website/site.css
@@ -0,0 +1,488 @@
+@import url("https://fonts.googleapis.com/css2?family=Source+Serif+4:wght@400;600;700&family=Space+Grotesk:wght@500;700&display=swap");
+
+:root {
+ color-scheme: dark;
+ --bg: #09111f;
+ --bg-elevated: rgba(10, 19, 34, 0.88);
+ --panel: rgba(16, 28, 48, 0.82);
+ --panel-strong: rgba(10, 18, 32, 0.96);
+ --border: rgba(148, 163, 184, 0.16);
+ --text: #edf4ff;
+ --muted: #9fb3cc;
+ --accent: #7dd3fc;
+ --accent-strong: #22d3ee;
+ --accent-soft: rgba(125, 211, 252, 0.14);
+ --warm: #f6c26b;
+ --code-bg: rgba(3, 7, 18, 0.88);
+ --shadow: 0 24px 80px rgba(2, 6, 23, 0.4);
+}
+
+* {
+ box-sizing: border-box;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
+body {
+ margin: 0;
+ min-height: 100vh;
+ font-family: "Source Serif 4", "Iowan Old Style", "Palatino Linotype", serif;
+ background:
+ radial-gradient(circle at top left, rgba(34, 211, 238, 0.18), transparent 24rem),
+ radial-gradient(circle at top right, rgba(246, 194, 107, 0.2), transparent 22rem),
+ linear-gradient(180deg, #0b1324 0%, #08111d 46%, #060c16 100%);
+ color: var(--text);
+}
+
+body::before {
+ content: "";
+ position: fixed;
+ inset: 0;
+ pointer-events: none;
+ background-image:
+ linear-gradient(rgba(255, 255, 255, 0.02) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
+ background-size: 32px 32px;
+ mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5), transparent 92%);
+}
+
+a {
+ color: var(--accent);
+ text-decoration: none;
+}
+
+a:hover {
+ color: #c4f0ff;
+}
+
+code,
+pre,
+.button,
+.eyebrow,
+.panel-label,
+.content-meta,
+.toc-list a {
+ font-family: "Space Grotesk", "Avenir Next", "Segoe UI", sans-serif;
+}
+
+code {
+ padding: 0.15rem 0.45rem;
+ border-radius: 999px;
+ background: rgba(125, 211, 252, 0.1);
+ color: #dff8ff;
+ font-size: 0.9em;
+}
+
+pre code {
+ display: block;
+ padding: 0;
+ background: transparent;
+ border-radius: 0;
+ color: inherit;
+ overflow-x: auto;
+}
+
+.page-shell {
+ width: min(1360px, calc(100vw - 2rem));
+ margin: 0 auto;
+ padding: 2rem 0 4rem;
+}
+
+.hero {
+ display: grid;
+ grid-template-columns: minmax(0, 1.5fr) minmax(320px, 0.9fr);
+ gap: 1.5rem;
+ align-items: stretch;
+}
+
+.hero-copy,
+.hero-panel,
+.toc-card,
+.content-card {
+ backdrop-filter: blur(18px);
+ background: var(--bg-elevated);
+ border: 1px solid var(--border);
+ border-radius: 28px;
+ box-shadow: var(--shadow);
+}
+
+.hero-copy {
+ padding: 3rem;
+}
+
+.hero-panel {
+ padding: 2rem;
+ background: linear-gradient(180deg, rgba(13, 23, 39, 0.9), rgba(9, 17, 31, 0.92));
+}
+
+.eyebrow {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.45rem;
+ padding: 0.45rem 0.85rem;
+ border-radius: 999px;
+ background: var(--accent-soft);
+ color: var(--accent);
+ font-size: 0.78rem;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+}
+
+.hero h1 {
+ margin: 1rem 0 0.75rem;
+ font-family: "Space Grotesk", "Avenir Next", "Segoe UI", sans-serif;
+ font-size: clamp(2.6rem, 5vw, 4.8rem);
+ line-height: 0.95;
+ letter-spacing: -0.05em;
+}
+
+.hero-summary {
+ max-width: 34rem;
+ margin: 0;
+ color: var(--muted);
+ font-size: 1.2rem;
+ line-height: 1.7;
+}
+
+.hero-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.9rem;
+ margin-top: 2rem;
+}
+
+.button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 44px;
+ padding: 0.9rem 1.25rem;
+ border-radius: 999px;
+ font-size: 0.95rem;
+ font-weight: 700;
+ letter-spacing: 0.01em;
+ transition:
+ transform 150ms ease,
+ border-color 150ms ease,
+ background-color 150ms ease;
+}
+
+.button:hover {
+ transform: translateY(-1px);
+}
+
+.button-primary {
+ background: linear-gradient(135deg, var(--accent), var(--accent-strong));
+ color: #062033;
+}
+
+.button-secondary {
+ border: 1px solid rgba(125, 211, 252, 0.24);
+ background: rgba(8, 17, 29, 0.68);
+ color: var(--text);
+}
+
+.panel-label {
+ margin: 0 0 1rem;
+ color: var(--warm);
+ font-size: 0.78rem;
+ font-weight: 700;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+}
+
+.stats-grid {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 0.9rem;
+ margin: 0;
+}
+
+.stats-grid div {
+ padding: 1rem;
+ border-radius: 20px;
+ background: rgba(125, 211, 252, 0.08);
+ border: 1px solid rgba(125, 211, 252, 0.12);
+}
+
+.stats-grid dt {
+ margin: 0;
+ color: var(--muted);
+ font-size: 0.8rem;
+ text-transform: uppercase;
+ letter-spacing: 0.08em;
+}
+
+.stats-grid dd {
+ margin: 0.55rem 0 0;
+ font-family: "Space Grotesk", "Avenir Next", "Segoe UI", sans-serif;
+ font-size: 1.8rem;
+ font-weight: 700;
+}
+
+.panel-note {
+ margin: 1.2rem 0 0;
+ color: var(--muted);
+ line-height: 1.7;
+}
+
+.layout {
+ display: grid;
+ grid-template-columns: minmax(250px, 290px) minmax(0, 1fr);
+ gap: 1.5rem;
+ margin-top: 1.5rem;
+ align-items: start;
+}
+
+.toc-card {
+ position: sticky;
+ top: 1rem;
+ padding: 1.25rem;
+ background: var(--panel);
+}
+
+.toc-header,
+.content-meta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.8rem;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.toc-header {
+ margin-bottom: 1rem;
+}
+
+.toc-list {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.toc-item + .toc-item {
+ margin-top: 0.5rem;
+}
+
+.toc-subitem {
+ padding-left: 1rem;
+}
+
+.toc-list a {
+ display: block;
+ padding: 0.55rem 0.7rem;
+ border-radius: 14px;
+ color: var(--muted);
+ font-size: 0.95rem;
+ line-height: 1.35;
+}
+
+.toc-list a:hover {
+ background: rgba(125, 211, 252, 0.08);
+ color: var(--text);
+}
+
+.content-card {
+ padding: 1.5rem;
+ background: linear-gradient(180deg, rgba(11, 20, 36, 0.88), rgba(8, 15, 26, 0.96));
+}
+
+.content-meta {
+ margin-bottom: 1.5rem;
+ padding-bottom: 1rem;
+ border-bottom: 1px solid var(--border);
+ color: var(--muted);
+ font-size: 0.85rem;
+ letter-spacing: 0.04em;
+ text-transform: uppercase;
+}
+
+.markdown-body {
+ color: var(--text);
+ font-size: 1.1rem;
+ line-height: 1.82;
+}
+
+.markdown-body > *:first-child {
+ margin-top: 0;
+}
+
+.markdown-body h1,
+.markdown-body h2,
+.markdown-body h3,
+.markdown-body h4 {
+ position: relative;
+ margin: 2.4rem 0 0.85rem;
+ font-family: "Space Grotesk", "Avenir Next", "Segoe UI", sans-serif;
+ line-height: 1.08;
+ letter-spacing: -0.04em;
+}
+
+.markdown-body h1 {
+ font-size: 2.4rem;
+}
+
+.markdown-body h2 {
+ font-size: 1.9rem;
+ color: #f3f8ff;
+}
+
+.markdown-body h3 {
+ font-size: 1.4rem;
+ color: #d5e9ff;
+}
+
+.markdown-body h4 {
+ font-size: 1.15rem;
+}
+
+.markdown-body p,
+.markdown-body ul,
+.markdown-body ol,
+.markdown-body table,
+.markdown-body blockquote,
+.markdown-body pre {
+ margin: 1rem 0;
+}
+
+.markdown-body ul,
+.markdown-body ol {
+ padding-left: 1.25rem;
+}
+
+.markdown-body li + li {
+ margin-top: 0.35rem;
+}
+
+.markdown-body strong {
+ color: #ffffff;
+}
+
+.markdown-body hr {
+ border: 0;
+ height: 1px;
+ margin: 2rem 0;
+ background: linear-gradient(90deg, transparent, rgba(148, 163, 184, 0.5), transparent);
+}
+
+.markdown-body blockquote {
+ padding: 1rem 1.2rem;
+ border-left: 4px solid var(--warm);
+ border-radius: 18px;
+ background: rgba(246, 194, 107, 0.08);
+ color: #fff3dd;
+}
+
+.markdown-body table {
+ width: 100%;
+ border-collapse: collapse;
+ overflow: hidden;
+ border-radius: 22px;
+ border: 1px solid rgba(148, 163, 184, 0.16);
+}
+
+.markdown-body th,
+.markdown-body td {
+ padding: 0.9rem 1rem;
+ text-align: left;
+ vertical-align: top;
+ border-bottom: 1px solid rgba(148, 163, 184, 0.12);
+}
+
+.markdown-body th {
+ background: rgba(125, 211, 252, 0.08);
+ font-family: "Space Grotesk", "Avenir Next", "Segoe UI", sans-serif;
+ font-size: 0.86rem;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+}
+
+.markdown-body tr:last-child td {
+ border-bottom: 0;
+}
+
+.markdown-body pre {
+ padding: 1.2rem 1.3rem;
+ overflow-x: auto;
+ border-radius: 22px;
+ background: var(--code-bg);
+ border: 1px solid rgba(125, 211, 252, 0.1);
+}
+
+.markdown-body .hljs {
+ color: #d9f1ff;
+}
+
+.markdown-body img {
+ max-width: 100%;
+ border-radius: 22px;
+}
+
+.markdown-body .header-anchor {
+ margin-left: 0.4rem;
+ color: rgba(125, 211, 252, 0.65);
+ opacity: 0;
+ transition: opacity 150ms ease;
+}
+
+.markdown-body h1:hover .header-anchor,
+.markdown-body h2:hover .header-anchor,
+.markdown-body h3:hover .header-anchor,
+.markdown-body h4:hover .header-anchor {
+ opacity: 1;
+}
+
+@media (max-width: 1040px) {
+ .hero,
+ .layout {
+ grid-template-columns: 1fr;
+ }
+
+ .toc-card {
+ position: static;
+ }
+
+ .stats-grid {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ }
+}
+
+@media (max-width: 760px) {
+ .page-shell {
+ width: min(100vw - 1rem, 100%);
+ padding-top: 0.5rem;
+ }
+
+ .hero-copy,
+ .hero-panel,
+ .toc-card,
+ .content-card {
+ border-radius: 24px;
+ }
+
+ .hero-copy,
+ .hero-panel,
+ .content-card {
+ padding: 1.25rem;
+ }
+
+ .hero h1 {
+ font-size: clamp(2.2rem, 12vw, 3.3rem);
+ }
+
+ .hero-summary,
+ .markdown-body {
+ font-size: 1rem;
+ }
+
+ .stats-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .content-meta,
+ .toc-header {
+ align-items: flex-start;
+ }
+}