Merge branch 'main' into refactor/task-13-page-chapters
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
---
|
||||
// / — the landing route map. The smallest page migration in the refactor:
|
||||
// six cards rendered through `RouteCard` inside a `GridGroup`, copy lifted
|
||||
// from the `chapters` collection (`src/content/chapters/landing.json`,
|
||||
// id `landing`).
|
||||
//
|
||||
// Migrated from `index.html` per plans/astro-refactor/task-12-page-landing.md.
|
||||
// The page is the project's static entry point — it ships zero JavaScript.
|
||||
// Wrapped in `ChapterLayout` so the chapters.css palette (the drifted
|
||||
// chapter surface this page has always rendered with) loads before the
|
||||
// components resolve any colour, and so the surrounding chrome (TopBar,
|
||||
// SiteFooter, shared CSS) stays in lock-step with the chapter pages that
|
||||
// already migrated.
|
||||
|
||||
import { getEntry } from 'astro:content';
|
||||
import ChapterLayout from '../layouts/ChapterLayout.astro';
|
||||
import ChapterHero from '../components/blocks/ChapterHero.astro';
|
||||
import GridGroup from '../components/blocks/GridGroup.astro';
|
||||
import RouteCard from '../components/blocks/RouteCard.astro';
|
||||
|
||||
const landing = await getEntry('chapters', 'landing');
|
||||
if (!landing) throw new Error('landing page entry missing from chapters collection');
|
||||
const base = import.meta.env.BASE_URL;
|
||||
|
||||
// Landing-page copy is English-only today: the existing index.html always
|
||||
// rendered English, and wiring the full bilingual toggle is a separate task
|
||||
// (the language-toggle island in `.agents/rules/astro.md`). When that ship
|
||||
// lands, the `lang` value flows through the same pattern as the other
|
||||
// chapter pages and every `.en` access below becomes a `[lang]` lookup.
|
||||
const lang = 'en';
|
||||
const data = landing.data;
|
||||
const cards = data.cards ?? [];
|
||||
---
|
||||
|
||||
<ChapterLayout
|
||||
title="AI For Dummies — Start here"
|
||||
description="AI For Dummies: a practical route map for models, agents, worktrees, skills, rules, and verification."
|
||||
>
|
||||
<a slot="top-previous" href={base} aria-current="page">AI FOR DUMMIES</a>
|
||||
<span slot="top-center">00 / START HERE</span>
|
||||
<a slot="top-next" href={`${base}skills-review/`}>review desk ↗</a>
|
||||
|
||||
<ChapterHero eyebrow={data.eyebrow[lang]} tone="red">
|
||||
<span slot="title" set:html={data.title[lang]} />
|
||||
<p>{data.lede[lang]}</p>
|
||||
<a slot="foot" class="guide-launch" href={`${base}full-guide/`}
|
||||
>Take the full field guide <span>→</span></a
|
||||
>
|
||||
</ChapterHero>
|
||||
|
||||
<GridGroup label="Guide chapters" columns={3}>
|
||||
{
|
||||
cards.map((card) => (
|
||||
<RouteCard
|
||||
number={card.label[lang]}
|
||||
title={card.title[lang]}
|
||||
summary={card.copy[lang]}
|
||||
href={`${base}${card.href}`}
|
||||
cta={card.cta?.[lang] ?? 'Open chapter →'}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</GridGroup>
|
||||
|
||||
<section class="landing-note">
|
||||
<span>{data.threadLabel?.[lang]}</span>
|
||||
<strong>{data.threadText?.[lang]}</strong>
|
||||
</section>
|
||||
|
||||
<span slot="footer-text">{data.footer?.[lang]}</span>
|
||||
</ChapterLayout>
|
||||
|
||||
<style>
|
||||
/* Page-level styles only. Anything reusable belongs in a component.
|
||||
`.guide-launch` and `.landing-note` lived in `landing.css` and were
|
||||
unique to this route, so they stay inline rather than earning a block
|
||||
of their own. See `.agents/rules/componentization.md`. */
|
||||
|
||||
.guide-launch {
|
||||
display: inline-flex;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
padding: 12px 16px;
|
||||
background: var(--ink);
|
||||
color: var(--paper);
|
||||
/* token-gap: legacy 12px fixed from landing.css; --step-0 is 11px;
|
||||
no token matches 12px; owner design-system-keeper */
|
||||
font:
|
||||
700 12px ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.06em;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
background 0.2s ease;
|
||||
}
|
||||
|
||||
.guide-launch:hover {
|
||||
transform: translateY(-3px);
|
||||
background: var(--blue);
|
||||
}
|
||||
|
||||
.guide-launch span {
|
||||
color: var(--gold);
|
||||
/* token-gap: legacy 22px arrow from landing.css; no --step-* covers 22px; owner design-system-keeper */
|
||||
font-size: 22px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.landing-note {
|
||||
display: grid;
|
||||
grid-template-columns: 170px minmax(0, 1fr);
|
||||
gap: 30px;
|
||||
margin: 0 0 70px;
|
||||
padding: 25px 0;
|
||||
border-top: 1px solid var(--ink);
|
||||
border-bottom: 1px solid var(--ink);
|
||||
}
|
||||
|
||||
.landing-note span {
|
||||
color: var(--red);
|
||||
/* token-gap: legacy 11px monospace eyebrow (no DM Mono in stack);
|
||||
--step-0 also resolves to 11px but with different font weight;
|
||||
preserved verbatim from landing.css; owner design-system-keeper */
|
||||
font:
|
||||
700 11px ui-monospace,
|
||||
monospace;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.landing-note strong {
|
||||
/* token-gap: clamp(22px,3.2vw,42px) is specific to this strip; no
|
||||
--step-* ramp covers both endpoints; owner design-system-keeper */
|
||||
font-size: clamp(22px, 3.2vw, 42px);
|
||||
line-height: 1.08;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
/* token-gap: 520px collapse from landing.css (was bottom-bar threshold); owner design-system-keeper */
|
||||
@media (max-width: 520px) {
|
||||
.landing-note {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 9px;
|
||||
margin-bottom: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.guide-launch {
|
||||
transition: none;
|
||||
}
|
||||
.guide-launch:hover {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user