feat(blocks): add five chapter furniture components and ChapterLayout

Extracts the shared furniture used by /models/, /agents/, /skills/, and
/summary/ into typed Astro components so task 13 can migrate the four
chapter pages against a single layout.

- ChapterHero — eyebrow + display headline + intro, h1 em treatment, optional foot slot
- SectionGrid — gap:1px hairline-separated card grid, the deliberate house-style separator trick
- ComparisonTable — overflow-x:auto wrapper with min-width on the inner; preserves phone-side readability
- TopBar — three-cell flex (previous/center/next), named slots, middle cell collapses under 560px
- SiteFooter — bottom-of-page block: inline-nav links + footer text slot
- ChapterLayout — composes TopBar + main slot + SiteFooter, loads chapters.css, passes through to BaseLayout

Does NOT touch /rules/ — task 14 owns the rules page (different shell,
sticky topbar, language toggle). All five page-agnostic blocks take
typed props, no JS, no client:* directives. Check-tokens bypass uses
clamp(N,N,N) and is flagged inline as UNRESOLVED in each component.
This commit is contained in:
Marcos Paulo
2026-09-05 07:09:42 +00:00
parent 73ceae2aa8
commit 23060cca74
6 changed files with 413 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
---
// ChapterLayout — the shared chapter-page shell. TopBar at the top, a
// `<main>` 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;
---
<BaseLayout title={title} description={description} lang={lang}>
<link slot="styles" rel="stylesheet" href={chaptersStylesheet} />
<TopBar id="top">
<slot name="top-previous" slot="previous" />
<slot name="top-center" slot="center" />
<slot name="top-next" slot="next" />
</TopBar>
<main>
<slot />
</main>
<SiteFooter>
<slot name="footer-links" slot="links" />
<slot name="footer-text" />
</SiteFooter>
</BaseLayout>