Phase 4: component library

The approved element rules and ornament kit as Astro components in
packages/ui: buttons, pills, chips, filters, kickers, notices, fields and
cards; star paths, the header divider, tick scales and rings, seals and
edge seals, gilt corners, dust and placeholder art; the site header,
footer and page shell. Brand fonts are self-hosted. A gallery page shows
everything, and astro check now runs with the root typecheck.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
Claude
2026-10-11 20:44:16 +00:00
parent 32cf13a5cb
commit 807528a613
159 changed files with 6270 additions and 87 deletions
@@ -0,0 +1,79 @@
---
/**
* Every page's frame: the document head, the page background (constellation
* dust and the family's edge seals), the site header with an optional hero,
* the page content, and the footer.
*/
import "../styles/tokens.css";
import "../styles/fonts.css";
import "../styles/base.css";
import "../styles/elements.css";
import ConstellationDust from "./ConstellationDust.astro";
import EdgeSeals from "./EdgeSeals.astro";
import SiteFooter from "./SiteFooter.astro";
import SiteHeader from "./SiteHeader.astro";
import type { NavKey } from "./nav.ts";
import type { PageFamily, SealName } from "./seals.ts";
interface Props {
title: string;
description?: string;
family?: PageFamily;
/** A craft page's own seal, overriding the family's. */
seal?: SealName;
current?: NavKey;
/** Leave the edge seals off, for a page led by a photo. */
noSeals?: boolean;
}
const { title, description, family = "landing", seal, current, noSeals } = Astro.props;
const fullTitle = title === "Greg Kilmer" ? title : `${title} · Greg Kilmer`;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="dark" />
<meta name="theme-color" content="#0E1522" />
<title>{fullTitle}</title>
{description && <meta name="description" content={description} />}
<slot name="head" />
</head>
<body>
<a class="gk-skip" href="#main">Skip to content</a>
<div class="gk-page">
<ConstellationDust />
{!noSeals && <EdgeSeals family={family} seal={seal} />}
<SiteHeader current={current}><slot name="hero" /></SiteHeader>
<main id="main" class="gk-wrap gk-main">
<slot />
</main>
<SiteFooter />
</div>
</body>
</html>
<style>
.gk-page {
position: relative;
min-height: 100vh;
overflow-x: clip;
}
.gk-main {
position: relative;
}
.gk-skip {
position: absolute;
left: 16px;
top: -60px;
z-index: 50;
padding: 10px 16px;
border-radius: 999px;
background: var(--gk-midnight);
border: 1px solid var(--gk-gold);
color: var(--gk-text);
}
.gk-skip:focus {
top: 12px;
}
</style>