# Component library
`packages/ui` (`@gk/ui`) holds the approved element rules and ornament kit as
Astro components. The site imports them; nothing else defines how a button,
chip or seal looks. The rules come from the design canvas's Element rules and
Ornament kit boards, approved Oct 11.
Run the gallery with `npm run ui` (or `npm run ui:build` for a static copy in
`packages/ui/dist`). It shows every component inside the real page shell.
## Layout
| Path | What it is |
| --- | --- |
| `src/styles/tokens.css` | Colors, fonts, spacing, radii, control sizes and the page width as `--gk-*` variables. |
| `src/styles/fonts.css` | Cinzel and Montserrat, self-hosted as Latin-subset WOFF2 (OFL, see `src/assets/fonts/LICENSE.md`). |
| `src/styles/base.css` | Page defaults: body, headings, body links, the focus ring, `.gk-wrap`, reduced motion. |
| `src/styles/elements.css` | The element rules as global `gk-*` classes, so Markdown output and plain HTML can use them too. |
| `src/lib/ornaments.ts` | The seeded geometry behind star paths, tick scales, tick rings and dust. Tested in `test/ornaments.test.ts`. |
| `src/components/` | The Astro components below. |
| `src/assets/` | Seals and motifs, the monogram, 86 stroke icons, the card tick strip, and the fonts. |
## Element rules
| Rule | Component | Notes |
| --- | --- | --- |
| I Buttons | `Button` | `variant` primary (teal pill), secondary (gold hairline) or text (filament underline on hover); `size="compact"` for 36px; `href` makes it a link. One primary per section. |
| II States | `StatusPill` | Round pill. `live` teal with a lit dot, `state` without the dot, `favorite` and `current` gold with a star. |
| II Labels | `Chip` | Square 6px chip. `core` gives the teal edge; `href` makes it a page link led by a violet star. |
| III Filters | `FilterGroup` | Separate 36px pills. Items with `href` are links (`aria-current`); items without are toggle buttons (`aria-pressed`) a page script drives. |
| IV Kickers | `Kicker`, `SectionHeading` | Gold capitals over a tick scale. `SectionHeading` adds the Cinzel heading and the filament underline. |
| IV Notices | `Notice` | The ledger note: soft gold panel, gold rule on the left. |
| V Fields | `Field`, `SearchField` | Input, select or text area in the 10px box, filament across the base on focus, with `hint` and `error` wired to `aria-describedby`. |
| VI Cards | `Card` | Linked cards turn gold on hover with a tick scale along the top. `featured` adds the gold border and gilt corners; one per page. |
| VII Links | (base.css) | Body links are teal and always underlined. |
Shared: controls are 44px (36px compact), chips 26px, focus is a 2px gold
ring 3px out, disabled is 40% opacity.
## Ornaments
| Component | Use |
| --- | --- |
| `Star` | The four-point star. Gold, violet (only ever a star), teal, starlight or outline. |
| `StarPath` | Greg's star path line. `strength` calm, standard or wild; the same `seed` always draws the same path (it defaults to the page path). Two per page at most. |
| `Divider` | The header divider: gold line, large center star, star paths both sides. Header and footer only. |
| `HeroHorizon` | Gold hairline with a violet star, where a hero has no divider. |
| `TickScale` | Astrolabe ticks; with `value` it is a meter. |
| `TickRing` | A tick ring around a step number or small seal; `medallion` adds the disc and glow. |
| `SlotMeter` | Open order slots as stars over a tick meter. |
| `GiltCorners` | Corner brackets for the one featured panel per page. |
| `Seal`, `EdgeSeals` | A seal as an image; `EdgeSeals` places the page family's seal at the page edges at 6 to 7%. |
| `ConstellationDust` | Sparse static specks, about one in five gold. |
| `StarChartArt` | Placeholder art and the fallback for a missing image: star-chart grid, gold mat, a seal. |
| `Icon` | One of the 86 brand icons, in the current text color. |
Each page family's edge seal is in `src/components/seals.ts` (`pageSeals`):
landing uses transmutation star paths, resume the Kepler nest, work the
squared circle, and so on. A craft page passes its own craft seal.
## Page shell
`PageShell` is every page's frame: the head (title, description), dust and
edge seals, `SiteHeader` (nebula, filament banner, the primary nav with the My
world menu, an optional hero in the `hero` slot, the divider), the page
content, and `SiteFooter`. The nav entries live in `src/components/nav.ts`;
pass `current` to mark the page's entry.
```astro
---
import PageShell from "@gk/ui/components/PageShell.astro";
---
…
…
```
The site follows the device's light or dark setting until the visitor presses the sun and moon toggle in the header (`ThemeToggle`), which saves their choice in the browser. A script in PageShell's head sets `` or `"dark"` before the page paints; without script the site stays dark. Style light mode with `:root[data-theme="light"]` (in a component, `:global(:root[data-theme="light"]) .x`), not a `prefers-color-scheme` media query, so the toggle can override it. Colors come from the tokens in `tokens.css`, which has the light values too, so a component that uses `var(--gk-…)` needs nothing more. For a translucent color use a channel token, as in `rgba(var(--gk-gold-rgb), 0.35)`, never a hardcoded rgba. In SVG markup use `style="fill:var(--gk-gold)"`.
Motif images come in a light recolor and, for seals, a gold foil version for each mode. Show a motif with `Motif` (or `Seal`), which renders both files and shows the one for the current mode; a plain `
` stays dark. Pass `foil` only to a seal standing alone at 120px or more and half opacity or more. After changing a motif SVG, run `node packages/ui/scripts/light-motifs.mjs` to rewrite the `light/`, `foil/` and `foil-light/` versions.