Merge branch 'refactor/task-12-page-landing'
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