Files
ai-for-dummies/src/pages/index.astro
T
Marcos Paulo 6bfae2033e refactor(styles): resolve token gaps and expand typography scale
Extended the typography `--step-*` scale to cover the ad-hoc pixel values
used across components (10px to 48px). Added overlay tokens `--white-14`,
`--white-23`, `--white-25`, `--white-31`.

Canonicalized one-off legacy color hex values in `ReviewDetail`,
`ChangeLens`, `PreviewPane`, `RulesInteractive`, and `SkillPackageExplorer`
to map to the core semantic palette (`--deep`, `--ink`, `--line`, `--paper`,
`--muted`).

Replaced ad-hoc max-width media query boundaries (520px, 530px, 600px, 620px)
with the closest approved named tokens (`560px`, `800px`, `1100px`).
2026-09-05 22:53:56 +00:00

150 lines
4.4 KiB
TypeScript

---
// / — 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);
font:
700 var(--step-12) 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);
font-size: var(--step-22);
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);
font:
700 var(--step-0) ui-monospace,
monospace;
letter-spacing: 0.1em;
}
.landing-note strong {
font-size: var(--step-4);
line-height: 1.08;
letter-spacing: -0.04em;
}
@media (max-width: 560px) {
.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>