audit-labs/audit-labs.dev

The website for Audit Labs.

clone: git clone https://gitbay.org/audit-labs/audit-labs.dev.git

7b2e93335b2a709631eea32993ea65248cec5a33

verified · cmc

author: Christian Cleberg <hello@cleberg.net> · 2026-08-06T23:56:42Z

refactor: extract shared CSS to assets/site.css; add gh-attest page

Moves the duplicated design system into a single assets/site.css that every
page links. The home hero keeps its single-column layout; project pages opt
into a two-column variant via .hero.split, so one stylesheet serves both without
changing the home page's appearance.

Adds a dedicated gh-attest page (/gh-attest/) built on the shared system —
adapted for a hosted GitHub App: a signal-to-control evidence terminal, a
capture/map/export overview, the collected signals and their controls, and a
read-only-by-design guarantee. Points the home card, footers, and cross-links at
the new page.
 assets/site.css          | 194 ++++++++++++++++++
 audit-report/index.html  | 117 +----------
 evidence-seal/index.html | 110 +----------
 gh-attest/index.html     | 161 +++++++++++++++
 index.html               | 505 +----------------------------------------------
 5 files changed, 364 insertions(+), 723 deletions(-)

diff --git a/assets/site.css b/assets/site.css
new file mode 100644
index 0000000..a932e34
--- /dev/null
+++ b/assets/site.css
@@ -0,0 +1,194 @@
+/* ===================================================================
+   audit-labs.dev — shared styles
+   Design system: DM Serif Display (display) · DM Sans (body) ·
+   IBM Plex Mono (labels/code). Warm palette, amber accent.
+
+   The home page uses a single-column hero (`.hero`); project pages
+   opt into a two-column hero with `.hero.split`.
+   =================================================================== */
+
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+
+:root {
+    --black: #0a0a0a;
+    --off-white: #f4f1eb;
+    --warm-white: #faf8f4;
+    --amber: #d97706;
+    --amber-light: #fbbf24;
+    --green: #15803d;
+    --gray-1: #1c1c1c;
+    --gray-2: #2e2e2e;
+    --gray-3: #6b6b6b;
+    --gray-4: #a3a3a3;
+    --gray-5: #d4d4d4;
+    --border: #e5e1d8;
+    --red: #c0392b;
+}
+
+body {
+    font-family: 'DM Sans', sans-serif;
+    background: var(--warm-white);
+    color: var(--black);
+    line-height: 1.6;
+}
+
+.mono { font-family: 'IBM Plex Mono', monospace; }
+.serif { font-family: 'DM Serif Display', serif; }
+
+/* ---------- NAV ---------- */
+nav { position: sticky; top: 0; z-index: 100; background: var(--warm-white); border-bottom: 1px solid var(--border); padding: 0 2rem; }
+.nav-inner { max-width: 1100px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; height: 60px; }
+.logo { font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 1.1rem; letter-spacing: -0.02em; color: var(--black); text-decoration: none; }
+.logo span { color: var(--amber); }
+.nav-links { display: flex; gap: 2rem; align-items: center; list-style: none; }
+.nav-links a { font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; color: var(--gray-3); text-decoration: none; transition: color 0.15s; }
+.nav-links a:hover { color: var(--black); }
+.nav-links .btn-github { background: var(--black); color: var(--off-white); padding: 0.45rem 1rem; border-radius: 4px; font-size: 0.75rem; transition: background 0.15s; }
+.nav-links .btn-github:hover { background: var(--gray-2); color: var(--off-white); }
+
+/* ---------- HERO (base = home; .split = project pages) ---------- */
+.hero { background: var(--black); color: var(--off-white); padding: 7rem 2rem 5rem; position: relative; overflow: hidden; }
+.hero::before {
+    content: ''; position: absolute; inset: 0; pointer-events: none;
+    background-image:
+        repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(255,255,255,0.03) 39px, rgba(255,255,255,0.03) 40px),
+        repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(255,255,255,0.03) 39px, rgba(255,255,255,0.03) 40px);
+}
+.hero-inner { max-width: 1100px; margin: 0 auto; position: relative; }
+
+.hero.split { padding: 5.5rem 2rem 4.5rem; }
+.hero.split .hero-inner { display: grid; grid-template-columns: 1fr 1fr; gap: 3.5rem; align-items: center; }
+@media (max-width: 820px) { .hero.split .hero-inner { grid-template-columns: 1fr; gap: 2.5rem; } }
+
+.hero-label { font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--amber-light); margin-bottom: 1.5rem; display: flex; align-items: center; gap: 0.5rem; }
+.hero-label::before { content: ''; display: inline-block; width: 1.5rem; height: 1px; background: var(--amber-light); }
+
+.crumb { font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--amber-light); margin-bottom: 1.4rem; display: flex; align-items: center; gap: 0.5rem; }
+.crumb::before { content: ''; width: 1.5rem; height: 1px; background: var(--amber-light); }
+.crumb a { color: var(--amber-light); text-decoration: none; opacity: 0.8; }
+
+h1 { font-family: 'DM Serif Display', serif; font-size: clamp(2.8rem, 6vw, 5rem); font-weight: 400; line-height: 1.1; letter-spacing: -0.02em; margin-bottom: 1.5rem; max-width: 700px; }
+h1 em { font-style: italic; color: var(--amber-light); }
+.hero.split h1 { font-size: clamp(2.4rem, 5vw, 3.9rem); line-height: 1.08; margin-bottom: 1.3rem; max-width: none; }
+
+.hero-desc { font-size: 1.05rem; color: #a09a8e; max-width: 540px; margin-bottom: 2.5rem; line-height: 1.75; }
+.hero.split .hero-desc { font-size: 1.02rem; max-width: 34rem; margin-bottom: 2rem; }
+
+.hero-actions { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 4rem; }
+.hero.split .hero-actions { margin-bottom: 0; }
+
+.btn-primary { background: var(--amber); color: #fff; text-decoration: none; padding: 0.75rem 1.5rem; border-radius: 4px; font-family: 'IBM Plex Mono', monospace; font-size: 0.8rem; font-weight: 500; transition: background 0.15s; }
+.btn-primary:hover { background: var(--amber-light); color: #000; }
+.btn-secondary { background: transparent; color: var(--gray-4); text-decoration: none; padding: 0.75rem 1.5rem; border-radius: 4px; font-family: 'IBM Plex Mono', monospace; font-size: 0.8rem; border: 1px solid var(--gray-2); transition: border-color 0.15s, color 0.15s; }
+.btn-secondary:hover { border-color: var(--gray-4); color: var(--off-white); }
+
+/* ---------- TERMINAL ---------- */
+.terminal { background: #111; border: 1px solid #2a2a2a; border-radius: 8px; overflow: hidden; max-width: 600px; }
+.hero.split .terminal { max-width: none; }
+.terminal-bar { background: #1a1a1a; border-bottom: 1px solid #2a2a2a; padding: 0.6rem 1rem; display: flex; gap: 0.4rem; align-items: center; }
+.dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
+.dot-red { background: #ff5f57; } .dot-yellow { background: #febc2e; } .dot-green { background: #28c840; }
+.terminal-body { padding: 1.25rem 1.5rem; font-family: 'IBM Plex Mono', monospace; font-size: 0.82rem; line-height: 1.9; }
+.hero.split .terminal-body { padding: 1.2rem 1.4rem; font-size: 0.78rem; line-height: 1.95; }
+.t-prompt { color: #5a9060; } .t-cmd { color: #e8e0d0; } .t-comment { color: #555; }
+.t-out { color: #7a9f7a; } .t-path { color: #d4a862; } .t-dim { color: #444; }
+.t-bad { color: #e06c5e; } .t-hash { color: #8a8a8a; }
+
+/* ---------- SECTIONS ---------- */
+section { padding: 5rem 2rem; border-bottom: 1px solid var(--border); }
+.section-inner { max-width: 1100px; margin: 0 auto; }
+.eyebrow { font-family: 'IBM Plex Mono', monospace; font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--amber); margin-bottom: 0.9rem; }
+h2 { font-family: 'DM Serif Display', serif; font-size: clamp(1.8rem, 3vw, 2.4rem); font-weight: 400; line-height: 1.2; }
+.eyebrow + h2 { margin-bottom: 0.6rem; }
+.lede { color: var(--gray-3); font-size: 1rem; max-width: 44rem; line-height: 1.7; }
+
+.section-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 3rem; flex-wrap: wrap; gap: 1rem; }
+.section-link { font-family: 'IBM Plex Mono', monospace; font-size: 0.75rem; color: var(--gray-3); text-decoration: none; border-bottom: 1px solid var(--gray-5); padding-bottom: 1px; transition: color 0.15s; }
+.section-link:hover { color: var(--black); }
+
+/* ---------- HOME: repos grid ---------- */
+.repos { background: var(--warm-white); }
+.repo-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.5rem; }
+.repo-card { background: #fff; border: 1px solid var(--border); border-radius: 8px; padding: 2rem; text-decoration: none; color: inherit; display: block; transition: border-color 0.15s, box-shadow 0.15s; position: relative; }
+.repo-card:hover { border-color: var(--amber); box-shadow: 0 4px 20px rgba(0,0,0,0.06); }
+.repo-tag { font-family: 'IBM Plex Mono', monospace; font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--amber); background: #fef3c7; padding: 0.2rem 0.5rem; border-radius: 3px; display: inline-block; margin-bottom: 1rem; }
+.repo-card h3 { font-family: 'IBM Plex Mono', monospace; font-size: 0.95rem; font-weight: 700; margin-bottom: 0.6rem; color: var(--black); }
+.repo-card p { font-size: 0.9rem; color: var(--gray-3); line-height: 1.65; margin-bottom: 1.5rem; }
+.repo-langs { display: flex; gap: 0.5rem; flex-wrap: wrap; }
+.lang-badge { font-family: 'IBM Plex Mono', monospace; font-size: 0.65rem; background: var(--off-white); border: 1px solid var(--border); color: var(--gray-3); padding: 0.15rem 0.5rem; border-radius: 3px; }
+
+/* ---------- HOME: tools grid ---------- */
+.tools { background: #fff; }
+.tools-intro { max-width: 550px; margin-bottom: 3rem; }
+.tools-intro p { color: var(--gray-3); font-size: 0.95rem; margin-top: 0.75rem; line-height: 1.7; }
+.tool-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
+.tool-item { background: #fff; padding: 1.75rem; transition: background 0.15s; }
+.tool-item:hover { background: var(--warm-white); }
+.tool-icon { font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; color: var(--amber); margin-bottom: 0.75rem; letter-spacing: 0.05em; }
+.tool-item h4 { font-family: 'IBM Plex Mono', monospace; font-size: 0.85rem; font-weight: 700; margin-bottom: 0.5rem; color: var(--black); }
+.tool-item p { font-size: 0.82rem; color: var(--gray-3); line-height: 1.6; }
+
+/* ---------- FRAMEWORKS strip (home + project pages) ---------- */
+.frameworks { padding: 3.5rem 2rem; background: var(--warm-white); }
+.frameworks-inner { max-width: 1100px; margin: 0 auto; display: flex; align-items: center; gap: 3rem; flex-wrap: wrap; }
+.frameworks-label { font-family: 'IBM Plex Mono', monospace; font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gray-4); white-space: nowrap; }
+.frameworks-list { display: flex; gap: 2.5rem; flex-wrap: wrap; align-items: center; }
+.framework-tag { font-family: 'IBM Plex Mono', monospace; font-size: 0.8rem; font-weight: 700; color: var(--gray-3); letter-spacing: 0.05em; }
+
+/* ---------- PROJECT PAGES: overview cards ---------- */
+.guarantees { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; margin-top: 2.6rem; }
+.card { background: #fff; border: 1px solid var(--border); border-radius: 8px; padding: 1.8rem; transition: border-color 0.15s, box-shadow 0.15s; }
+.card:hover { border-color: var(--amber); box-shadow: 0 4px 20px rgba(0,0,0,0.06); }
+.card .num { font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; color: var(--amber); letter-spacing: 0.1em; }
+.card h3 { font-family: 'DM Serif Display', serif; font-weight: 400; font-size: 1.3rem; margin: 0.5rem 0 0.6rem; }
+.card p { font-size: 0.9rem; color: var(--gray-3); line-height: 1.65; }
+.card p .mono { color: var(--gray-1); }
+
+/* ---------- PROJECT PAGES: contents / commands list ---------- */
+.cmds { background: #fff; }
+.cmd-list { margin-top: 2.4rem; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
+.cmd-row { display: grid; grid-template-columns: 11rem 1fr; gap: 1.5rem; padding: 1.15rem 1.5rem; border-bottom: 1px solid var(--border); align-items: baseline; }
+.cmd-row:last-child { border-bottom: none; }
+.cmd-row:hover { background: var(--warm-white); }
+.cmd-name { font-family: 'IBM Plex Mono', monospace; font-size: 0.85rem; font-weight: 700; color: var(--black); }
+.cmd-desc { font-size: 0.9rem; color: var(--gray-3); line-height: 1.6; }
+.cmd-desc .mono { color: var(--amber); }
+@media (max-width: 560px) { .cmd-row { grid-template-columns: 1fr; gap: 0.3rem; } }
+
+/* ---------- PROJECT PAGES: install / quickstart ---------- */
+.install { background: var(--warm-white); }
+.install-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2.5rem; margin-top: 2.4rem; align-items: start; }
+@media (max-width: 820px) { .install-grid { grid-template-columns: 1fr; } }
+.install pre { background: #111; color: #e8e0d0; border-radius: 8px; padding: 1.25rem 1.4rem; font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; line-height: 1.9; overflow-x: auto; }
+.install pre .c { color: #555; } .install pre .p { color: #5a9060; }
+.badges { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.2rem; }
+.badge { font-family: 'IBM Plex Mono', monospace; font-size: 0.65rem; background: #fff; border: 1px solid var(--border); color: var(--gray-3); padding: 0.2rem 0.55rem; border-radius: 3px; }
+.exit { margin-top: 1.4rem; display: flex; flex-direction: column; gap: 0.55rem; }
+.exit .e { font-size: 0.85rem; color: var(--gray-3); display: flex; gap: 0.7rem; align-items: baseline; }
+.exit .code { font-family: 'IBM Plex Mono', monospace; font-weight: 700; min-width: 1.2rem; }
+.exit .g { color: var(--green); } .exit .r { color: var(--red); } .exit .a { color: var(--amber); }
+
+/* ---------- FOOTER ---------- */
+footer { background: var(--black); color: var(--gray-4); padding: 3rem 2rem; }
+.footer-inner { max-width: 1100px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1.5rem; }
+.footer-logo { font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 0.9rem; color: var(--gray-4); text-decoration: none; }
+.footer-logo span { color: var(--amber); }
+.footer-left p { font-size: 0.78rem; color: var(--gray-2); margin-top: 0.4rem; }
+.footer-links { display: flex; gap: 1.5rem; align-items: center; flex-wrap: wrap; }
+.footer-links a { font-family: 'IBM Plex Mono', monospace; font-size: 0.75rem; color: var(--gray-3); text-decoration: none; transition: color 0.15s; }
+.footer-links a:hover { color: var(--off-white); }
+
+/* ---------- ANIMATION ---------- */
+@keyframes fadeUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
+.hero-label, .crumb { animation: fadeUp 0.5s ease both; }
+h1 { animation: fadeUp 0.5s ease 0.1s both; }
+.hero-desc { animation: fadeUp 0.5s ease 0.2s both; }
+.hero-actions { animation: fadeUp 0.5s ease 0.3s both; }
+.terminal { animation: fadeUp 0.5s ease 0.4s both; }
+@media (prefers-reduced-motion: reduce) { * { animation: none !important; } }
+
+/* ---------- RESPONSIVE ---------- */
+@media (max-width: 640px) {
+    .nav-links a:not(.btn-github):not(:last-child) { display: none; }
+    h1 { font-size: 2.4rem; }
+}
diff --git a/audit-report/index.html b/audit-report/index.html
index c509ac7..6d5c2b8 100644
--- a/audit-report/index.html
+++ b/audit-report/index.html
@@ -7,118 +7,7 @@
     <meta name="description" content="Turn audit-tools evidence packages into control-mapped, auditor-ready reports (Markdown, HTML, JSON) with SOC 2, ISO 27001 and NIST mappings, plus diff and trend modes.">
     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet">
-    <style>
-        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
-        :root {
-            --black:#0a0a0a; --off-white:#f4f1eb; --warm-white:#faf8f4;
-            --amber:#d97706; --amber-light:#fbbf24; --green:#15803d;
-            --gray-1:#1c1c1c; --gray-2:#2e2e2e; --gray-3:#6b6b6b; --gray-4:#a3a3a3; --gray-5:#d4d4d4;
-            --border:#e5e1d8; --red:#c0392b;
-        }
-        body { font-family:'DM Sans',sans-serif; background:var(--warm-white); color:var(--black); line-height:1.6; }
-        .mono { font-family:'IBM Plex Mono',monospace; }
-
-        /* NAV */
-        nav { position:sticky; top:0; z-index:100; background:var(--warm-white); border-bottom:1px solid var(--border); padding:0 2rem; }
-        .nav-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; height:60px; }
-        .logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:1.1rem; letter-spacing:-.02em; color:var(--black); text-decoration:none; }
-        .logo span { color:var(--amber); }
-        .nav-links { display:flex; gap:2rem; align-items:center; list-style:none; }
-        .nav-links a { font-family:'IBM Plex Mono',monospace; font-size:.78rem; color:var(--gray-3); text-decoration:none; transition:color .15s; }
-        .nav-links a:hover { color:var(--black); }
-        .nav-links .btn-github { background:var(--black); color:var(--off-white); padding:.45rem 1rem; border-radius:4px; font-size:.75rem; }
-        .nav-links .btn-github:hover { background:var(--gray-2); }
-
-        /* HERO */
-        .hero { background:var(--black); color:var(--off-white); padding:5.5rem 2rem 4.5rem; position:relative; overflow:hidden; }
-        .hero::before { content:''; position:absolute; inset:0; pointer-events:none;
-            background-image:
-                repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px),
-                repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px); }
-        .hero-inner { max-width:1100px; margin:0 auto; position:relative; display:grid; grid-template-columns:1fr 1fr; gap:3.5rem; align-items:center; }
-        @media (max-width:820px){ .hero-inner{ grid-template-columns:1fr; gap:2.5rem; } }
-        .crumb { font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.15em; text-transform:uppercase; color:var(--amber-light); margin-bottom:1.4rem; display:flex; align-items:center; gap:.5rem; }
-        .crumb::before { content:''; width:1.5rem; height:1px; background:var(--amber-light); }
-        .crumb a { color:var(--amber-light); text-decoration:none; opacity:.8; }
-        h1 { font-family:'DM Serif Display',serif; font-size:clamp(2.4rem,5vw,3.9rem); font-weight:400; line-height:1.08; letter-spacing:-.02em; margin-bottom:1.3rem; }
-        h1 em { font-style:italic; color:var(--amber-light); }
-        .hero-desc { font-size:1.02rem; color:#a09a8e; margin-bottom:2rem; line-height:1.75; max-width:34rem; }
-        .hero-actions { display:flex; gap:1rem; flex-wrap:wrap; }
-        .btn-primary { background:var(--amber); color:#fff; text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; font-weight:500; transition:background .15s; }
-        .btn-primary:hover { background:var(--amber-light); color:#000; }
-        .btn-secondary { background:transparent; color:var(--gray-4); text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; border:1px solid var(--gray-2); transition:border-color .15s,color .15s; }
-        .btn-secondary:hover { border-color:var(--gray-4); color:var(--off-white); }
-
-        /* TERMINAL */
-        .terminal { background:#111; border:1px solid #2a2a2a; border-radius:8px; overflow:hidden; }
-        .terminal-bar { background:#1a1a1a; border-bottom:1px solid #2a2a2a; padding:.6rem 1rem; display:flex; gap:.4rem; align-items:center; }
-        .dot { width:10px; height:10px; border-radius:50%; }
-        .dot-red{background:#ff5f57;} .dot-yellow{background:#febc2e;} .dot-green{background:#28c840;}
-        .terminal-body { padding:1.2rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.95; }
-        .t-prompt{color:#5a9060;} .t-cmd{color:#e8e0d0;} .t-comment{color:#555;} .t-out{color:#7a9f7a;} .t-path{color:#d4a862;} .t-dim{color:#444;} .t-bad{color:#e06c5e;} .t-hash{color:#8a8a8a;}
-
-        /* SECTIONS */
-        section { padding:5rem 2rem; border-bottom:1px solid var(--border); }
-        .section-inner { max-width:1100px; margin:0 auto; }
-        .eyebrow { font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.14em; text-transform:uppercase; color:var(--amber); margin-bottom:.9rem; }
-        h2 { font-family:'DM Serif Display',serif; font-size:clamp(1.7rem,3vw,2.3rem); font-weight:400; line-height:1.2; margin-bottom:.6rem; }
-        .lede { color:var(--gray-3); font-size:1rem; max-width:44rem; line-height:1.7; }
-
-        .guarantees { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:1.5rem; margin-top:2.6rem; }
-        .card { background:#fff; border:1px solid var(--border); border-radius:8px; padding:1.8rem; transition:border-color .15s,box-shadow .15s; }
-        .card:hover { border-color:var(--amber); box-shadow:0 4px 20px rgba(0,0,0,.06); }
-        .card .num { font-family:'IBM Plex Mono',monospace; font-size:.7rem; color:var(--amber); letter-spacing:.1em; }
-        .card h3 { font-family:'DM Serif Display',serif; font-weight:400; font-size:1.3rem; margin:.5rem 0 .6rem; }
-        .card p { font-size:.9rem; color:var(--gray-3); line-height:1.65; }
-        .card p .mono { color:var(--gray-1); }
-
-        /* COMMANDS / CONTENTS */
-        .cmds { background:#fff; }
-        .cmd-list { margin-top:2.4rem; border:1px solid var(--border); border-radius:8px; overflow:hidden; }
-        .cmd-row { display:grid; grid-template-columns:11rem 1fr; gap:1.5rem; padding:1.15rem 1.5rem; border-bottom:1px solid var(--border); align-items:baseline; }
-        .cmd-row:last-child { border-bottom:none; }
-        .cmd-row:hover { background:var(--warm-white); }
-        .cmd-name { font-family:'IBM Plex Mono',monospace; font-size:.85rem; font-weight:700; color:var(--black); }
-        .cmd-desc { font-size:.9rem; color:var(--gray-3); line-height:1.6; }
-        .cmd-desc .mono { color:var(--amber); }
-        @media (max-width:560px){ .cmd-row{ grid-template-columns:1fr; gap:.3rem; } }
-
-        /* FRAMEWORKS STRIP */
-        .frameworks { padding:3.5rem 2rem; background:var(--warm-white); }
-        .frameworks-inner { max-width:1100px; margin:0 auto; display:flex; align-items:center; gap:3rem; flex-wrap:wrap; }
-        .frameworks-label { font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.12em; text-transform:uppercase; color:var(--gray-4); white-space:nowrap; }
-        .frameworks-list { display:flex; gap:2.5rem; flex-wrap:wrap; align-items:center; }
-        .framework-tag { font-family:'IBM Plex Mono',monospace; font-size:.8rem; font-weight:700; color:var(--gray-3); letter-spacing:.05em; }
-
-        /* INSTALL */
-        .install { background:var(--warm-white); }
-        .install-grid { display:grid; grid-template-columns:1fr 1fr; gap:2.5rem; margin-top:2.4rem; align-items:start; }
-        @media (max-width:820px){ .install-grid{ grid-template-columns:1fr; } }
-        .install pre { background:#111; color:#e8e0d0; border-radius:8px; padding:1.25rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.9; overflow-x:auto; }
-        .install pre .c { color:#555; } .install pre .p { color:#5a9060; }
-        .badges { display:flex; flex-wrap:wrap; gap:.5rem; margin-top:1.2rem; }
-        .badge { font-family:'IBM Plex Mono',monospace; font-size:.65rem; background:#fff; border:1px solid var(--border); color:var(--gray-3); padding:.2rem .55rem; border-radius:3px; }
-        .exit { margin-top:1.4rem; display:flex; flex-direction:column; gap:.55rem; }
-        .exit .e { font-size:.85rem; color:var(--gray-3); display:flex; gap:.7rem; align-items:baseline; }
-        .exit .code { font-family:'IBM Plex Mono',monospace; font-weight:700; min-width:1.2rem; }
-        .exit .g{color:var(--green);} .exit .r{color:var(--red);} .exit .a{color:var(--amber);}
-
-        /* FOOTER */
-        footer { background:var(--black); color:var(--gray-4); padding:3rem 2rem; }
-        .footer-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:1.5rem; }
-        .footer-logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:.9rem; color:var(--gray-4); text-decoration:none; }
-        .footer-logo span { color:var(--amber); }
-        .footer-left p { font-size:.78rem; color:var(--gray-2); margin-top:.4rem; }
-        .footer-links { display:flex; gap:1.5rem; flex-wrap:wrap; }
-        .footer-links a { font-family:'IBM Plex Mono',monospace; font-size:.75rem; color:var(--gray-3); text-decoration:none; transition:color .15s; }
-        .footer-links a:hover { color:var(--off-white); }
-
-        @keyframes fadeUp { from{opacity:0;transform:translateY(16px);} to{opacity:1;transform:translateY(0);} }
-        .crumb{animation:fadeUp .5s ease both;} h1{animation:fadeUp .5s ease .1s both;}
-        .hero-desc{animation:fadeUp .5s ease .2s both;} .hero-actions{animation:fadeUp .5s ease .3s both;} .terminal{animation:fadeUp .5s ease .4s both;}
-        @media (prefers-reduced-motion:reduce){ *{animation:none!important;} }
-        @media (max-width:640px){ .nav-links a:not(.btn-github):not(:last-child){ display:none; } }
-    </style>
+    <link rel="stylesheet" href="../assets/site.css">
 </head>
 <body>
 
@@ -133,7 +22,7 @@
     </div>
 </nav>
 
-<header class="hero">
+<header class="hero split">
     <div class="hero-inner">
         <div>
             <div class="crumb"><a href="/">Audit Labs</a> / audit-report</div>
@@ -265,7 +154,7 @@ audit-report ./output/aws_audit_prod_2026-08 \
             <a href="/">Home</a>
             <a href="https://github.com/audit-labs/audit-report">audit-report</a>
             <a href="/evidence-seal/">evidence-seal</a>
-            <a href="https://github.com/audit-labs/gh-attest">gh-attest</a>
+            <a href="/gh-attest/">gh-attest</a>
             <a href="https://github.com/audit-labs">GitHub</a>
         </div>
     </div>
diff --git a/evidence-seal/index.html b/evidence-seal/index.html
index c6833e1..52c25c5 100644
--- a/evidence-seal/index.html
+++ b/evidence-seal/index.html
@@ -7,111 +7,7 @@
     <meta name="description" content="Tamper-evident seals and chain of custody for audit evidence. SHA-256 Merkle manifests, seal chaining, optional ed25519 signing and RFC 3161 timestamping.">
     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet">
-    <style>
-        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
-        :root {
-            --black:#0a0a0a; --off-white:#f4f1eb; --warm-white:#faf8f4;
-            --amber:#d97706; --amber-light:#fbbf24; --green:#15803d;
-            --gray-1:#1c1c1c; --gray-2:#2e2e2e; --gray-3:#6b6b6b; --gray-4:#a3a3a3; --gray-5:#d4d4d4;
-            --border:#e5e1d8; --red:#c0392b;
-        }
-        body { font-family:'DM Sans',sans-serif; background:var(--warm-white); color:var(--black); line-height:1.6; }
-        .mono { font-family:'IBM Plex Mono',monospace; }
-
-        /* NAV */
-        nav { position:sticky; top:0; z-index:100; background:var(--warm-white); border-bottom:1px solid var(--border); padding:0 2rem; }
-        .nav-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; height:60px; }
-        .logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:1.1rem; letter-spacing:-.02em; color:var(--black); text-decoration:none; }
-        .logo span { color:var(--amber); }
-        .nav-links { display:flex; gap:2rem; align-items:center; list-style:none; }
-        .nav-links a { font-family:'IBM Plex Mono',monospace; font-size:.78rem; color:var(--gray-3); text-decoration:none; transition:color .15s; }
-        .nav-links a:hover { color:var(--black); }
-        .nav-links .btn-github { background:var(--black); color:var(--off-white); padding:.45rem 1rem; border-radius:4px; font-size:.75rem; }
-        .nav-links .btn-github:hover { background:var(--gray-2); }
-
-        /* HERO */
-        .hero { background:var(--black); color:var(--off-white); padding:5.5rem 2rem 4.5rem; position:relative; overflow:hidden; }
-        .hero::before { content:''; position:absolute; inset:0; pointer-events:none;
-            background-image:
-                repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px),
-                repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px); }
-        .hero-inner { max-width:1100px; margin:0 auto; position:relative; display:grid; grid-template-columns:1fr 1fr; gap:3.5rem; align-items:center; }
-        @media (max-width:820px){ .hero-inner{ grid-template-columns:1fr; gap:2.5rem; } }
-        .crumb { font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.15em; text-transform:uppercase; color:var(--amber-light); margin-bottom:1.4rem; display:flex; align-items:center; gap:.5rem; }
-        .crumb::before { content:''; width:1.5rem; height:1px; background:var(--amber-light); }
-        .crumb a { color:var(--amber-light); text-decoration:none; opacity:.8; }
-        h1 { font-family:'DM Serif Display',serif; font-size:clamp(2.4rem,5vw,3.9rem); font-weight:400; line-height:1.08; letter-spacing:-.02em; margin-bottom:1.3rem; }
-        h1 em { font-style:italic; color:var(--amber-light); }
-        .hero-desc { font-size:1.02rem; color:#a09a8e; margin-bottom:2rem; line-height:1.75; max-width:34rem; }
-        .hero-actions { display:flex; gap:1rem; flex-wrap:wrap; }
-        .btn-primary { background:var(--amber); color:#fff; text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; font-weight:500; transition:background .15s; }
-        .btn-primary:hover { background:var(--amber-light); color:#000; }
-        .btn-secondary { background:transparent; color:var(--gray-4); text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; border:1px solid var(--gray-2); transition:border-color .15s,color .15s; }
-        .btn-secondary:hover { border-color:var(--gray-4); color:var(--off-white); }
-
-        /* TERMINAL */
-        .terminal { background:#111; border:1px solid #2a2a2a; border-radius:8px; overflow:hidden; }
-        .terminal-bar { background:#1a1a1a; border-bottom:1px solid #2a2a2a; padding:.6rem 1rem; display:flex; gap:.4rem; align-items:center; }
-        .dot { width:10px; height:10px; border-radius:50%; }
-        .dot-red{background:#ff5f57;} .dot-yellow{background:#febc2e;} .dot-green{background:#28c840;}
-        .terminal-body { padding:1.2rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.95; }
-        .t-prompt{color:#5a9060;} .t-cmd{color:#e8e0d0;} .t-comment{color:#555;} .t-out{color:#7a9f7a;} .t-path{color:#d4a862;} .t-dim{color:#444;} .t-bad{color:#e06c5e;} .t-hash{color:#8a8a8a;}
-
-        /* SECTIONS */
-        section { padding:5rem 2rem; border-bottom:1px solid var(--border); }
-        .section-inner { max-width:1100px; margin:0 auto; }
-        .eyebrow { font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.14em; text-transform:uppercase; color:var(--amber); margin-bottom:.9rem; }
-        h2 { font-family:'DM Serif Display',serif; font-size:clamp(1.7rem,3vw,2.3rem); font-weight:400; line-height:1.2; margin-bottom:.6rem; }
-        .lede { color:var(--gray-3); font-size:1rem; max-width:44rem; line-height:1.7; }
-
-        .guarantees { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:1.5rem; margin-top:2.6rem; }
-        .card { background:#fff; border:1px solid var(--border); border-radius:8px; padding:1.8rem; transition:border-color .15s,box-shadow .15s; }
-        .card:hover { border-color:var(--amber); box-shadow:0 4px 20px rgba(0,0,0,.06); }
-        .card .num { font-family:'IBM Plex Mono',monospace; font-size:.7rem; color:var(--amber); letter-spacing:.1em; }
-        .card h3 { font-family:'DM Serif Display',serif; font-weight:400; font-size:1.3rem; margin:.5rem 0 .6rem; }
-        .card p { font-size:.9rem; color:var(--gray-3); line-height:1.65; }
-        .card p .mono { color:var(--gray-1); }
-
-        /* COMMANDS */
-        .cmds { background:#fff; }
-        .cmd-list { margin-top:2.4rem; border:1px solid var(--border); border-radius:8px; overflow:hidden; }
-        .cmd-row { display:grid; grid-template-columns:9rem 1fr; gap:1.5rem; padding:1.15rem 1.5rem; border-bottom:1px solid var(--border); align-items:baseline; }
-        .cmd-row:last-child { border-bottom:none; }
-        .cmd-row:hover { background:var(--warm-white); }
-        .cmd-name { font-family:'IBM Plex Mono',monospace; font-size:.85rem; font-weight:700; color:var(--black); }
-        .cmd-desc { font-size:.9rem; color:var(--gray-3); line-height:1.6; }
-        .cmd-desc .mono { color:var(--amber); }
-        @media (max-width:560px){ .cmd-row{ grid-template-columns:1fr; gap:.3rem; } }
-
-        /* INSTALL */
-        .install { background:var(--warm-white); }
-        .install-grid { display:grid; grid-template-columns:1fr 1fr; gap:2.5rem; margin-top:2.4rem; align-items:start; }
-        @media (max-width:820px){ .install-grid{ grid-template-columns:1fr; } }
-        .install pre { background:#111; color:#e8e0d0; border-radius:8px; padding:1.25rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.9; overflow-x:auto; }
-        .install pre .c { color:#555; } .install pre .p { color:#5a9060; }
-        .badges { display:flex; flex-wrap:wrap; gap:.5rem; margin-top:1.2rem; }
-        .badge { font-family:'IBM Plex Mono',monospace; font-size:.65rem; background:#fff; border:1px solid var(--border); color:var(--gray-3); padding:.2rem .55rem; border-radius:3px; }
-        .exit { margin-top:1.4rem; display:flex; flex-direction:column; gap:.55rem; }
-        .exit .e { font-size:.85rem; color:var(--gray-3); display:flex; gap:.7rem; align-items:baseline; }
-        .exit .code { font-family:'IBM Plex Mono',monospace; font-weight:700; min-width:1.2rem; }
-        .exit .g{color:var(--green);} .exit .r{color:var(--red);} .exit .a{color:var(--amber);}
-
-        /* FOOTER */
-        footer { background:var(--black); color:var(--gray-4); padding:3rem 2rem; }
-        .footer-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:1.5rem; }
-        .footer-logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:.9rem; color:var(--gray-4); text-decoration:none; }
-        .footer-logo span { color:var(--amber); }
-        .footer-left p { font-size:.78rem; color:var(--gray-2); margin-top:.4rem; }
-        .footer-links { display:flex; gap:1.5rem; flex-wrap:wrap; }
-        .footer-links a { font-family:'IBM Plex Mono',monospace; font-size:.75rem; color:var(--gray-3); text-decoration:none; transition:color .15s; }
-        .footer-links a:hover { color:var(--off-white); }
-
-        @keyframes fadeUp { from{opacity:0;transform:translateY(16px);} to{opacity:1;transform:translateY(0);} }
-        .crumb{animation:fadeUp .5s ease both;} h1{animation:fadeUp .5s ease .1s both;}
-        .hero-desc{animation:fadeUp .5s ease .2s both;} .hero-actions{animation:fadeUp .5s ease .3s both;} .terminal{animation:fadeUp .5s ease .4s both;}
-        @media (prefers-reduced-motion:reduce){ *{animation:none!important;} }
-        @media (max-width:640px){ .nav-links a:not(.btn-github):not(:last-child){ display:none; } }
-    </style>
+    <link rel="stylesheet" href="../assets/site.css">
 </head>
 <body>
 
@@ -126,7 +22,7 @@
     </div>
 </nav>
 
-<header class="hero">
+<header class="hero split">
     <div class="hero-inner">
         <div>
             <div class="crumb"><a href="/">Audit Labs</a> / evidence-seal</div>
@@ -247,7 +143,7 @@ evidence-seal verify ./evidence</pre>
             <a href="/">Home</a>
             <a href="/audit-report/">audit-report</a>
             <a href="https://github.com/audit-labs/evidence-seal">evidence-seal</a>
-            <a href="https://github.com/audit-labs/gh-attest">gh-attest</a>
+            <a href="/gh-attest/">gh-attest</a>
             <a href="https://github.com/audit-labs">GitHub</a>
         </div>
     </div>
diff --git a/gh-attest/index.html b/gh-attest/index.html
new file mode 100644
index 0000000..ea10305
--- /dev/null
+++ b/gh-attest/index.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>gh-attest | Audit Labs</title>
+    <meta name="description" content="A read-only GitHub App that turns your security configuration into auditor-ready evidence — branch protection, scanning alerts, and org access recorded over time and mapped to SOC 2 and ISO 27001 controls.">
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet">
+    <link rel="stylesheet" href="../assets/site.css">
+</head>
+<body>
+
+<nav>
+    <div class="nav-inner">
+        <a href="/" class="logo">AUDIT<span>LABS</span></a>
+        <ul class="nav-links">
+            <li><a href="/">Home</a></li>
+            <li><a href="/audit-report/">audit-report</a></li>
+            <li><a href="https://github.com/audit-labs/gh-attest" class="btn-github">View on GitHub →</a></li>
+        </ul>
+    </div>
+</nav>
+
+<header class="hero split">
+    <div class="hero-inner">
+        <div>
+            <div class="crumb"><a href="/">Audit Labs</a> / gh-attest</div>
+            <h1>Your GitHub settings,<br><em>as audit evidence.</em></h1>
+            <p class="hero-desc">
+                A read-only GitHub App that records branch protection, scanning alerts, and
+                organization access as they change &mdash; maps each signal to SOC&nbsp;2 and
+                ISO&nbsp;27001 controls, and exports point-in-time CSV and PDF evidence packages.
+                It never modifies your repositories, permissions, or membership.
+            </p>
+            <div class="hero-actions">
+                <a href="https://github.com/audit-labs/gh-attest" class="btn-primary">View on GitHub</a>
+                <a href="#collect" class="btn-secondary">What it collects</a>
+            </div>
+        </div>
+        <div class="terminal">
+            <div class="terminal-bar"><div class="dot dot-red"></div><div class="dot dot-yellow"></div><div class="dot dot-green"></div></div>
+            <div class="terminal-body">
+                <span class="t-comment"># Changes are recorded as they happen</span><br>
+                <span class="t-out">▸ branch protection enabled</span><span class="t-hash">&nbsp;&nbsp;repo/app · main</span><br>
+                <span class="t-path">&nbsp;&nbsp;&nbsp;→ SOC 2 CC8.1 · ISO 27001 A.8.32</span><br>
+                <span class="t-out">▸ secret scanning alert resolved</span><span class="t-hash">&nbsp;&nbsp;repo/api</span><br>
+                <span class="t-path">&nbsp;&nbsp;&nbsp;→ SOC 2 CC6.1, CC6.6 · ISO A.5.17</span><br>
+                <span class="t-dim">──────────────────────────────</span><br>
+                <span class="t-comment"># Export a point-in-time package</span><br>
+                <span class="t-out">✓ evidence package → </span><span class="t-path">acme_2026-08.csv + .pdf</span>
+            </div>
+        </div>
+    </div>
+</header>
+
+<section>
+    <div class="section-inner">
+        <div class="eyebrow">How it works</div>
+        <h2>Capture, map, export.</h2>
+        <p class="lede">Evidence accrues on its own &mdash; you install the app once and pull a package whenever an auditor asks.</p>
+        <div class="guarantees">
+            <div class="card">
+                <div class="num">01 · CAPTURE</div>
+                <h3>As it changes</h3>
+                <p>Webhooks record branch protection, rulesets, and scanning alerts the moment they change. An hourly cron polls for state webhooks never announce &mdash; protection that predates install, and current membership &mdash; storing each as a timestamped snapshot.</p>
+            </div>
+            <div class="card">
+                <div class="num">02 · MAP</div>
+                <h3>To the controls</h3>
+                <p>Each signal is mapped to SOC&nbsp;2 and ISO&nbsp;27001 controls with a plain-language rationale. Mappings apply as a join at query time, so one can be corrected without re-ingesting history.</p>
+            </div>
+            <div class="card">
+                <div class="num">03 · EXPORT</div>
+                <h3>Auditor-ready</h3>
+                <p>Point-in-time CSV and PDF evidence packages, rendered off the request path via a queue. Every export reflects the exact state at the moment you asked &mdash; not just today&rsquo;s.</p>
+            </div>
+        </div>
+    </div>
+</section>
+
+<section class="cmds" id="collect">
+    <div class="section-inner">
+        <div class="eyebrow">What it collects</div>
+        <h2>Signals, and the controls they evidence.</h2>
+        <p class="lede">Every mapping &mdash; and why each signal is defensible evidence for its control &mdash; is documented alongside the machine-readable version in the repo.</p>
+        <div class="cmd-list">
+            <div class="cmd-row"><div class="cmd-name">Branch protection</div><div class="cmd-desc">Protection rules and repository rulesets. <span class="mono">SOC 2 CC8.1 · ISO 27001 A.8.32</span></div></div>
+            <div class="cmd-row"><div class="cmd-name">Secret scanning</div><div class="cmd-desc">Secret scanning alerts and push protection. <span class="mono">SOC 2 CC6.1, CC6.6 · ISO A.5.17</span></div></div>
+            <div class="cmd-row"><div class="cmd-name">Dependabot</div><div class="cmd-desc">Dependency vulnerability alerts. <span class="mono">SOC 2 CC7.1, CC7.2 · ISO A.8.8</span></div></div>
+            <div class="cmd-row"><div class="cmd-name">Code scanning</div><div class="cmd-desc">Code scanning alerts from CodeQL and partners. <span class="mono">SOC 2 CC7.1 · ISO A.8.28, A.8.29</span></div></div>
+            <div class="cmd-row"><div class="cmd-name">Access</div><div class="cmd-desc">Organization and team membership over time. <span class="mono">SOC 2 CC6.2, CC6.3 · ISO A.5.18</span></div></div>
+            <div class="cmd-row"><div class="cmd-name">Inventory</div><div class="cmd-desc">Repository inventory and visibility. <span class="mono">ISO 27001 A.5.9</span></div></div>
+        </div>
+    </div>
+</section>
+
+<section class="frameworks">
+    <div class="frameworks-inner">
+        <span class="frameworks-label">Maps GitHub signals to</span>
+        <div class="frameworks-list">
+            <span class="framework-tag">SOC 2</span>
+            <span class="framework-tag">ISO 27001</span>
+        </div>
+    </div>
+</section>
+
+<section class="install" id="start">
+    <div class="section-inner">
+        <div class="eyebrow">Get started</div>
+        <h2>Install once, evidence accrues.</h2>
+        <div class="install-grid">
+            <div>
+                <pre><span class="c"># 1. Install the GitHub App on your org</span>
+<span class="c">#    (read-only, least-privilege scopes)</span>
+<span class="c"># 2. Select the repositories to cover</span>
+<span class="c"># 3. Snapshots begin immediately</span>
+<span class="c"># 4. Export a package whenever you need one</span></pre>
+                <div class="badges">
+                    <span class="badge">TypeScript</span>
+                    <span class="badge">Cloudflare Workers</span>
+                    <span class="badge">D1</span>
+                    <span class="badge">R2</span>
+                    <span class="badge">GPL-3.0</span>
+                </div>
+            </div>
+            <div>
+                <p class="lede">Read-only, by design &mdash; what it never does:</p>
+                <div class="exit">
+                    <div class="e"><span class="code g">✓</span><span>Never modifies your repositories or their contents.</span></div>
+                    <div class="e"><span class="code g">✓</span><span>Never changes permissions, teams, or membership.</span></div>
+                    <div class="e"><span class="code g">✓</span><span>Requests the minimum read scopes to observe configuration.</span></div>
+                </div>
+                <p class="lede" style="margin-top:1.4rem; font-size:.9rem;">
+                    Prefer to run audits yourself?
+                    <a href="/audit-report/" style="color:var(--amber); text-decoration:none;">audit-report</a>
+                    turns offline evidence packages into the same control-mapped reports.
+                </p>
+            </div>
+        </div>
+    </div>
+</section>
+
+<footer>
+    <div class="footer-inner">
+        <div class="footer-left">
+            <a href="/" class="footer-logo">AUDIT<span>LABS</span></a>
+            <p>© 2026 Audit Labs — a two-person team building for the community.</p>
+        </div>
+        <div class="footer-links">
+            <a href="/">Home</a>
+            <a href="/audit-report/">audit-report</a>
+            <a href="/evidence-seal/">evidence-seal</a>
+            <a href="https://github.com/audit-labs/gh-attest">gh-attest</a>
+            <a href="https://github.com/audit-labs">GitHub</a>
+        </div>
+    </div>
+</footer>
+
+</body>
+</html>
diff --git a/index.html b/index.html
index 48a6385..4372ce9 100644
--- a/index.html
+++ b/index.html
@@ -7,506 +7,7 @@
     <a rel="me" href="https://c.im/@cmc"></a>
     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet">
-    <style>
-        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
-
-        :root {
-            --black: #0a0a0a;
-            --off-white: #f4f1eb;
-            --warm-white: #faf8f4;
-            --amber: #d97706;
-            --amber-light: #fbbf24;
-            --green: #15803d;
-            --green-muted: #166534;
-            --gray-1: #1c1c1c;
-            --gray-2: #2e2e2e;
-            --gray-3: #6b6b6b;
-            --gray-4: #a3a3a3;
-            --gray-5: #d4d4d4;
-            --border: #e5e1d8;
-        }
-
-        body {
-            font-family: 'DM Sans', sans-serif;
-            background: var(--warm-white);
-            color: var(--black);
-            line-height: 1.6;
-        }
-
-        .mono { font-family: 'IBM Plex Mono', monospace; }
-        .serif { font-family: 'DM Serif Display', serif; }
-
-        /* NAV */
-        nav {
-            position: sticky;
-            top: 0;
-            z-index: 100;
-            background: var(--warm-white);
-            border-bottom: 1px solid var(--border);
-            padding: 0 2rem;
-        }
-
-        .nav-inner {
-            max-width: 1100px;
-            margin: 0 auto;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            height: 60px;
-        }
-
-        .logo {
-            font-family: 'IBM Plex Mono', monospace;
-            font-weight: 700;
-            font-size: 1.1rem;
-            letter-spacing: -0.02em;
-            color: var(--black);
-            text-decoration: none;
-        }
-
-        .logo span { color: var(--amber); }
-
-        .nav-links {
-            display: flex;
-            gap: 2rem;
-            align-items: center;
-            list-style: none;
-        }
-
-        .nav-links a {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.78rem;
-            color: var(--gray-3);
-            text-decoration: none;
-            transition: color 0.15s;
-        }
-
-        .nav-links a:hover { color: var(--black); }
-
-        .nav-links .btn-github {
-            background: var(--black);
-            color: var(--off-white);
-            padding: 0.45rem 1rem;
-            border-radius: 4px;
-            font-size: 0.75rem;
-            transition: background 0.15s;
-        }
-
-        .nav-links .btn-github:hover { background: var(--gray-2); color: var(--off-white); }
-
-        /* HERO */
-        .hero {
-            background: var(--black);
-            color: var(--off-white);
-            padding: 7rem 2rem 5rem;
-            position: relative;
-            overflow: hidden;
-        }
-
-        .hero::before {
-            content: '';
-            position: absolute;
-            inset: 0;
-            background-image: 
-                repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(255,255,255,0.03) 39px, rgba(255,255,255,0.03) 40px),
-                repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(255,255,255,0.03) 39px, rgba(255,255,255,0.03) 40px);
-            pointer-events: none;
-        }
-
-        .hero-inner {
-            max-width: 1100px;
-            margin: 0 auto;
-            position: relative;
-        }
-
-        .hero-label {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.7rem;
-            letter-spacing: 0.15em;
-            text-transform: uppercase;
-            color: var(--amber-light);
-            margin-bottom: 1.5rem;
-            display: flex;
-            align-items: center;
-            gap: 0.5rem;
-        }
-
-        .hero-label::before {
-            content: '';
-            display: inline-block;
-            width: 1.5rem;
-            height: 1px;
-            background: var(--amber-light);
-        }
-
-        h1 {
-            font-family: 'DM Serif Display', serif;
-            font-size: clamp(2.8rem, 6vw, 5rem);
-            font-weight: 400;
-            line-height: 1.1;
-            letter-spacing: -0.02em;
-            margin-bottom: 1.5rem;
-            max-width: 700px;
-        }
-
-        h1 em {
-            font-style: italic;
-            color: var(--amber-light);
-        }
-
-        .hero-desc {
-            font-size: 1.05rem;
-            color: #a09a8e;
-            max-width: 540px;
-            margin-bottom: 2.5rem;
-            line-height: 1.75;
-        }
-
-        .hero-actions {
-            display: flex;
-            gap: 1rem;
-            flex-wrap: wrap;
-            margin-bottom: 4rem;
-        }
-
-        .btn-primary {
-            background: var(--amber);
-            color: #fff;
-            text-decoration: none;
-            padding: 0.75rem 1.5rem;
-            border-radius: 4px;
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.8rem;
-            font-weight: 500;
-            transition: background 0.15s;
-        }
-
-        .btn-primary:hover { background: var(--amber-light); color: #000; }
-
-        .btn-secondary {
-            background: transparent;
-            color: var(--gray-4);
-            text-decoration: none;
-            padding: 0.75rem 1.5rem;
-            border-radius: 4px;
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.8rem;
-            border: 1px solid var(--gray-2);
-            transition: border-color 0.15s, color 0.15s;
-        }
-
-        .btn-secondary:hover { border-color: var(--gray-4); color: var(--off-white); }
-
-        /* Terminal block */
-        .terminal {
-            background: #111;
-            border: 1px solid #2a2a2a;
-            border-radius: 8px;
-            overflow: hidden;
-            max-width: 600px;
-        }
-
-        .terminal-bar {
-            background: #1a1a1a;
-            border-bottom: 1px solid #2a2a2a;
-            padding: 0.6rem 1rem;
-            display: flex;
-            gap: 0.4rem;
-            align-items: center;
-        }
-
-        .dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
-        .dot-red { background: #ff5f57; }
-        .dot-yellow { background: #febc2e; }
-        .dot-green { background: #28c840; }
-
-        .terminal-body {
-            padding: 1.25rem 1.5rem;
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.82rem;
-            line-height: 1.9;
-        }
-
-        .t-prompt { color: #5a9060; }
-        .t-cmd { color: #e8e0d0; }
-        .t-comment { color: #555; }
-        .t-out { color: #7a9f7a; }
-        .t-path { color: #d4a862; }
-        .t-dim { color: #444; }
-
-        /* REPOS SECTION */
-        .repos {
-            padding: 5rem 2rem;
-            background: var(--warm-white);
-            border-bottom: 1px solid var(--border);
-        }
-
-        .section-inner {
-            max-width: 1100px;
-            margin: 0 auto;
-        }
-
-        .section-header {
-            display: flex;
-            justify-content: space-between;
-            align-items: baseline;
-            margin-bottom: 3rem;
-            flex-wrap: wrap;
-            gap: 1rem;
-        }
-
-        h2 {
-            font-family: 'DM Serif Display', serif;
-            font-size: clamp(1.8rem, 3vw, 2.4rem);
-            font-weight: 400;
-            line-height: 1.2;
-        }
-
-        .section-link {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.75rem;
-            color: var(--gray-3);
-            text-decoration: none;
-            border-bottom: 1px solid var(--gray-5);
-            padding-bottom: 1px;
-            transition: color 0.15s;
-        }
-
-        .section-link:hover { color: var(--black); }
-
-        .repo-grid {
-            display: grid;
-            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
-            gap: 1.5rem;
-        }
-
-        .repo-card {
-            background: #fff;
-            border: 1px solid var(--border);
-            border-radius: 8px;
-            padding: 2rem;
-            text-decoration: none;
-            color: inherit;
-            display: block;
-            transition: border-color 0.15s, box-shadow 0.15s;
-            position: relative;
-        }
-
-        .repo-card:hover {
-            border-color: var(--amber);
-            box-shadow: 0 4px 20px rgba(0,0,0,0.06);
-        }
-
-        .repo-tag {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.65rem;
-            text-transform: uppercase;
-            letter-spacing: 0.1em;
-            color: var(--amber);
-            background: #fef3c7;
-            padding: 0.2rem 0.5rem;
-            border-radius: 3px;
-            display: inline-block;
-            margin-bottom: 1rem;
-        }
-
-        .repo-card h3 {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.95rem;
-            font-weight: 700;
-            margin-bottom: 0.6rem;
-            color: var(--black);
-        }
-
-        .repo-card p {
-            font-size: 0.9rem;
-            color: var(--gray-3);
-            line-height: 1.65;
-            margin-bottom: 1.5rem;
-        }
-
-        .repo-langs {
-            display: flex;
-            gap: 0.5rem;
-            flex-wrap: wrap;
-        }
-
-        .lang-badge {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.65rem;
-            background: var(--off-white);
-            border: 1px solid var(--border);
-            color: var(--gray-3);
-            padding: 0.15rem 0.5rem;
-            border-radius: 3px;
-        }
-
-        /* TOOLS SECTION */
-        .tools {
-            padding: 5rem 2rem;
-            background: #fff;
-            border-bottom: 1px solid var(--border);
-        }
-
-        .tools-intro {
-            max-width: 550px;
-            margin-bottom: 3rem;
-        }
-
-        .tools-intro p {
-            color: var(--gray-3);
-            font-size: 0.95rem;
-            margin-top: 0.75rem;
-            line-height: 1.7;
-        }
-
-        .tool-list {
-            display: grid;
-            grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
-            gap: 1px;
-            background: var(--border);
-            border: 1px solid var(--border);
-            border-radius: 8px;
-            overflow: hidden;
-        }
-
-        .tool-item {
-            background: #fff;
-            padding: 1.75rem;
-            transition: background 0.15s;
-        }
-
-        .tool-item:hover { background: var(--warm-white); }
-
-        .tool-icon {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.7rem;
-            color: var(--amber);
-            margin-bottom: 0.75rem;
-            letter-spacing: 0.05em;
-        }
-
-        .tool-item h4 {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.85rem;
-            font-weight: 700;
-            margin-bottom: 0.5rem;
-            color: var(--black);
-        }
-
-        .tool-item p {
-            font-size: 0.82rem;
-            color: var(--gray-3);
-            line-height: 1.6;
-        }
-
-        /* FRAMEWORKS */
-        .frameworks {
-            padding: 3.5rem 2rem;
-            background: var(--warm-white);
-            border-bottom: 1px solid var(--border);
-        }
-
-        .frameworks-inner {
-            max-width: 1100px;
-            margin: 0 auto;
-            display: flex;
-            align-items: center;
-            gap: 3rem;
-            flex-wrap: wrap;
-        }
-
-        .frameworks-label {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.68rem;
-            letter-spacing: 0.12em;
-            text-transform: uppercase;
-            color: var(--gray-4);
-            white-space: nowrap;
-        }
-
-        .frameworks-list {
-            display: flex;
-            gap: 2.5rem;
-            flex-wrap: wrap;
-            align-items: center;
-        }
-
-        .framework-tag {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.8rem;
-            font-weight: 700;
-            color: var(--gray-3);
-            letter-spacing: 0.05em;
-        }
-
-        /* FOOTER */
-        footer {
-            background: var(--black);
-            color: var(--gray-4);
-            padding: 3rem 2rem;
-        }
-
-        .footer-inner {
-            max-width: 1100px;
-            margin: 0 auto;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            flex-wrap: wrap;
-            gap: 1.5rem;
-        }
-
-        .footer-logo {
-            font-family: 'IBM Plex Mono', monospace;
-            font-weight: 700;
-            font-size: 0.9rem;
-            color: var(--gray-4);
-            text-decoration: none;
-        }
-
-        .footer-logo span { color: var(--amber); }
-
-        .footer-left p {
-            font-size: 0.78rem;
-            color: var(--gray-2);
-            margin-top: 0.4rem;
-        }
-
-        .footer-links {
-            display: flex;
-            gap: 1.5rem;
-            align-items: center;
-        }
-
-        .footer-links a {
-            font-family: 'IBM Plex Mono', monospace;
-            font-size: 0.75rem;
-            color: var(--gray-3);
-            text-decoration: none;
-            transition: color 0.15s;
-        }
-
-        .footer-links a:hover { color: var(--off-white); }
-
-        /* ANIMATIONS */
-        @keyframes fadeUp {
-            from { opacity: 0; transform: translateY(16px); }
-            to { opacity: 1; transform: translateY(0); }
-        }
-
-        .hero-label { animation: fadeUp 0.5s ease both; }
-        h1 { animation: fadeUp 0.5s ease 0.1s both; }
-        .hero-desc { animation: fadeUp 0.5s ease 0.2s both; }
-        .hero-actions { animation: fadeUp 0.5s ease 0.3s both; }
-        .terminal { animation: fadeUp 0.5s ease 0.4s both; }
-
-        /* RESPONSIVE */
-        @media (max-width: 640px) {
-            .nav-links a:not(.btn-github):not(:last-child) { display: none; }
-            h1 { font-size: 2.4rem; }
-        }
-    </style>
+    <link rel="stylesheet" href="assets/site.css">
 </head>
 <body>
 
@@ -580,7 +81,7 @@
                     <span class="lang-badge">Markdown</span>
                 </div>
             </a>
-            <a href="https://github.com/audit-labs/gh-attest" class="repo-card">
+            <a href="/gh-attest/" class="repo-card">
                 <div class="repo-tag">GitHub App</div>
                 <h3>audit-labs/gh-attest</h3>
                 <p>A read-only GitHub App that turns your security configuration into compliance evidence. Captures branch protection, scanning alerts, and org access over time, maps them to SOC 2 and ISO 27001 controls, and exports CSV and PDF evidence packages.</p>
@@ -678,7 +179,7 @@
             <a href="https://github.com/audit-labs/audit-tools">audit-tools</a>
             <a href="/audit-report/">audit-report</a>
             <a href="/evidence-seal/">evidence-seal</a>
-            <a href="https://github.com/audit-labs/gh-attest">gh-attest</a>
+            <a href="/gh-attest/">gh-attest</a>
             <a href="https://github.com/audit-labs/tutorials">tutorials</a>
             <a href="https://github.com/audit-labs">GitHub</a>
         </div>