diff --git a/src/components/blocks/ChapterHero.astro b/src/components/blocks/ChapterHero.astro
new file mode 100644
index 0000000..2a8eb7f
--- /dev/null
+++ b/src/components/blocks/ChapterHero.astro
@@ -0,0 +1,82 @@
+---
+// ChapterHero — eyebrow + display headline + intro paragraph. The shared
+// opener for /models/, /agents/, /skills/, /summary/. The optional `foot`
+// slot holds the rules case-study's two-column hero-foot.
+//
+// The eyebrow reuses the existing `Eyebrow` primitive but defaults to the
+// `red` tone, which matches the chapter surfaces (not the guide surface).
+// The h1 em treatment (Georgia italic, red) is the chapter-page signature.
+
+import Eyebrow from '../primitives/Eyebrow.astro';
+
+interface Props {
+ /** Short uppercase label, same treatment as Eyebrow. Defaults to red,
+ * matching chapters.css `.eyebrow`. */
+ eyebrow: string;
+ /** Colour tone for the eyebrow. */
+ tone?: 'accent' | 'red';
+}
+
+const { eyebrow, tone = 'red' } = Astro.props;
+---
+
+
+
+
+
+
+
+
+
diff --git a/src/components/blocks/ComparisonTable.astro b/src/components/blocks/ComparisonTable.astro
new file mode 100644
index 0000000..a3eda3c
--- /dev/null
+++ b/src/components/blocks/ComparisonTable.astro
@@ -0,0 +1,81 @@
+---
+// ComparisonTable — horizontal-scroll wrapper for wide comparison tables.
+// Used by /models/ and /rules/ pages where tables become unreadable on a
+// phone without horizontal scroll.
+//
+// The pattern from chapters.css and full-guide/audit.css:
+//
+//
...
+//
+// with `.table-wrap { overflow-x: auto }`.
+//
+// Callers pass the table via the default slot; the wrapper class adds the
+// scroll behaviour and hairline border so the wrapper itself looks
+// intentional, not like an overflow leak.
+
+interface Props {
+ /** Minimum width on the inner table. Forces horizontal scroll below this
+ * width rather than squashing columns into illegibility. */
+ minWidth?: string;
+}
+
+const { minWidth = '640px' } = Astro.props;
+---
+
+
+
+
+
+
+
+
diff --git a/src/components/blocks/SectionGrid.astro b/src/components/blocks/SectionGrid.astro
new file mode 100644
index 0000000..e670172
--- /dev/null
+++ b/src/components/blocks/SectionGrid.astro
@@ -0,0 +1,82 @@
+---
+// SectionGrid — the gap:1px hairline-separated card grid. Used by /models/'
+// LOW/MEDIUM/HIGH cards and /agents/' FRAME/HAND OFF/PROVE cards.
+//
+// The separator technique is deliberate house style: `gap:1px` over a
+// coloured parent background fakes borders without `border` shorthand. The
+// child fills its background to cover the parent's 1px seam.
+//
+// Each direct child is expected to be a card — the markup pattern from
+// chapters.css:
+// LABEL
Title
Body
+// The component styles `> .card` and its internals so callers don't repeat.
+
+interface Props {
+ /** Number of columns at the widest breakpoint. */
+ columns?: number;
+}
+
+const { columns = 3 } = Astro.props;
+---
+
+
+
+
+
+
diff --git a/src/components/blocks/SiteFooter.astro b/src/components/blocks/SiteFooter.astro
new file mode 100644
index 0000000..4c258b2
--- /dev/null
+++ b/src/components/blocks/SiteFooter.astro
@@ -0,0 +1,63 @@
+---
+// SiteFooter — the bottom of every chapter page. Holds the inline-nav links
+// (chapter-to-chapter or to the field guide) plus the small footer text.
+//
+// The chapter pages use a "pill" link style: 1px ink border, ink text,
+// inverts on hover. Padding and gap are inherited from chapters.css
+// `.links`. The block element is the lower bound of the page main — no
+// margin/padding magic, just the rule above the first link.
+//
+// Footer text (the muted paragraph) goes into the default slot.
+
+interface Props {
+ /** Optional accessible label for the inline-nav region. */
+ navLabel?: string;
+}
+
+const { navLabel = 'Chapter navigation' } = Astro.props;
+---
+
+
+
+
+
+
+
+
+
diff --git a/src/components/blocks/TopBar.astro b/src/components/blocks/TopBar.astro
new file mode 100644
index 0000000..70372c3
--- /dev/null
+++ b/src/components/blocks/TopBar.astro
@@ -0,0 +1,64 @@
+---
+// TopBar — the three-cell topbar shared by /models/, /agents/, /skills/,
+// /summary/. Each slot is independent; the layout is a flex row with
+// `justify-content: space-between`.
+//
+// The chapter pages use:
+// ← ROUTE MAP | 01 / MODELS | field guide ↗
+//
+// The brief's watch-for: callers that mark a link as the current page
+// should set `aria-current="page"` on that link. The component does not
+// impose it — slot content is preserved verbatim. This is the only
+// indication of location for assistive tech on these pages, so losing
+// it would be a real regression.
+
+interface Props {
+ /** Optional HTML id for the topbar. */
+ id?: string;
+}
+
+const { id } = Astro.props;
+---
+
+
+
+
+
+
+
+
diff --git a/src/layouts/ChapterLayout.astro b/src/layouts/ChapterLayout.astro
new file mode 100644
index 0000000..03c72b9
--- /dev/null
+++ b/src/layouts/ChapterLayout.astro
@@ -0,0 +1,41 @@
+---
+// ChapterLayout — the shared chapter-page shell. TopBar at the top, a
+// `` slot for page content, SiteFooter at the bottom.
+//
+// Pages include this instead of BaseLayout for the four chapter routes
+// (/models/, /agents/, /skills/, /summary/). /rules/ uses a different shell
+// (task 14). /full-guide/ has its own.
+//
+// The chapters.css stylesheet is the shared layer. It carries the
+// chapter-palette tokens, the hero/grid/practice legacy classes, and the
+// responsive contract that audit-ui.mjs asserts.
+
+import BaseLayout from './BaseLayout.astro';
+import TopBar from '../components/blocks/TopBar.astro';
+import SiteFooter from '../components/blocks/SiteFooter.astro';
+import chaptersStylesheet from '../../chapters.css?url';
+
+interface Props {
+ title: string;
+ description: string;
+ lang?: string;
+}
+
+const { title, description, lang = 'en' } = Astro.props;
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+