@getvitops/generator 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +174 -0
- package/assets/bricks/elements/copy-button.php +3 -3
- package/assets/bricks/elements/multi-field.php +3 -3
- package/assets/css/animation.css +90 -0
- package/assets/css/global.css +10 -0
- package/assets/css/index.css +5 -0
- package/assets/css/layout-utilities.css +46 -0
- package/assets/css/layout.css +87 -2
- package/assets/css/patterns/anchor-link.css +36 -0
- package/assets/css/patterns/code.css +24 -0
- package/assets/css/patterns/details.css +28 -16
- package/assets/css/patterns/dialog.css +13 -31
- package/assets/css/patterns/drawer.css +27 -66
- package/assets/css/patterns/dropdown.css +15 -1
- package/assets/css/patterns/lightbox.css +3 -3
- package/assets/css/patterns/marquee.css +33 -5
- package/assets/css/patterns/nav.css +27 -79
- package/assets/css/patterns/navbar.css +86 -0
- package/assets/css/patterns/navshell.css +383 -0
- package/assets/css/patterns/popover.css +56 -8
- package/assets/css/patterns/scroll-target.css +18 -4
- package/assets/css/patterns/sitenav.css +117 -338
- package/assets/css/patterns/split-link.css +3 -3
- package/assets/js/elements.js +3 -3
- package/{site.schema.json → config.schema.json} +2300 -2283
- package/dist/index.d.mts +882 -415
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3284 -3095
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["providersSection"],"sources":["../src/shared.ts","../src/schema.ts","../src/tokens.ts","../src/docs.ts","../src/design-md.ts","../src/site.ts","../src/legal/providers.ts","../src/legal/derive.ts","../src/legal/render.ts","../src/legal/templates/shared.ts","../src/legal/templates/cookies.ca.ts","../src/legal/templates/privacy.ca.ts","../src/legal/templates/terms.ca.ts","../src/legal/templates/index.ts","../src/legal/index.ts","../src/icons-sprite.ts","../src/generate.ts","../src/index.ts"],"sourcesContent":["/**\n * Data shared between the generator (`generate.ts`) and the docs bundle\n * (`docs.ts`). Lives in its own module because `generate.ts` imports `docs.ts` —\n * importing back the other way would be a cycle.\n */\n\n/**\n * Selector the dark functional-token flip hangs off.\n *\n * `data-brx-theme` is Bricks' own attribute — Bricks sets it, so it's what the\n * WordPress target needs. Nothing sets it anywhere else, which meant the dark\n * flip was unreachable outside Bricks: the shipped `<color-scheme-toggle>` web\n * component writes `documentElement.dataset.theme` (i.e. `data-theme`), so\n * clicking \"Dark\" changed an attribute no rule matched. Matching both makes the\n * component work on every target without changing what Bricks already does.\n *\n * This covers the EXPLICIT choice. The OS preference is a second, opt-in block —\n * see `SYSTEM_DARK_SEL` — because turning it on flips a site dark for dark-OS\n * users, which is the site's decision rather than the design system's.\n *\n * Shared so the docs quote the selector the generator actually emits.\n */\nexport const DARK_SEL = ':root[data-brx-theme=\"dark\"], :root[data-theme=\"dark\"]';\n\n/**\n * Selector for the OS-preference dark block, emitted inside\n * `@media (prefers-color-scheme: dark)` when a site opts in.\n *\n * Derived from `DARK_SEL`'s attributes rather than written out a third time, and\n * inverted: this must apply when NO explicit choice has been made. That is\n * exactly what `<color-scheme-toggle>`'s \"System\" position produces — it removes\n * `data-theme` entirely — so with this block present System resolves to the OS\n * instead of silently falling through to light, and needs no JS to do it.\n *\n * The `:not()`s are what keep an explicit *light* choice winning over a dark OS.\n */\nexport const SYSTEM_DARK_SEL = `:root${DARK_SEL.split(', ')\n .map((s) => s.replace(/^:root\\[([\\w-]+)=\"dark\"\\]$/, '[$1=\"light\"]'))\n .map((attr) => `:not(${attr})`)\n .join('')}`;\n\n/**\n * Roles the shipped CSS partials reference with NO fallback, so a config that\n * omits one leaves those rules resolving to nothing — an invalid declaration,\n * not a graceful degrade.\n *\n * `colors.roles` is an open record: any name works and generates a full token\n * set, utilities and dark flip. But the framework's own component CSS is\n * written against these six, so \"roles are arbitrary\" is only half true — they\n * are *extensible*, over a required core. `validate()` warns when one is\n * missing; `required-roles.test.ts` re-derives this list from the partials so\n * it cannot drift as components are added.\n *\n * Kept as a constant rather than scanned at call time because `validate()` is\n * a pure function — the CLI, the Vite plugin and `toJSONSchema` all import it,\n * and none of them should touch the filesystem to answer \"is this config ok?\".\n */\nexport const REQUIRED_ROLES: readonly string[] = [\n 'brand-primary',\n 'danger',\n 'neutral',\n 'surface',\n 'ui-primary',\n 'warning',\n];\n\n/**\n * Every token key a role can resolve to, across both role kinds. Shared so the\n * required-roles drift test greps for exactly what the generator emits.\n *\n * These are *keys*, not var names: the role sits in the middle of the property\n * (`--color-bg-danger-muted`), so compose them with `tokenVar()` from `tokens.ts`\n * rather than concatenating by hand.\n */\nexport const ROLE_TOKEN_KEYS: readonly string[] = [\n // backgrounds — surface roles get the bare token and the full range,\n // chromatic roles get tints plus the solid family.\n 'bg',\n 'bg-muted',\n 'bg-x-muted',\n 'bg-bold',\n 'bg-x-bold',\n 'bg-solid',\n 'bg-solid-bold',\n 'bg-solid-x-bold',\n // foregrounds\n 'text',\n 'text-bold',\n 'text-muted',\n 'text-x-muted',\n 'text-xx-muted',\n 'text-on',\n 'text-on-bold',\n // non-text tiers\n 'icon',\n 'icon-muted',\n 'border',\n 'border-muted',\n 'border-bold',\n];\n\n/** How a role is authored in `colors.roles`: a bare hue, or a hue plus its kind. */\n// `kind` admits an explicit `undefined` because the repo runs\n// `exactOptionalPropertyTypes` and the zod-inferred config type spells optionals\n// that way — without it every call site would need a cast.\nexport type RoleSpec = string | { hue: string; kind?: 'surface' | 'chromatic' | undefined };\n\n/** The palette hue a role points at, through either authoring form. */\nexport const roleHue = (spec: RoleSpec): string => (typeof spec === 'string' ? spec : spec.hue);\n\n/**\n * A role's kind. The bare-string shorthand means `chromatic`, because signal\n * colours are the common case and surfaces are the two or three you name once.\n */\nexport const roleKind = (spec: RoleSpec): 'surface' | 'chromatic' =>\n typeof spec === 'string' ? 'chromatic' : (spec.kind ?? 'chromatic');\n\n/**\n * Pattern base geometry props → per-pattern override-hook shorthand. Each hook\n * wraps the authored value (`padding: var(--p-btn, 0.4em 0.8em)`) so a\n * consumer restyles one pattern by setting one variable. The hook is named after\n * the pattern's key, not its class.\n */\nexport const BASE_HOOK: Record<string, string> = {\n padding: 'p',\n 'border-radius': 'br',\n border: 'b',\n 'box-shadow': 'ds',\n 'font-size': 'fs',\n // Both spellings map to `bg`, because patterns author either (`card` uses the\n // shorthand, `status` the longhand). A pattern setting both would map the\n // same var twice — a config error, not something to design around.\n background: 'bg',\n 'background-color': 'bg',\n};\n\n/**\n * Framework utility classes whose names collide with Tailwind's own defaults.\n * The `tailwind` format strips any rule targeting these — Tailwind provides\n * them, so consumers use Tailwind's utilities for these names instead.\n */\nexport const TW_CLASH: ReadonlySet<string> = new Set<string>([\n 'block',\n 'inline',\n 'inline-block',\n 'flow-root',\n 'flex',\n 'inline-flex',\n 'grid',\n 'inline-grid',\n 'table',\n 'inline-table',\n 'table-caption',\n 'table-cell',\n 'table-row',\n 'contents',\n 'hidden',\n 'list-item',\n 'static',\n 'fixed',\n 'absolute',\n 'relative',\n 'sticky',\n 'isolate',\n 'visible',\n 'invisible',\n 'collapse',\n 'sr-only',\n 'not-sr-only',\n 'flex-row',\n 'flex-row-reverse',\n 'flex-col',\n 'flex-col-reverse',\n 'flex-wrap',\n 'flex-nowrap',\n 'items-start',\n 'items-end',\n 'items-center',\n 'items-baseline',\n 'items-stretch',\n 'justify-start',\n 'justify-end',\n 'justify-center',\n 'justify-between',\n 'justify-around',\n 'justify-evenly',\n 'content-start',\n 'content-end',\n 'content-center',\n 'content-between',\n 'content-around',\n 'content-evenly',\n 'text-left',\n 'text-center',\n 'text-right',\n 'text-justify',\n 'text-start',\n 'text-end',\n 'text-wrap',\n 'text-nowrap',\n 'text-balance',\n 'text-pretty',\n]);\n","/**\n * Canonical `design-system.json` schema — the single source of truth.\n *\n * Authored with `zod/mini` (tree-shakeable Zod v4). Everything else derives from it:\n * • the `DesignSystem` TS type (`z.infer`), used throughout the generator,\n * • the published JSON Schema (`toJSONSchema`), emitted to `schema.json` for `$schema` refs,\n * • runtime validation (`validate`) for the CLI and to gate `generate`,\n * • the generated `authoring.md` reference doc (walks `jsonSchema`'s descriptions).\n */\nimport * as z from 'zod/mini';\nimport { REQUIRED_ROLES, type RoleSpec, roleHue } from './shared.ts';\n\n/**\n * Attach a JSON-Schema `description`. zod/mini has no `.describe()` method; the\n * mini-API equivalent is `.check(z.describe(…))`, and `.check()` clones — so a\n * shared sub-schema (`Scale`, `CssDecls`, …) can carry a different description\n * per use-site without mutating the original.\n */\nexport const desc = <T extends { check(...checks: never[]): T }>(schema: T, text: string): T =>\n schema.check(z.describe(text) as never);\n\nconst CssDecls = desc(\n z.record(z.string(), z.string()),\n 'A CSS declaration block: property → value. Values stay strings (they can be hex, var(), clamp(), keywords, …); the generator, not the schema, interprets them.',\n);\nconst Scalar = z.union([z.string(), z.number()]);\nconst VarMap = z.record(z.string(), Scalar);\n\n// ── colors ──────────────────────────────────────────────────────────────────\nconst SeededRamp = desc(\n z.strictObject({\n seed: desc(\n z.string(),\n 'Seed colour (hex or oklch()). An 11-step numeric scale (50…950, tinted near-white → tinted near-black) is generated in OKLCH from it; the seed is preserved at its natural step.',\n ),\n anchors: z.optional(\n desc(\n z.record(z.string(), z.string()),\n 'Step → colour overrides (hex or oklch()) pinned VERBATIM at those steps. Every other step takes its lightness from the shared ladder, with chroma and hue interpolated between the anchors — so an anchor is reproduced exactly and is the only step allowed off the ladder. An explicit anchor overrides the seed at that step; two anchors that resolve to the same step are an error.',\n ),\n ),\n }),\n 'Seeded hue: the 11-step scale is GENERATED in OKLCH from `seed` (anchors pin specific steps).',\n);\nconst FixedRamp = desc(\n z.strictObject({\n tones: desc(\n z.union([z.array(z.string()), z.record(z.string(), z.string())]),\n 'Fixed brand kit: authored tones placed verbatim at their nearest steps plus tinted off-white/off-black endpoints; no interpolation. Either an ordered light → dark array or a step → colour map.',\n ),\n }),\n 'Fixed hue: authored brand tones used verbatim; no generation.',\n);\nconst Ramp = desc(\n z.union([SeededRamp, FixedRamp]),\n 'A palette hue, authored one of two ways: `{ seed, anchors? }` generates an 11-step numeric OKLCH scale (50…950) from the seed, or `{ tones }` supplies a fixed brand kit used verbatim.',\n);\n\n/**\n * A role points at a hue, and optionally declares its kind. The bare-string form\n * is the shorthand for a chromatic role — signal colours are the common case,\n * and the two or three surfaces are worth naming explicitly.\n */\nconst RoleSpecSchema = z.union([\n desc(z.string(), 'A palette hue name. Shorthand for `{ hue, kind: \"chromatic\" }`.'),\n z.strictObject({\n hue: desc(z.string(), 'The palette hue this role resolves to.'),\n kind: z.optional(\n desc(\n z.enum(['surface', 'chromatic']),\n '`surface` — a page/panel colour: gets a bare `bg-<role>` plus the full emphasis range and text scale. `chromatic` (default) — a signal colour: tints and solids only, no bare `bg-<role>`.',\n ),\n ),\n }),\n]);\n\nconst UtilityName = z.enum(['bg', 'text', 'icon', 'border', 'outline', 'fill', 'stroke']);\n\nconst Colors = desc(\n z.strictObject({\n palette: desc(\n z.record(z.string(), Ramp),\n 'Palette hues by name. Each becomes an 11-step numeric OKLCH scale (`--color-<hue>-50…950`). Every ramp shares one fixed lightness ladder, so a step means the same lightness in every hue; only chroma and hue vary. Beyond the outermost authored colour the chroma decays towards a small endpoint value (0.008 light / 0.015 dark) so the near-white and near-black ends keep a whisper of the hue — but that is a **ceiling**, not a target, so a low-chroma seed stays low and **a chroma-0 seed gives a true neutral** rather than a tinted one. The ladder is also enforced: if pinned colours leave a ramp non-monotonic (some step darker than the one below it), the build fails rather than shipping a scale whose hover states run backwards.',\n ),\n roles: desc(\n z.record(z.string(), RoleSpecSchema),\n `Maps semantic role names onto palette hues. Role names are ARBITRARY — add a key and the generator emits that role's token set (\\`--color-<target>-<role>[-<variant>]\\` for target bg/text/icon/border), its dark-mode flip and its utility classes.\\n\\nA value is either a hue name (\\`\"danger\": \"rust\"\\`) or \\`{ \"hue\": …, \"kind\": \"surface\" | \"chromatic\" }\\`. **The kind decides the shape of the token set.** \\`chromatic\\` (the default, and what the bare-string form means) is a signal colour: its backgrounds split into tints (\\`bg-<role>-x-muted\\`/\\`-muted\\`) and solids (\\`bg-<role>-solid[-bold|-x-bold]\\`), with deliberately **no bare \\`bg-<role>\\`** — \"how loud?\" is a question the author answers. \\`surface\\` is a page/panel colour: it has a bare \\`bg-<role>\\` plus the full emphasis range and text scale.\\n\\nDark mode flips automatically; there is no per-appearance scheme grammar. The solid family and its computed \\`text-on-<role>\\` foreground stay mode-stable so a filled button keeps its identity. Six roles are a required core, because the shipped framework CSS references them with no fallback: ${REQUIRED_ROLES.join(', ')}. Conventional additions are ui-secondary/accent, brand-secondary, info and success.`,\n ),\n utilities: z.optional(\n desc(\n z.array(UtilityName),\n 'Which colour utility-class families to emit (`bg-*`, `text-*`, `icon-*`, `border-*`, `outline-*`, `fill-*`, `stroke-*`). Defaults to bg, text, icon, border. `icon` is a separate non-text tier (a glyph may run more vivid than text); `outline`/`fill`/`stroke` have no tokens of their own and alias the border and icon tiers.',\n ),\n ),\n }),\n 'The colour system (the only required section): `palette` hues become generated OKLCH scales; `roles` map semantic roles onto those hues, from which all role tokens and dark mode derive.',\n);\n\n// ── fluid modular scale (type + space) ──────────────────────────────────────\nconst Scale = z.strictObject({\n base: desc(z.string(), 'Anchor size (a CSS length, e.g. \"1rem\") — the value at `baseStep`.'),\n ratio: desc(z.number(), 'Modular ratio between adjacent steps at large viewports.'),\n steps: desc(\n z.optional(z.number()),\n 'Token count when `names` is absent (steps are then named 1..steps).',\n ),\n names: desc(\n z.optional(z.array(z.string())),\n 'Step names, smallest → largest (e.g. [\"xs\",\"sm\",\"md\",…]); each becomes a token suffix.',\n ),\n baseStep: desc(z.optional(z.number()), '1-based index of the step whose value is `base`.'),\n baseline: desc(\n z.optional(z.string()),\n 'Named step used as the fluid pivot / GUI scale centre (defaults to `baseStep`).',\n ),\n fluid: desc(\n z.optional(\n z.strictObject({\n minVw: desc(z.string(), 'Viewport width (CSS length) where fluid scaling bottoms out.'),\n maxVw: desc(z.string(), 'Viewport width (CSS length) where fluid scaling tops out.'),\n minRatio: desc(z.number(), 'Modular ratio at/below `minVw` (usually < `ratio`).'),\n }),\n ),\n 'Makes the scale fluid: each step compiles to a clamp() that interpolates from `minRatio` at `minVw` to `ratio` at `maxVw`.',\n ),\n});\n\n// ── patterns ────────────────────────────────────────────────────────────────\nconst Pattern = desc(\n z.strictObject({\n group: desc(\n z.optional(z.string()),\n 'Token-cascade group this pattern belongs to (e.g. tag / control / panel); base declarations resolve through `--<prop>-<group>` before `--<prop>-default`.',\n ),\n overrides: z.optional(\n desc(CssDecls, 'Per-pattern token overrides, emitted as `--<prop>-<name>-group` values.'),\n ),\n element: desc(\n z.optional(z.string()),\n 'Style at element level via zero-specificity `:where(<element>)` (instead of, or alongside, a class).',\n ),\n class: desc(\n z.optional(z.string()),\n \"Class name to emit (defaults to the pattern's key when no `element` is set). Combined with `element`, the pattern emits one zero-specificity `:where(<element>, .<class>)` rule so the class works on any tag and any explicit class overrides it.\",\n ),\n fill: desc(\n z.optional(z.boolean()),\n 'Whether this pattern is colour-filled (states/roles drive `background-color` + `on-solid` text) or text-coloured (they drive `color`). Defaults to true when `base` declares a background.',\n ),\n default_role: desc(\n z.optional(z.string()),\n 'Semantic colour role applied to the bare/default variant.',\n ),\n base: z.optional(\n desc(\n CssDecls,\n 'Base CSS declarations. Geometry properties (padding, border-radius, border, box-shadow, font-size) are wrapped in per-pattern override hooks (`--p-<name>`, `--br-<name>`, `--b-<name>`, `--ds-<name>`, `--fs-<name>`) so consumers can restyle one pattern by setting one variable.',\n ),\n ),\n states: desc(\n z.optional(z.record(z.string(), z.record(z.string(), z.unknown()))),\n 'Interaction states (hover / active / focus-visible), each a map of shortcuts: `step` (intensify the fill or text by n rungs — `bg-<role>-solid` → `-solid-bold`, `text-<role>` → `-bold`), `scale` (transform scale), `lift` (translateY + shadow), `shadow` (a shadow name → drop-shadow(var(--shadow-<name>)), or true → lift shadow), `ring` (focus ring), or raw `css` declarations. Hover rules are wrapped in `@media (hover: hover)`.',\n ),\n roles: desc(\n z.optional(z.array(z.string())),\n 'Semantic colour role variants to emit as `<pattern>-<role>` classes (fills use the role solid / on-solid tokens).',\n ),\n }),\n 'One component pattern (button, link, badge, card, …): base declarations + interaction states + semantic role variants, resolved through the pattern token cascade.',\n);\n\nconst Patterns = desc(\n z.strictObject({\n defaults: z.optional(\n desc(CssDecls, 'Cascade-wide fallback tokens, emitted as `--<prop>-default`.'),\n ),\n radii: z.optional(\n desc(CssDecls, 'Shape primitives, emitted as `--br-<name>` (referenced by pattern bases).'),\n ),\n groups: desc(\n z.optional(z.record(z.string(), CssDecls)),\n 'Group-level tokens, emitted as `--<prop>-<group>`; patterns opt in via their `group` key.',\n ),\n z: desc(z.optional(z.record(z.string(), z.number())), 'Z-index tiers → `--z-tier-<name>`.'),\n items: desc(\n z.optional(z.record(z.string(), Pattern)),\n 'The component patterns to emit, keyed by name.',\n ),\n }),\n 'Component patterns and their token cascade: `defaults` → `groups` → per-pattern `overrides`, plus shape (`radii`) and z-index primitives.',\n);\n\n// ── typography ──────────────────────────────────────────────────────────────\nconst TypographyRole = desc(\n z.record(z.string(), Scalar),\n 'A bag of CSS-ish keys, each mapped to a declaration plus a `--<role>-<sfx>` override hook. The recognised set is **closed**: `family`, `size`, `weight`, `style`, `line-height`, `tracking` (→ `letter-spacing`), `text-transform`, `text-decoration`, `text-wrap`, `color`. Note the last four are spelled with their full CSS property names — `transform` and `decoration` are NOT accepted. Anything unrecognised is **ignored**, not passed through, so the generator warns rather than emitting it: a silently-dropped `transform: uppercase` is how title-case navigation reaches production. Note also that `style`, `text-transform`, `text-decoration` and `text-wrap` are emitted on **every** role at their identity value (`normal`/`none`/`none`/`wrap`) whether declared or not, so applying one role class over another fully resets it — which means **omitting `text-wrap` is not \"inherit\"**: it emits `text-wrap: wrap` and cancels the `pretty` the role would otherwise inherit from a `pretty` ancestor such as a `body`-mapped role. Declare it on every role — `balance` for heading-like roles, `pretty` for copy, `wrap` for short single-line labels.',\n);\nconst Typography = desc(\n z.strictObject({\n families: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Role-facing family aliases → CSS font values, usually referencing the top-level `fonts` tokens (e.g. \"var(--font-display)\").',\n ),\n roles: desc(\n z.optional(z.record(z.string(), TypographyRole)),\n 'Semantic type roles (display, title, heading, body, quote, caption, eyebrow, code, lead, footnote, tag, …), each emitted as a `font-<role>` class.',\n ),\n headings: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Maps bare elements to type roles so unclassed markup picks up role styling — `{ \"h1\": \"display\", \"h2\": \"heading\" }`. The key is used verbatim as a selector, so it is not limited to h1…h6: **map `\"body\"` to your prose role** to bind base page typography to the role rather than hand-writing it. That binding is what makes the role editable — a stylesheet that re-states `font-family`/`line-height` as literals on `body` shadows `--<role>-ff`/`--<role>-lh`, and the live theme editor then appears to do nothing.',\n ),\n }),\n 'Typography: family aliases, semantic type roles (→ `font-<role>` classes), and the bare-element → role mapping.',\n);\n\n// ── animations ──────────────────────────────────────────────────────────────\nconst AnimEffect = desc(\n z.strictObject({\n kf: desc(\n z.string(),\n 'Keyframe family driving the effect: composite (transform/opacity), paint, or layout.',\n ),\n css: z.optional(desc(VarMap, 'Extra literal declarations merged into the effect class as-is.')),\n vars: z.optional(\n desc(\n VarMap,\n 'Effect endpoint variables (`--<key>: <value>`, e.g. opacity-from, translate-y-to) that override the keyframe defaults.',\n ),\n ),\n }),\n 'A named animation effect class — a pure value layer (`--_anim` + `--<prop>-from/-to`) over the static keyframe engine.',\n);\nconst Animations = desc(\n z.strictObject({\n effects: desc(\n z.optional(z.record(z.string(), AnimEffect)),\n 'Effect classes to emit (`.fade-in`, `.reveal-left`, …), keyed by class name.',\n ),\n journeys: desc(\n z.optional(\n z.strictObject({\n base: desc(\n z.optional(z.record(z.string(), VarMap)),\n 'Named journey building blocks: part name → var map.',\n ),\n compose: desc(\n z.optional(z.array(z.array(z.string()))),\n 'Combinations of base parts, each emitted as a `.<parts>-journey` class.',\n ),\n }),\n ),\n 'Multi-part journey classes composed from `base` building blocks.',\n ),\n }),\n 'Animation effect + journey classes (pure value layers). The animation engine itself — keyframes, drivers, floats, utilities — is static framework CSS, not configured here.',\n);\n\n// ── the design system ───────────────────────────────────────────────────────\nexport const DesignSystemSchema = z.strictObject({\n $schema: desc(\n z.optional(z.string()),\n 'URL of the published JSON Schema (stamped by `vitops init`) so editors provide autocomplete + validation.',\n ),\n meta: desc(\n z.optional(\n z.strictObject({\n name: desc(\n z.optional(z.string()),\n 'Brand/system name. Used as the `name` field and `<h1>` of the `design` format\\'s `DESIGN.md`. Defaults to \"Design System\".',\n ),\n description: desc(\n z.optional(z.string()),\n \"One or two sentences on the brand personality and the feeling the UI should evoke — what an agent needs when no token answers the question. Becomes the DESIGN.md `description` field and opens its Overview section; if omitted, a generic description of the system's mechanics is used instead.\",\n ),\n }),\n ),\n 'Brand identity for agent-facing output. Consumed only by the `design` format (`DESIGN.md`); it emits no CSS and no tokens.',\n ),\n colors: Colors,\n shadows: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Named shadows → `--shadow-<name>` tokens and `.drop-shadow-<name>` utilities. Values are shadow parameter lists (offset/blur/colour). Each token feeds two consumers with different grammars — `box-shadow` (pattern geometry, via the `--ds-*` group aliases) and `filter: drop-shadow(…)` (the utilities and the `shadow:` state shortcut) — so values must stay in the intersection: **one layer, no spread radius, no `inset`**. `drop-shadow()` rejects all three, and rejecting them invalidates the whole filter, so the shadow vanishes rather than degrading.',\n ),\n fonts: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Raw font stacks by name, emitted as `--font-<name>` tokens (referenced by `typography.families`). **Stacks only — vitops does not load webfonts.** A value here is a `font-family` list and nothing more: it emits no `@font-face`, no preload, and no metrics-matched fallback. If a family needs loading, declare it in Astro\\'s `fonts:` config (`astro.config`, or the site config\\'s `fonts` array) and point the token at the family\\'s `cssVariable` — `\"display\": \"var(--font-league-spartan), sans-serif\"`. Installing a `@fontsource*` package and importing its CSS also works but gives up subsetting, preload and `size-adjust`/`ascent-override` fallbacks, so it regresses CLS.',\n ),\n typeScale: desc(\n z.optional(Scale),\n 'Fluid modular TYPE scale → `--text-<name>` tokens, consumed by typography roles and text-size utilities.',\n ),\n spaceScale: desc(\n z.optional(Scale),\n 'Fluid modular SPACE scale → `--space-<name>` tokens, consumed by spacing/gap utilities and vertical rhythm.',\n ),\n patterns: z.optional(Patterns),\n typography: z.optional(Typography),\n animations: z.optional(Animations),\n});\n\nexport type DesignSystem = z.infer<typeof DesignSystemSchema>;\n\n// A deep-partial view used for theme deltas: an `extends` patch supplies only\n// what it overrides, so every field is optional — including one level down\n// through `colors` into palette / roles / utilities. Reuses the same leaf\n// schemas, so there's no second source of truth. Completeness is enforced after\n// merge (validate the resolved theme against `DesignSystemSchema`).\n//\n// Note this is NOT a per-appearance grammar. Light/dark is derived inside a\n// single design system by re-pointing which ramp step each token reads; the old\n// `schemes` layer this comment used to describe was removed with that redesign.\nconst ColorsPatch = z.strictObject({\n palette: z.optional(z.record(z.string(), Ramp)),\n roles: z.optional(z.record(z.string(), RoleSpecSchema)),\n utilities: z.optional(z.array(UtilityName)),\n});\nexport const DesignSystemPatchSchema = z.extend(z.partial(DesignSystemSchema), {\n colors: z.optional(ColorsPatch),\n});\nexport type DesignSystemPatch = z.infer<typeof DesignSystemPatchSchema>;\n\n/**\n * Stable URL of the published JSON Schema. Resolves once `@getvitops/generator` is on\n * npm (unpkg serves the packaged `schema.json`); `vitops init` stamps this into a\n * scaffolded config's `$schema` so editors light up autocomplete + validation.\n */\nexport const SCHEMA_URL = 'https://unpkg.com/@getvitops/generator/schema.json';\n\n/** The published JSON Schema (draft-2020-12), derived from the zod schema. */\nexport const jsonSchema = {\n $id: SCHEMA_URL,\n ...z.toJSONSchema(DesignSystemSchema, { target: 'draft-2020-12' }),\n};\n\n/** Split a CSS value on top-level commas, ignoring commas nested in `rgba(…)` etc. */\nconst splitLayers = (value: string): string[] => {\n const out: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < value.length; i++) {\n const c = value[i];\n if (c === '(') depth++;\n else if (c === ')') depth--;\n else if (c === ',' && depth === 0) {\n out.push(value.slice(start, i));\n start = i + 1;\n }\n }\n out.push(value.slice(start));\n return out.map((s) => s.trim()).filter(Boolean);\n};\n\nconst LENGTH = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(px|rem|em|ch|ex|vh|vw|vmin|vmax|cm|mm|in|pt|pc|q)?$/i;\n\n/**\n * Why a shadow can be *valid CSS* and still render nothing: a `--shadow-<name>`\n * token is consumed both as a `box-shadow` (pattern geometry) and inside\n * `filter: drop-shadow(…)` (the `.drop-shadow-<name>` utilities, the `shadow:`\n * state shortcut). `drop-shadow()` accepts a *single* layer of at most three\n * lengths and no `inset` — a spread radius, a second comma-separated layer or an\n * inset keyword makes the function invalid, which drops the entire `filter`\n * declaration. `box-shadow` accepts all three happily, so the value looks fine\n * everywhere it is authored and only the utility silently goes blank.\n */\nconst dropShadowIssue = (value: string): string | undefined => {\n const layers = splitLayers(value);\n if (layers.length > 1) return `${layers.length} comma-separated layers`;\n const layer = layers[0] ?? '';\n if (/(^|\\s)inset(\\s|$)/i.test(layer)) return 'an `inset` keyword';\n // Drop function calls (`rgb(0 0 0 / .5)`, `color-mix(…)`) so their numbers\n // aren't miscounted as lengths, then count what's left.\n const lengths = layer\n .replaceAll(/[\\w-]*\\([^()]*\\)/g, ' ')\n .split(/\\s+/)\n .filter((t) => LENGTH.test(t));\n if (lengths.length > 3) return `a spread radius (${lengths.length} lengths)`;\n return undefined;\n};\n\nexport type ValidationResult =\n | { ok: true; data: DesignSystem; errors: []; warnings: string[] }\n | { ok: false; data: undefined; errors: z.core.$ZodIssue[]; warnings: string[] };\n\nconst RAMP_KEYS = new Set(['seed', 'anchors', 'tones']);\n\n/**\n * Replace the bare \"Invalid input\" a failed union produces with the reason.\n *\n * `Ramp` is `SeededRamp | FixedRamp`, and both branches are closed — so `{ seed,\n * tones }` or a stray key fails *both* and zod reports only that the union didn't\n * match. That message sends you reading the schema rather than looking at the two\n * keys in front of you, and the config that produced it is one whose `tones` were\n * being silently discarded at generate time.\n */\nconst explainRamp =\n (input: unknown) =>\n (issue: z.core.$ZodIssue): z.core.$ZodIssue => {\n // A closed object reports the offending keys on the issue but renders them as\n // a bare \"Invalid input\", which names the parent and not the typo.\n if (issue.code === 'unrecognized_keys') {\n const keys = (issue as { keys?: string[] }).keys ?? [];\n if (keys.length)\n return {\n ...issue,\n message: `unknown key${keys.length > 1 ? 's' : ''} ${keys.map((k) => `\"${k}\"`).join(', ')} — not part of the schema, so ignored at generate time.`,\n };\n }\n if (issue.path.length !== 3 || issue.path[0] !== 'colors' || issue.path[1] !== 'palette')\n return issue;\n const hue = (input as { colors?: { palette?: Record<string, unknown> } })?.colors?.palette?.[\n String(issue.path[2])\n ];\n if (hue == null || typeof hue !== 'object') return issue;\n const keys = Object.keys(hue);\n const unknown = keys.filter((k) => !RAMP_KEYS.has(k));\n const message =\n 'seed' in hue && 'tones' in hue\n ? 'a hue is either seeded (`seed`, with optional `anchors`) or fixed (`tones`) — not both. ' +\n 'Drop one: with both present the `tones` are ignored at generate time.'\n : unknown.length\n ? `unknown key${unknown.length > 1 ? 's' : ''} ${unknown.map((k) => `\"${k}\"`).join(', ')}. ` +\n 'A hue takes `seed` + optional `anchors`, or `tones`.'\n : keys.length === 0\n ? 'a hue needs `seed` (+ optional `anchors`) or `tones`.'\n : null;\n return message ? { ...issue, message } : issue;\n };\n\n/**\n * Validate an unknown value against the design-system schema.\n *\n * `warnings` are configurations that parse and generate, but produce output that\n * won't behave as authored — currently only the token-namespace collisions the\n * flat `--<prop>-<name>` grammar makes possible.\n */\nexport function validate(input: unknown): ValidationResult {\n const result = z.safeParse(DesignSystemSchema, input);\n if (!result.success)\n return {\n ok: false,\n data: undefined,\n errors: result.error.issues.map(explainRamp(input)),\n warnings: [],\n };\n // Every role must point at a palette hue that exists.\n const { palette, roles } = result.data.colors;\n for (const [role, spec] of Object.entries(roles)) {\n const hue = roleHue(spec as RoleSpec);\n if (palette[hue] == null) {\n return {\n ok: false,\n data: undefined,\n errors: [\n {\n code: 'custom',\n path: ['colors', 'roles', role],\n message: `role \"${role}\" references unknown palette hue \"${hue}\"`,\n } as z.core.$ZodIssue,\n ],\n warnings: [],\n };\n }\n }\n const warnings: string[] = [];\n // Role names are arbitrary — but the shipped component CSS is written against\n // a core set, and references them with no fallback. Omitting one doesn't fail\n // validation (the tokens for the roles you DO define are all emitted fine); it\n // silently strips colour from whichever components depended on it, which is\n // far harder to diagnose than a warning here.\n const missing = REQUIRED_ROLES.filter((r) => roles[r] == null);\n if (missing.length)\n warnings.push(\n `colors.roles is missing ${missing.map((r) => `\"${r}\"`).join(', ')} — ` +\n `the framework's own component CSS references ${missing.length === 1 ? 'it' : 'them'} ` +\n `with no fallback, so those components will render uncoloured. ` +\n `Add any role you like, but keep these defined.`,\n );\n // A radius named after a pattern collides on `--br-<name>`: the radius token and\n // the pattern's own override hook are the same var, so whichever the generator\n // emits last silently wins. Same class of clash as a pattern keyed like its\n // group (see the `tag`/`label` note in AGENTS.md). The pattern hook takes it.\n const radii = Object.keys(result.data.patterns?.radii ?? {});\n const items = new Set(Object.keys(result.data.patterns?.items ?? {}));\n for (const name of radii)\n if (items.has(name))\n warnings.push(\n `patterns.radii.${name} collides with the \"${name}\" pattern on --br-${name}; ` +\n `the pattern's override hook wins — rename the radius`,\n );\n for (const [name, value] of Object.entries(result.data.shadows ?? {})) {\n const issue = dropShadowIssue(value);\n if (issue)\n warnings.push(\n `shadows.${name} carries ${issue}, which \\`filter: drop-shadow()\\` rejects — ` +\n `\\`.drop-shadow-${name}\\` will render no shadow at all (the token still works ` +\n `as a \\`box-shadow\\`). Use one layer of at most three lengths.`,\n );\n }\n return { ok: true, data: result.data, errors: [], warnings };\n}\n","/**\n * Palette expansion + semantic colour tokens.\n *\n * A palette hue is authored one of two ways:\n * • `{ seed, anchors? }` — an 11-step numeric scale (50…950) generated in\n * OKLCH via @getvitops/utils/color. Lightness comes from the shared\n * `LIGHTNESS_LADDER`; the seed (and any anchors) are reproduced verbatim at\n * their steps.\n * • `{ tones }` — a fixed brand kit: authored tones placed verbatim at their\n * nearest steps + tinted endpoints; nothing else is invented (strict kits).\n *\n * **The grammar.** Every role gets tokens named `--color-<target>-<role>[-<variant>]`,\n * where target ∈ bg | text | icon | border. Putting the target *inside* the name is\n * the point: `--color-bg-danger-muted` and `--color-text-danger-muted` are distinct\n * tokens, so the two axes that used to collide over one `<family>-<role>-<modifier>\n * ` namespace cannot any more. The utility class is the token name minus `--color-`.\n *\n * Variants are ordinal — xx-muted < x-muted < muted < (bare) < bold < x-bold —\n * and the tables are **sparse**: a target only emits the cells that are actually\n * viable. `bold` means \"more emphatic than the role's default in the current\n * appearance\", not \"darker\"; the appearance decides polarity.\n *\n * Roles come in two kinds (declared in `colors.roles`):\n * • `surface` — a page/panel colour. Has a bare `bg-<role>` plus the full\n * emphasis range and the complete text scale.\n * • `chromatic` (default) — a signal colour. Backgrounds split into *tints*\n * (`bg-<role>-x-muted` / `-muted`) and *solids* (`bg-<role>-solid[-bold|-x-bold]`);\n * there is deliberately **no bare `bg-<role>`**, because \"how loud?\" is a\n * question the author has to answer.\n *\n * Dark mode re-points which step each token reads; the solid family and the\n * `text-on-<role>` foreground computed against it stay mode-stable, so a filled\n * button keeps its identity across appearances.\n */\nimport {\n LIGHTNESS_LADDER,\n contrastLc,\n generateOklchPalette,\n hexToOklch,\n oklchStringToHex,\n pickOn,\n tintedEndpoints,\n} from '@getvitops/utils/color';\n\nexport const NUMERIC_STEPS = [\n '50',\n '100',\n '200',\n '300',\n '400',\n '500',\n '600',\n '700',\n '800',\n '900',\n '950',\n] as const;\ntype NumStep = (typeof NUMERIC_STEPS)[number];\n\n/**\n * Lightness of each numeric step. Re-exported from the engine's ladder rather\n * than restated — there used to be three copies of this curve (here, the engine,\n * and the linter) and they were free to drift.\n */\nconst STEP_L = Object.fromEntries(\n NUMERIC_STEPS.map((s) => [s, LIGHTNESS_LADDER[Number(s) as keyof typeof LIGHTNESS_LADDER]]),\n) as Record<NumStep, number>;\n\nexport interface ExpandedHue {\n /** Numeric steps (sparse for fixed-tone kits). */\n numeric: Partial<Record<NumStep, string>>;\n /** True when only authored tones + endpoints exist (no interpolation). */\n sparse?: boolean;\n /**\n * Steps the author pinned, and how far each sits from the ladder's lightness.\n * A pinned colour is reproduced exactly, so a large value here is legal — but\n * it means this hue reads heavier or lighter than its siblings at that step,\n * which the generator surfaces as a warning.\n */\n deviations?: Partial<Record<NumStep, number>>;\n}\n\ninterface SeedInput {\n seed: string;\n anchors?: Record<string, string>;\n}\ninterface TonesInput {\n tones: string[] | Record<string, string>;\n}\n\nconst isHex = (v: string) => v.startsWith('#');\nconst toOklchStr = (v: string) => {\n if (!isHex(v)) return v; // already oklch(...)\n const { l, c, h } = hexToOklch(v);\n return `oklch(${(l * 100).toFixed(2)}% ${c.toFixed(4)} ${h.toFixed(2)})`;\n};\nconst nearestStep = (l: number): NumStep =>\n NUMERIC_STEPS.reduce((best, s) =>\n Math.abs(l - STEP_L[s]) < Math.abs(l - STEP_L[best]) ? s : best,\n );\n\n/**\n * Claim `step` for `value`, refusing to overwrite a step another colour already\n * took.\n *\n * Silently dropping one of two colliding tones is the worst outcome: the palette\n * still builds, and the tone the author cared about is simply gone. The record\n * form (`tones: { \"600\": \"#…\", \"700\": \"#…\" }`) is the escape hatch, so the error\n * points at it.\n */\nfunction claim(\n into: Record<string, string>,\n step: string,\n value: string,\n hueLabel: string,\n what: string,\n): void {\n const taken = into[step];\n if (taken != null && taken !== value) {\n throw new Error(\n `palette hue \"${hueLabel}\": ${what} ${value} and ${taken} both map to step ${step}. ` +\n `Key them explicitly, e.g. { \"${step}\": \"${taken}\", \"${Number(step) + 100}\": \"${value}\" }.`,\n );\n }\n into[step] = value;\n}\n\nfunction expandSeeded(input: SeedInput, hueLabel: string): ExpandedHue {\n // The seed and any author anchors pin verbatim at their natural (or explicit)\n // steps; the engine fills every other step from the shared lightness ladder,\n // fading chroma toward the tinted ends. No implicit 50/950 anchors any more —\n // the ladder already defines the endpoints, and pinning them would override it.\n // Author anchors are placed FIRST and may collide only with each other. The\n // seed goes in afterwards, and only where an anchor hasn't already claimed the\n // step: an explicit anchor is the author overriding that step, which is exactly\n // what the live editor writes when you recolour a swatch. Treating that as a\n // collision would break the editor's save path.\n const anchors: Record<string, string> = {};\n for (const [key, value] of Object.entries(input.anchors ?? {})) {\n const step = (NUMERIC_STEPS as readonly string[]).includes(key)\n ? key\n : nearestStep(hexToOklch(value).l);\n claim(anchors, step, toOklchStr(value), hueLabel, 'anchors');\n }\n const seedStep = nearestStep(hexToOklch(input.seed).l);\n anchors[seedStep] ??= toOklchStr(input.seed);\n const scale = generateOklchPalette(anchors) as Record<string, string>;\n const numeric: Partial<Record<NumStep, string>> = {};\n for (const s of NUMERIC_STEPS) if (scale[s] != null) numeric[s] = oklchStringToHex(scale[s]);\n return { numeric, deviations: deviationsFor(anchors) };\n}\n\nfunction expandTones(input: TonesInput, hueLabel: string): ExpandedHue {\n // Strict kit: authored tones verbatim at their nearest step; add tinted\n // endpoints (the one allowed exception); interpolate nothing else.\n const entries: Array<[string | null, string]> = Array.isArray(input.tones)\n ? input.tones.map((hex) => [null, hex])\n : Object.entries(input.tones).map(([k, hex]) => [k, hex]);\n\n const placed: Record<string, string> = {};\n for (const [key, hex] of entries) {\n const step =\n key != null && (NUMERIC_STEPS as readonly string[]).includes(key)\n ? key\n : nearestStep(hexToOklch(hex).l);\n claim(placed, step, hex, hueLabel, 'tones');\n }\n\n const numeric: Partial<Record<NumStep, string>> = {};\n for (const [step, hex] of Object.entries(placed)) numeric[step as NumStep] = hex;\n\n const firstTone = entries[0]?.[1] ?? '#808080';\n const ends = tintedEndpoints(hexToOklch(firstTone).h);\n numeric['50'] ??= ends.light;\n numeric['950'] ??= ends.dark;\n\n return { numeric, sparse: true, deviations: deviationsFor(placed) };\n}\n\n/** How far each pinned colour sits from its step's ladder lightness. */\nfunction deviationsFor(pinned: Record<string, string>): Partial<Record<NumStep, number>> {\n const out: Partial<Record<NumStep, number>> = {};\n for (const [step, value] of Object.entries(pinned)) {\n const l = isHex(value) ? hexToOklch(value).l : hexToOklch(oklchStringToHex(value)).l;\n out[step as NumStep] = l - STEP_L[step as NumStep];\n }\n return out;\n}\n\n/** Snap to the nearest AVAILABLE numeric step (sparse kits). */\nfunction snap(numeric: Partial<Record<NumStep, string>>, want: NumStep): NumStep {\n if (numeric[want] != null) return want;\n const have = NUMERIC_STEPS.filter((s) => numeric[s] != null);\n return have.reduce((best, s) =>\n Math.abs(STEP_L[s] - STEP_L[want]) < Math.abs(STEP_L[best] - STEP_L[want]) ? s : best,\n );\n}\n\n/** Expand every palette hue into its numeric scale. */\nexport function expandPalette(raw: Record<string, unknown>): Record<string, ExpandedHue> {\n const out: Record<string, ExpandedHue> = {};\n for (const [name, entry] of Object.entries(raw)) {\n const e = entry as Partial<SeedInput & TonesInput>;\n if (typeof e?.seed === 'string') out[name] = expandSeeded(e as SeedInput, name);\n else if (e?.tones != null) out[name] = expandTones(e as TonesInput, name);\n else throw new Error(`palette hue \"${name}\" must have a \"seed\" or \"tones\"`);\n }\n return out;\n}\n\n/**\n * Warn about pinned colours that sit noticeably off the ladder. Not an error:\n * the author asked for that exact colour and gets it. But at ~0.03 L the hue\n * starts reading visibly heavier or lighter than its siblings at that step, and\n * that is the class of drift the fixed ladder exists to prevent.\n */\nexport const LADDER_TOLERANCE = 0.03;\n\nexport function ladderWarnings(palette: Record<string, ExpandedHue>): string[] {\n const warnings: string[] = [];\n for (const [hue, expanded] of Object.entries(palette)) {\n for (const [step, deviation] of Object.entries(expanded.deviations ?? {})) {\n if (Math.abs(deviation as number) <= LADDER_TOLERANCE) continue;\n const dir = (deviation as number) > 0 ? 'lighter' : 'darker';\n warnings.push(\n `colors.palette.${hue}: the colour pinned at step ${step} is ${Math.abs(\n deviation as number,\n ).toFixed(3)} ${dir} than the shared lightness ladder — this hue will read ` +\n `${dir} than others at ${step}. Legal, but move it to a neighbouring step if that wasn't intended.`,\n );\n }\n }\n return warnings;\n}\n\n/**\n * Gamut mapping nudges lightness by a hair, so an exact `<` comparison would\n * report rounding as an inversion. Well below any deviation a person could see.\n */\nconst MONOTONIC_EPSILON = 1e-3;\n\n/**\n * Ramps whose lightness does not fall monotonically from 50 to 950.\n *\n * A ramp built from the ladder alone cannot invert — only pinned colours (a seed,\n * an `anchor`, a `tones` entry) can, because they are the one thing allowed off\n * it. `ladderWarnings` will not catch it: it compares each pinned step against\n * *its own* ladder rung, never against its neighbours, so it reports the wrong\n * defect (\"reads darker than others at 600\") while the real problem is that 600\n * is darker than 700. And since `LADDER_TOLERANCE` is 0.03 — the same size as the\n * ladder's own 50→100 gap — two anchors can each sit within tolerance and still\n * invert, with no warning at all.\n *\n * This is an error rather than a warning because the rest of the system assumes\n * the order: `snap` picks the nearest step by ladder lightness, the mode-stable\n * solid family hard-codes 600/700/800 as increasingly dark, and both dark tables\n * re-point steps on the same assumption. An inverted ramp therefore runs hover\n * states backwards — the failure the fixed ladder was introduced to eliminate.\n */\nexport function monotonicityErrors(palette: Record<string, ExpandedHue>): string[] {\n const errors: string[] = [];\n for (const [hue, expanded] of Object.entries(palette)) {\n const numeric = expanded.numeric ?? {};\n // Present steps only — a sparse `tones` kit is legal, and comparing against\n // absent steps would invent inversions that aren't there.\n const steps = NUMERIC_STEPS.filter((s) => numeric[s] != null);\n for (let i = 1; i < steps.length; i++) {\n const [prev, step] = [steps[i - 1] as NumStep, steps[i] as NumStep];\n // The final hex, not the nominal ladder value: a pinned colour is emitted\n // verbatim, and it is precisely the pinned steps that can invert.\n const lPrev = hexToOklch(numeric[prev] as string).l;\n const lStep = hexToOklch(numeric[step] as string).l;\n if (lStep < lPrev + MONOTONIC_EPSILON) continue;\n // Point at the colour the author actually wrote. Only a pinned step can be\n // off the ladder, so naming its correct home is the actionable half — the\n // unpinned neighbour is already exactly where it belongs, and telling\n // someone to move that one sends them the wrong way.\n const pinned = expanded.deviations ?? {};\n const culprits = ([prev, step] as NumStep[]).filter((s) => pinned[s] != null);\n const fix = culprits.length\n ? culprits\n .map((s) => {\n const l = hexToOklch(numeric[s] as string).l;\n return `${numeric[s]} (pinned at ${s}) sits at L ${l.toFixed(3)}, nearest step ${nearestStep(l)}`;\n })\n .join('; ')\n : `no step here is pinned, so this is a bug in the generator rather than in your config`;\n errors.push(\n `colors.palette.${hue}: step ${step} (${numeric[step]}, L ${lStep.toFixed(3)}) is LIGHTER ` +\n `than step ${prev} (${numeric[prev]}, L ${lPrev.toFixed(3)}). A ramp must darken from 50 ` +\n `to 950 — inverted, a hover from \\`bg-<role>-solid\\` to \\`-solid-bold\\` gets lighter, and ` +\n `the dark-mode tables re-point steps assuming the order. ${fix}.`,\n );\n }\n }\n return errors;\n}\n\n// ── the token tables ─────────────────────────────────────────────────────────\n\n/** Which shape of token set a role gets. */\nexport type RoleKind = 'surface' | 'chromatic';\n\n/** Token key → numeric step. Keys are `<target>[-<variant>]`; see `tokenVar`. */\ntype Table = Record<string, NumStep>;\n\n/**\n * Surface roles: a bare `bg` (cards, panels, inputs), `bg-muted` for the page\n * behind them, `bg-x-muted` for wells, and `bg-bold`/`-x-bold` for the inverse\n * surface a tooltip sits on. Elevation is expressed by *which* token you reach\n * for — page `bg-muted`, card `bg` — rather than by a raised/sunken pair. That\n * is what lets a future `data-surfaces` axis flatten it without touching markup.\n */\nconst SURFACE_LIGHT: Table = {\n bg: '50',\n 'bg-muted': '100',\n 'bg-x-muted': '200',\n 'bg-bold': '800',\n 'bg-x-bold': '950',\n text: '900',\n 'text-bold': '950',\n 'text-muted': '700',\n 'text-x-muted': '500',\n 'text-xx-muted': '400',\n 'text-on-bold': '50',\n icon: '600',\n 'icon-muted': '500',\n 'border-muted': '200',\n border: '300',\n 'border-bold': '600',\n};\nconst SURFACE_DARK: Table = {\n bg: '900',\n 'bg-muted': '950',\n 'bg-x-muted': '950',\n 'bg-bold': '200',\n 'bg-x-bold': '50',\n text: '100',\n 'text-bold': '50',\n // 300 and 400, not v3.1's 400 and 500: those were tuned against WCAG and come\n // up short of APCA's secondary-text and non-text bars over a dark surface.\n 'text-muted': '300',\n 'text-x-muted': '500',\n 'text-xx-muted': '600',\n 'text-on-bold': '950',\n icon: '400',\n 'icon-muted': '500',\n 'border-muted': '800',\n border: '700',\n 'border-bold': '400',\n};\n\n/**\n * Chromatic roles: tints for alert/badge backgrounds, solids for fills. No bare\n * `bg` — see the module docblock. No `text-muted` either: a de-emphasised\n * coloured text could not hold its contrast target off a white surface, so the\n * way to soften coloured text is weight/size, not another colour.\n */\nconst CHROMATIC_LIGHT: Table = {\n 'bg-x-muted': '50',\n 'bg-muted': '100',\n text: '700',\n 'text-bold': '900',\n icon: '600',\n border: '200',\n 'border-bold': '300',\n};\nconst CHROMATIC_DARK: Table = {\n 'bg-x-muted': '950',\n 'bg-muted': '900',\n text: '300',\n 'text-bold': '200',\n icon: '400',\n border: '800',\n 'border-bold': '700',\n};\n\n/**\n * The solid family — mode-stable, so a filled button keeps its identity when the\n * appearance flips. Fixed steps rather than the old scan-and-clamp: with a shared\n * lightness ladder every hue's 600 already sits at the same lightness, so there\n * is nothing left to search for. `text-on-<role>` is computed against `bg-solid`.\n */\nconst SOLID: Table = { 'bg-solid': '600', 'bg-solid-bold': '700', 'bg-solid-x-bold': '800' };\n\n/**\n * Map a token key to its CSS custom property for a given role.\n *\n * `on` is the one irregular case: the foreground for a filled surface reads\n * `--color-text-on-<role>`, with the role *after* `on`, because it names what it\n * sits on rather than what it is.\n *\n * The utility class name is this minus the `--color-` prefix, which is why the\n * emitter and the linter can both derive their vocabulary from one function.\n */\nexport function tokenVar(role: string, key: string): string {\n const dash = key.indexOf('-');\n const target = dash === -1 ? key : key.slice(0, dash);\n const variant = dash === -1 ? '' : key.slice(dash + 1);\n if (variant === 'on') return `--color-${target}-on-${role}`;\n if (variant.startsWith('on-')) return `--color-${target}-on-${role}-${variant.slice(3)}`;\n return variant ? `--color-${target}-${role}-${variant}` : `--color-${target}-${role}`;\n}\n\n/** The class name a token key produces for a role (`bg-danger-solid`, …). */\nexport const tokenClass = (role: string, key: string): string =>\n tokenVar(role, key).slice('--color-'.length);\n\nexport interface FunctionalRole {\n role: string;\n hue: string;\n kind: RoleKind;\n /** token key → CSS value, per appearance. */\n light: Record<string, string>;\n dark: Record<string, string>;\n}\n\n/** Resolve the token set for one role over its hue. */\nexport function functionalRole(\n role: string,\n hueName: string,\n hue: ExpandedHue,\n kind: RoleKind = 'chromatic',\n): FunctionalRole {\n const numeric = hue.numeric;\n const v = (n: NumStep) => `var(--color-${hueName}-${snap(numeric, n)})`;\n const hex = (n: NumStep) => numeric[snap(numeric, n)] as string;\n\n const map = (table: Table): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [token, step] of Object.entries(table)) out[token] = v(step);\n return out;\n };\n\n // Solids and the foreground computed against them are identical in both\n // appearances — that mode-stability is the whole point of the family.\n const solids = map(SOLID);\n const onSolid = pickOn(hex(SOLID['bg-solid'] as NumStep));\n\n const light = {\n ...map(kind === 'surface' ? SURFACE_LIGHT : CHROMATIC_LIGHT),\n ...solids,\n 'text-on': onSolid,\n };\n const dark = {\n ...map(kind === 'surface' ? SURFACE_DARK : CHROMATIC_DARK),\n ...solids,\n 'text-on': onSolid,\n };\n return { role, hue: hueName, kind, light, dark };\n}\n\n// ── the contrast contract ────────────────────────────────────────────────────\n\n/**\n * APCA targets. `TEXT` is the body-text bar; `SECONDARY` covers text on a\n * non-primary surface and de-emphasised text. `NON_TEXT` is the icon/boundary\n * tier — the APCA analogue of WCAG's 3:1, where a glyph may run more vivid than\n * text because shape carries meaning alongside contrast.\n */\nexport const CONTRAST = { TEXT: 75, SECONDARY: 60, NON_TEXT: 45 } as const;\n\n/**\n * Text tokens deliberately exempt from the contract. Placeholders and disabled\n * text are required to look unavailable; holding them to the body-text bar would\n * defeat the affordance. Nothing else may be exempt.\n */\nconst EXEMPT_TEXT = new Set(['text-x-muted', 'text-xx-muted']);\n\n/**\n * Verify a role's contrast targets. Returns human-readable failures.\n *\n * Chromatic roles are checked against the surface planes they actually sit on\n * (`surfaceBg`) as well as their own tints — coloured text almost never appears\n * over its own solid, it appears over the page. Checking only within the role\n * would have missed the pairing that matters most.\n */\nexport function checkContrast(\n fr: FunctionalRole,\n numericOf: (hueName: string) => Partial<Record<NumStep, string>>,\n surfaceBg?: { light: string[]; dark: string[] },\n): string[] {\n const failures: string[] = [];\n const resolve = (val: string): string => {\n const m = /^var\\(--color-([a-z0-9-]+)-(\\d+)\\)$/.exec(val);\n if (!m) return val;\n return numericOf(m[1] as string)[m[2] as NumStep] ?? val;\n };\n const fail = (appearance: string, msg: string) =>\n failures.push(`${fr.role}/${appearance}: ${msg}`);\n\n for (const [appearance, tokens] of [\n ['light', fr.light],\n ['dark', fr.dark],\n ] as const) {\n // Backgrounds this role's own foregrounds have to work on. For a surface\n // role that's its own planes; for a chromatic role it's the page surface\n // plus its own tints.\n const ownBg = Object.keys(tokens)\n .filter((k) => k === 'bg' || k.startsWith('bg-'))\n .filter((k) => !k.startsWith('bg-solid'))\n .filter((k) => !k.startsWith('bg-bold') && !k.startsWith('bg-x-bold'));\n const planes: Array<[string, string]> =\n fr.kind === 'surface'\n ? ownBg.map((k) => [k, resolve(tokens[k] as string)])\n : [\n ...(surfaceBg?.[appearance] ?? []).map(\n (h, i) => [`surface#${i}`, h] as [string, string],\n ),\n ...ownBg.map((k) => [k, resolve(tokens[k] as string)] as [string, string]),\n ];\n\n for (const [planeName, bg] of planes) {\n // `bg` is the role's primary surface and holds the full body-text bar;\n // every other plane holds the secondary bar.\n const textMin = planeName === 'bg' ? CONTRAST.TEXT : CONTRAST.SECONDARY;\n for (const key of ['text', 'text-bold', 'text-muted']) {\n if (tokens[key] == null || EXEMPT_TEXT.has(key)) continue;\n const min = key === 'text-muted' ? CONTRAST.SECONDARY : textMin;\n const lc = contrastLc(resolve(tokens[key] as string), bg);\n if (lc < min) fail(appearance, `${key} Lc ${lc.toFixed(1)} < ${min} on ${planeName} ${bg}`);\n }\n // Icons carry meaning, so they hold the non-text bar everywhere. Borders\n // do not: a chromatic `border-<role>` is *decorative* — the tinted edge of\n // an alert, where the colour reinforces a message the text already makes.\n // Only a surface role's `border-bold` is the \"this boundary is the only\n // thing separating two regions\" token, so only that one is guaranteed.\n const nonText = fr.kind === 'surface' ? ['icon', 'border-bold'] : ['icon'];\n for (const key of nonText) {\n if (tokens[key] == null) continue;\n const lc = contrastLc(resolve(tokens[key] as string), bg);\n if (lc < CONTRAST.NON_TEXT)\n fail(\n appearance,\n `${key} Lc ${lc.toFixed(1)} < ${CONTRAST.NON_TEXT} on ${planeName} ${bg}`,\n );\n }\n }\n\n // The filled-surface pairing: text-on against the solid it names.\n const solid = resolve(tokens['bg-solid'] as string);\n const onLc = contrastLc(tokens['text-on'] as string, solid);\n if (onLc < CONTRAST.SECONDARY)\n fail(appearance, `text-on Lc ${onLc.toFixed(1)} < ${CONTRAST.SECONDARY} on bg-solid`);\n\n // The inverse surface, where it exists.\n if (tokens['bg-bold'] != null && tokens['text-on-bold'] != null) {\n const lc = contrastLc(resolve(tokens['text-on-bold'] as string), resolve(tokens['bg-bold']));\n if (lc < CONTRAST.TEXT)\n fail(appearance, `text-on-bold Lc ${lc.toFixed(1)} < ${CONTRAST.TEXT} on bg-bold`);\n }\n }\n return failures;\n}\n","/**\n * OKF documentation bundle generator (ported from the repo's `generate-docs.ts`).\n *\n * Pure: `generateDocs(ds, assetsDir)` returns a `{ relPath: markdown }` map for the\n * Open Knowledge Format tree (top index, css/, bricks/), reading the Bricks element\n * PHP from `<assetsDir>/bricks/elements`. No filesystem writes — the caller decides\n * where the bundle lands (e.g. `<outDir>/docs`).\n */\nimport { readFileSync, readdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { jsonSchema, SCHEMA_URL, type DesignSystem } from './schema.ts';\nimport { BASE_HOOK, DARK_SEL, REQUIRED_ROLES, SYSTEM_DARK_SEL, TW_CLASH } from './shared.ts';\nimport { expandPalette } from './tokens.ts';\n\nconst DS_PATH = 'design-system.json';\n\n// Curated element display order (by $name, sans the vitops- prefix). Unlisted\n// elements fall to the end alphabetically so new ones still appear.\nconst ORDER = [\n 'split',\n 'centered',\n 'carousel',\n 'color-scheme-toggle',\n 'copy-button',\n 'dismissable',\n 'entries',\n 'image-compare',\n 'sitenav',\n 'multi-field',\n 'split-link',\n 'split-panel',\n];\n\n// ── PHP array-literal parser ─────────────────────────────────────────────────\ntype Json = string | number | boolean | null | Json[] | { [k: string]: Json };\n\ninterface Tok {\n t: 'str' | 'num' | 'id' | 'punc' | 'arrow';\n v: string;\n}\n\nfunction tokenize(src: string): Tok[] {\n const toks: Tok[] = [];\n let i = 0;\n const n = src.length;\n while (i < n) {\n const c = src[i] as string;\n if (c === ' ' || c === '\\t' || c === '\\n' || c === '\\r') {\n i++;\n continue;\n }\n if (c === '/' && src[i + 1] === '/') {\n while (i < n && src[i] !== '\\n') i++;\n continue;\n }\n if (c === '#') {\n while (i < n && src[i] !== '\\n') i++;\n continue;\n }\n if (c === '/' && src[i + 1] === '*') {\n i += 2;\n while (i < n && !(src[i] === '*' && src[i + 1] === '/')) i++;\n i += 2;\n continue;\n }\n if (c === \"'\" || c === '\"') {\n const quote = c;\n i++;\n let s = '';\n while (i < n && src[i] !== quote) {\n if (src[i] === '\\\\' && i + 1 < n) {\n const next = src[i + 1];\n s += next === 'n' ? '\\n' : next === 't' ? '\\t' : next;\n i += 2;\n } else {\n s += src[i++];\n }\n }\n i++;\n toks.push({ t: 'str', v: s });\n continue;\n }\n if (c === '=' && src[i + 1] === '>') {\n toks.push({ t: 'arrow', v: '=>' });\n i += 2;\n continue;\n }\n if ('[](){},'.includes(c)) {\n toks.push({ t: 'punc', v: c });\n i++;\n continue;\n }\n if (\n (c >= '0' && c <= '9') ||\n (c === '-' && (src[i + 1] as string) >= '0' && (src[i + 1] as string) <= '9')\n ) {\n let s = c;\n i++;\n while (i < n && (src[i] as string) >= '0' && (src[i] as string) <= '9') s += src[i++];\n toks.push({ t: 'num', v: s });\n continue;\n }\n if (/[A-Za-z_\\\\]/.test(c)) {\n let s = c;\n i++;\n while (i < n && /[A-Za-z0-9_\\\\]/.test(src[i] as string)) s += src[i++];\n toks.push({ t: 'id', v: s });\n continue;\n }\n i++;\n }\n return toks;\n}\n\nclass Parser {\n p = 0;\n toks: Tok[];\n constructor(toks: Tok[]) {\n this.toks = toks;\n }\n peek(): Tok | undefined {\n return this.toks[this.p];\n }\n next(): Tok | undefined {\n return this.toks[this.p++];\n }\n parseValue(): Json {\n const t = this.peek();\n if (!t) return null;\n if (t.t === 'str') {\n this.next();\n return t.v;\n }\n if (t.t === 'num') {\n this.next();\n return Number(t.v);\n }\n if (t.t === 'id') {\n this.next();\n if (t.v === 'true') return true;\n if (t.v === 'false') return false;\n if (t.v === 'null') return null;\n if (this.peek()?.t === 'punc' && this.peek()?.v === '(') {\n this.next();\n if (t.v === 'array') return this.parseBody(')');\n const args = this.parseCallArgs();\n return args.find((a) => typeof a === 'string') ?? args[0] ?? '';\n }\n return t.v;\n }\n if (t.t === 'punc' && t.v === '[') {\n this.next();\n return this.parseBody(']');\n }\n if (t.t === 'punc' && t.v === '(') {\n this.next();\n return this.parseBody(')');\n }\n this.next();\n return null;\n }\n private parseCallArgs(): Json[] {\n const args: Json[] = [];\n while (this.peek() && !(this.peek()!.t === 'punc' && this.peek()!.v === ')')) {\n args.push(this.parseValue());\n if (this.peek()?.t === 'punc' && this.peek()?.v === ',') this.next();\n }\n this.next();\n return args;\n }\n private parseBody(close: string): Json {\n const list: Json[] = [];\n const map: Record<string, Json> = {};\n let keyed = false;\n while (this.peek() && !(this.peek()!.t === 'punc' && this.peek()!.v === close)) {\n const first = this.parseValue();\n if (this.peek()?.t === 'arrow') {\n this.next();\n const val = this.parseValue();\n // PHP array keys are scalars; stringify objects defensively.\n map[typeof first === 'object' && first !== null ? JSON.stringify(first) : String(first)] =\n val;\n keyed = true;\n } else {\n list.push(first);\n }\n if (this.peek()?.t === 'punc' && this.peek()?.v === ',') this.next();\n }\n this.next();\n return keyed ? map : list;\n }\n}\n\nfunction parsePhpLiteral(text: string): Json {\n return new Parser(tokenize(text)).parseValue();\n}\n\n// ── Source-region helpers ────────────────────────────────────────────────────\nfunction matchBalanced(src: string, open: number): number {\n const pairs: Record<string, string> = { '(': ')', '[': ']', '{': '}' };\n const stack: string[] = [];\n let i = open;\n const n = src.length;\n while (i < n) {\n const c = src[i] as string;\n if (c === '/' && src[i + 1] === '/') {\n while (i < n && src[i] !== '\\n') i++;\n continue;\n }\n if (c === '/' && src[i + 1] === '*') {\n i += 2;\n while (i < n && !(src[i] === '*' && src[i + 1] === '/')) i++;\n i += 2;\n continue;\n }\n if (c === \"'\" || c === '\"') {\n i++;\n while (i < n && src[i] !== c) {\n if (src[i] === '\\\\') i++;\n i++;\n }\n i++;\n continue;\n }\n if (c in pairs) stack.push(pairs[c] as string);\n else if (c === ')' || c === ']' || c === '}') {\n if (stack.pop() !== c) {\n /* unbalanced — best effort */\n }\n if (stack.length === 0) return i + 1;\n }\n i++;\n }\n return n;\n}\n\nfunction methodBody(src: string, name: string): string | null {\n const m = new RegExp(`function\\\\s+${name}\\\\s*\\\\([^)]*\\\\)`).exec(src);\n if (!m) return null;\n const brace = src.indexOf('{', m.index + m[0].length);\n if (brace < 0) return null;\n const end = matchBalanced(src, brace);\n return src.slice(brace + 1, end - 1);\n}\n\nfunction literalAt(src: string, fromIdx: number): { text: string; end: number } | null {\n let i = fromIdx;\n while (i < src.length && /\\s/.test(src[i] as string)) i++;\n let open: number;\n if (src[i] === '[') open = i;\n else if (src.startsWith('array', i)) open = src.indexOf('(', i);\n else return null;\n const end = matchBalanced(src, open);\n return { text: src.slice(i, end), end };\n}\n\n// ── Per-element extraction ───────────────────────────────────────────────────\ninterface Control {\n key: string;\n def: Record<string, Json>;\n}\ninterface Element {\n name: string;\n label: string;\n nestable: boolean;\n docblock: string;\n controls: Control[];\n cssClass: string | null;\n children: string[];\n keywords: string[];\n}\n\nfunction firstString(re: RegExp, src: string): string | null {\n const m = re.exec(src);\n return m ? (m[1] ?? null) : null;\n}\n\nfunction extractDocblock(src: string): string {\n const m = /\\/\\*\\*([\\s\\S]*?)\\*\\//.exec(src);\n if (!m) return '';\n const lines = (m[1] as string)\n .split('\\n')\n .map((l) => l.replace(/^\\s*\\*?\\s?/, '').replace(/\\s+$/, ''));\n while (lines.length && lines[0] === '') lines.shift();\n if (lines.length && /Bricks Builder\\)\\./.test(lines[0] as string)) lines.shift();\n const owned = lines.findIndex((l) => l.startsWith('Owned by the framework repo'));\n const kept = (owned >= 0 ? lines.slice(0, owned) : lines).map((l) => l.replace(/^•\\s*/, '- '));\n while (kept.length && kept[kept.length - 1] === '') kept.pop();\n while (kept.length && kept[0] === '') kept.shift();\n return kept.join('\\n');\n}\n\nfunction extractControls(src: string): Control[] {\n const body = methodBody(src, 'set_controls');\n if (!body) return [];\n const controls: Control[] = [];\n const re = /\\$this->controls\\[\\s*'([^']+)'\\s*\\](\\[\\s*'([^']+)'\\s*\\])?\\s*=\\s*/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body))) {\n const key = m[1] as string;\n if (m[2]) continue;\n const lit = literalAt(body, m.index + m[0].length);\n if (!lit) continue;\n const def = parsePhpLiteral(lit.text);\n if (def && typeof def === 'object' && !Array.isArray(def))\n controls.push({ key, def: def as Record<string, Json> });\n re.lastIndex = lit.end;\n }\n return controls;\n}\n\nfunction extractChildren(src: string): string[] {\n const body = methodBody(src, 'get_nestable_children');\n if (!body) return [];\n const labels: string[] = [];\n const re = /'label'\\s*=>\\s*esc_html__\\(\\s*'([^']*)'/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body))) labels.push(m[1] as string);\n return labels;\n}\n\nfunction extractKeywords(src: string): string[] {\n const body = methodBody(src, 'get_keywords');\n if (!body) return [];\n const ret = /return\\s+/.exec(body);\n if (!ret) return [];\n const lit = literalAt(body, ret.index + ret[0].length);\n if (!lit) return [];\n const arr = parsePhpLiteral(lit.text);\n return Array.isArray(arr) ? arr.filter((x): x is string => typeof x === 'string') : [];\n}\n\nfunction parseElement(src: string): Element | null {\n const name = firstString(/public\\s+\\$name\\s*=\\s*'vitops-([^']+)'/, src);\n if (!name) return null;\n return {\n name,\n label:\n firstString(/function get_label\\(\\)[\\s\\S]*?return\\s+esc_html__\\(\\s*'([^']*)'/, src) ?? name,\n nestable: /public\\s+\\$nestable\\s*=\\s*true/.test(src),\n docblock: extractDocblock(src),\n controls: extractControls(src),\n cssClass: firstString(\n /\\$this->controls\\[\\s*'_cssClasses'\\s*\\]\\[\\s*'default'\\s*\\]\\s*=\\s*'([^']*)'/,\n src,\n ),\n children: extractChildren(src),\n keywords: extractKeywords(src),\n };\n}\n\n// ── Markdown rendering ───────────────────────────────────────────────────────\n/** Stringify a parsed-PHP Json value for prose (objects → JSON, not [object Object]). */\nconst asText = (v: Json | undefined): string =>\n v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);\n\nfunction controlLine(c: Control): string {\n const def = c.def;\n if (def.type === 'info') return `- _Note:_ ${asText(def.content)}`;\n const label = (def.label as string) || c.key;\n const options =\n def.options && typeof def.options === 'object' && !Array.isArray(def.options)\n ? (def.options as Record<string, string>)\n : null;\n const meta: string[] = [];\n let type = (def.type as string) || 'text';\n if (def.units === true) type += '+units';\n meta.push(type);\n if (def.default !== undefined) {\n const raw = asText(def.default);\n const shown = options && options[raw] ? options[raw] : raw;\n meta.push(`default \\`${shown}\\``);\n }\n if (def.placeholder !== undefined && def.placeholder !== '')\n meta.push(`placeholder \\`${asText(def.placeholder)}\\``);\n if (def.min !== undefined || def.max !== undefined)\n meta.push(\n `range ${def.min != null ? asText(def.min) : '–'}–${def.max != null ? asText(def.max) : '∞'}`,\n );\n const tail: string[] = [];\n if (def.description) tail.push(asText(def.description));\n if (options)\n tail.push(\n `Options: ${Object.values(options)\n .map((o) => `\\`${o}\\``)\n .join(', ')}.`,\n );\n if (Array.isArray(def.css) && def.css.length) {\n const first = def.css[0];\n if (first && typeof first === 'object' && !Array.isArray(first) && 'property' in first)\n tail.push(`Bound to \\`${asText((first as Record<string, Json>).property)}\\`.`);\n }\n if (def.type === 'repeater' && def.fields && typeof def.fields === 'object') {\n const fields = Object.values(def.fields as Record<string, Json>)\n .map((f) =>\n f && typeof f === 'object' && !Array.isArray(f)\n ? asText((f as Record<string, Json>).label)\n : null,\n )\n .filter(Boolean);\n if (fields.length) tail.push(`Fields: ${fields.join(', ')}.`);\n }\n const head = `- **${label}** (${meta.join(', ')})`;\n return tail.length ? `${head} — ${tail.join(' ')}` : head;\n}\n\nfunction renderElement(el: Element): string {\n const out: string[] = [];\n const nest = el.nestable ? 'nestable' : 'not nestable';\n out.push(`## ${el.label} — \\`vitops-${el.name}\\` · ${nest}`);\n out.push('');\n if (el.docblock) {\n out.push(el.docblock);\n out.push('');\n }\n const real = el.controls.filter((c) => c.def.type !== 'info');\n if (real.length) {\n out.push('**Controls**');\n out.push('');\n for (const c of el.controls) out.push(controlLine(c));\n out.push('');\n } else {\n const notes = el.controls.filter((c) => c.def.type === 'info');\n if (notes.length) {\n for (const c of notes) out.push(controlLine(c));\n out.push('');\n }\n }\n if (el.cssClass) {\n out.push(\n `**Base CSS class:** \\`${el.cssClass}\\` (applied automatically; add ratio/modifier classes alongside it in the element's \"CSS classes\" field).`,\n );\n out.push('');\n }\n if (el.children.length) {\n out.push(`**Seeded children:** ${el.children.join(', ')}.`);\n out.push('');\n }\n if (el.keywords.length) {\n out.push(`**Keywords:** ${el.keywords.filter((k) => k !== 'vitops').join(', ')}.`);\n out.push('');\n }\n return out.join('\\n');\n}\n\n// ── OKF helpers ──────────────────────────────────────────────────────────────\ninterface Frontmatter {\n type: string;\n title: string;\n description: string;\n resource?: string;\n tags?: string[];\n}\nfunction frontmatter(fm: Frontmatter): string {\n const q = (s: string) => `\"${s.replace(/\"/g, '\\\\\"')}\"`;\n const lines = [\n `type: ${q(fm.type)}`,\n `title: ${q(fm.title)}`,\n `description: ${q(fm.description)}`,\n ];\n if (fm.resource) lines.push(`resource: ${q(fm.resource)}`);\n if (fm.tags) lines.push(`tags: [${fm.tags.join(', ')}]`);\n lines.push('generator: \"@getvitops/generator\"');\n return `---\\n${lines.join('\\n')}\\n---`;\n}\n\nconst INDEX_NOTE = `<!-- GENERATED by @getvitops/generator — do not edit; regenerate with \\`vitops generate\\`. -->`;\n\nconst ELEMENTS_FRONTMATTER = frontmatter({\n type: 'Bricks Elements Reference',\n title: 'Vitops — Bricks Builder elements reference',\n description:\n 'Every repo-owned Bricks element, its controls, defaults, seeded children and keywords, for driving the Bricks Builder UI.',\n resource: 'bricks/elements',\n tags: ['bricks', 'wordpress', 'elements', 'design-system'],\n});\n\nconst ELEMENTS_PREAMBLE = `${ELEMENTS_FRONTMATTER}\n\n# Vitops — Bricks Builder elements reference\n\nContext for driving the Bricks Builder UI (e.g. Claude for Chrome). Every section below\nis generated from the element's own source, so this reference always matches the elements\ncurrently deployed. See also the CSS class vocabulary in [/css/classes.md](../css/classes.md)\nand the integration guidance in [/bricks/index.md](index.md).\n\n## How they appear in the builder\n\n- The elements register from \\`dist/bricks/load.php\\` and group under a **\"Vitops\"** category\n pinned to the **top** of the element panel. Insert one by searching its **label** (e.g.\n \"Split\", \"Carousel\") or any of its **keywords** (listed per element).\n- Two rendering families:\n - **Web-component elements** render a Lit custom element (\\`<wc-*>\\`, \\`<copy-button>\\`, …)\n from \\`dist/elements.js\\` and progressively enhance. A few (Image Compare, Split Panel)\n show their children stacked in the builder canvas until the client-side upgrade runs —\n that is expected, not broken.\n - **CSS-pattern elements** (Split, Centered, Menu, Split Link) render plain markup styled\n by the framework CSS — no JS dependency.\n- **Nestable** elements accept child elements dropped into them; some seed starter children\n (listed as \"Seeded children\"). **Non-nestable** elements are configured entirely through\n their controls.\n\n## Configuring layout\n\nSome layout is set through **controls**; some through **CSS classes typed into the element's\nbuilt-in \"CSS classes\" field** (called out per element as modifier classes). Responsive\nsuffixes on those classes engage from a container breakpoint: \\`-sm\\` = 30rem, \\`-md\\` = 48rem,\n\\`-lg\\` = 64rem, \\`-xl\\` = 80rem.\n\nEach control below lists its type, default/placeholder, any select options, and the CSS\ncustom property it writes (when it drives one). Info notes flagged _Note:_ carry the\nmodifier-class and structural guidance from the element itself.\n\n---\n`;\n\nfunction renderElementsDoc(elementsDir: string): string {\n const files = existsSync(elementsDir)\n ? readdirSync(elementsDir).filter((f) => f.endsWith('.php'))\n : [];\n const elements: Element[] = [];\n for (const f of files) {\n try {\n const el = parseElement(readFileSync(join(elementsDir, f), 'utf8'));\n if (el) elements.push(el);\n } catch {\n /* skip unparseable element */\n }\n }\n elements.sort((a, b) => {\n const ia = ORDER.indexOf(a.name);\n const ib = ORDER.indexOf(b.name);\n if (ia >= 0 && ib >= 0) return ia - ib;\n if (ia >= 0) return -1;\n if (ib >= 0) return 1;\n return a.name.localeCompare(b.name);\n });\n const body = elements.map(renderElement).join('\\n---\\n\\n');\n return `${ELEMENTS_PREAMBLE}\\n${body}`;\n}\n\n// ── CSS framework reference (rule-summarized, from the config) ────────────────\nconst code = (xs: string[]) => xs.map((x) => `\\`${x}\\``).join(', ');\n\nfunction renderCssClasses(ds: DesignSystem): string {\n const expanded = expandPalette(ds.colors.palette as Record<string, unknown>);\n const ramps = Object.keys(expanded);\n const roles = Object.keys(ds.colors.roles ?? {});\n const utils = ds.colors.utilities ?? ['bg', 'text', 'icon', 'border'];\n const typeRoles = Object.keys(ds.typography?.roles ?? {});\n const shadows = Object.keys(ds.shadows ?? {});\n const effects = Object.keys(ds.animations?.effects ?? {});\n // Split by keyframe family, because only composite/paint effects get the\n // hover-/focus-/active- state variants — `.transition` deliberately doesn't\n // transition `height`, so a `hover-size-grow` would be a class that resolves\n // to nothing. Listing every effect under \"with the state prefixes above\" is\n // what sent the docs site rendering exactly that.\n const stateful = Object.entries(ds.animations?.effects ?? {})\n .filter(([, e]) => e.kf === 'composite' || e.kf === 'paint')\n .map(([name]) => name);\n const keyframeOnly = effects.filter((name) => !stateful.includes(name));\n const items = (ds.patterns?.items ?? {}) as Record<\n string,\n { roles?: string[]; default_role?: string }\n >;\n const patterns = Object.keys(items);\n const patternRoles = Array.from(\n new Set(\n Object.values(items).flatMap(\n (p) => [p.default_role, ...(p.roles ?? [])].filter(Boolean) as string[],\n ),\n ),\n );\n const spaceNames = ds.spaceScale?.names ?? [];\n const typeNames = ds.typeScale?.names ?? [];\n const families = Object.keys(ds.typography?.families ?? {});\n const radii = Object.keys(ds.patterns?.radii ?? {});\n\n return `${frontmatter({\n type: 'CSS Framework Reference',\n title: 'Vitops CSS framework — class vocabulary',\n description:\n 'Every utility and component class in the Vitops CSS framework, stated as a naming rule over the design tokens it expands.',\n resource: DS_PATH,\n tags: ['css', 'utilities', 'patterns', 'design-system'],\n })}\n\n# Vitops CSS framework — class vocabulary (LLM reference)\n\nA variable-driven CSS framework. Classes encode the design system's **tokens** (colour,\ntype, space, shadow), **responsive grammar**, and **interaction states** — so styling with\nthese classes stays consistent and theme-/dark-mode-aware. Prefer them over hand-written\nCSS or ad-hoc property values.\n\nThis is a **rule reference**, not an exhaustive list: each family below is a naming rule\nplus the set of tokens it expands over. Applying a rule to any listed token yields a valid\nclass (e.g. rule \\`bg-<color>\\` + colour \\`pine-xl\\` → \\`bg-pine-xl\\`).\n\nThe tokens themselves are authored in \\`design-system.json\\` — see\n[/authoring.md](../authoring.md); the systems behind them are explained in\n[/concepts/](../concepts/index.md); per-format output differences (including which of\nthese utilities Tailwind provides natively) in [/formats.md](../formats.md).\n\n## Responsive & state variant grammar\n\nEvery utility accepts a **container-breakpoint prefix**; animation utilities also accept a\n**state prefix**. In CSS/Bricks the separator is \\`-\\`; in Tailwind it is \\`:\\` / \\`@\\`.\n\n| Intent | CSS / Bricks | Tailwind |\n| ----------------- | -------------------------- | ----------------------------------------- |\n| responsive split | \\`md-split-1-2\\` | \\`@md:split-1-2\\` |\n| responsive align | \\`md-items-center\\` | \\`@md:items-center\\` |\n| hover effect | \\`transition hover-fade-in\\` | \\`transition fade-in hover:flip-fade-in\\` |\n\n- Breakpoint prefixes (bare): \\`sm-\\` = 30rem, \\`md-\\` = 48rem, \\`lg-\\` = 64rem, \\`xl-\\` = 80rem.\n- State prefixes (animation effects only): \\`hover-\\`, \\`active-\\`, \\`focus-\\`, and \\`flip-<effect>\\`\n (plays the effect in reverse on toggle). Effects require \\`transition\\` on the element.\n\n## Layout & structure\n\n- **\\`centered\\`** — named-track grid centering content in the reading \\`measure\\` track.\n Widen a **direct child** by adding \\`breakout\\`, \\`spotlight\\`, or \\`fullbleed\\` (each\n breakpoint-prefixable) to that child. Track widths are set via \\`--width-measure\\` /\n \\`--width-breakout\\` / \\`--width-spotlight\\` and \\`--gutter\\`.\n- **\\`rhythm\\`** — relationship-based vertical spacing (margins between headings, paragraphs,\n lists, media) driven by the space scale. Usually paired with \\`centered\\`.\n- **\\`split\\`** — a two-column pair. Ratio rule: **\\`split-<a>-<b>\\`** where \\`<a>-<b>\\` ∈\n \\`1-2\\`, \\`2-1\\`, \\`1-3\\`, \\`3-1\\`, \\`1-4\\`, \\`4-1\\`, \\`2-3\\`, \\`3-2\\` (breakpoint-prefixable); equal\n columns without one. The ratio is a flex **basis**, so a column's padding counts\n inside its share, and \\`min-inline-size: 0\\` is built in so long unbreakable content\n can't stretch a column past it.\n - **Stacking is \\`flex-col\\`** — there is no split-specific class for it:\n \\`class=\"split flex-col md-split-1-2\"\\` is stacked below 48rem and 1:2 above,\n because the \\`<bp>-\\` ratio classes assert the row. While stacked the ratio goes\n inert on its own (a percentage basis against an auto-height column resolves as\n \\`content\\`), unless you give the split a definite \\`block-size\\`.\n - **\\`split-reverse\\`** — swaps the two panels (breakpoint-prefixable). Implemented\n as \\`order\\` on the first child, so it reverses on whichever axis the split is\n currently on: bare, it swaps the columns in a row AND the rows in a stack;\n scoped (\\`md-split-reverse\\`) it swaps only once there are two columns — media\n first in source so it leads on mobile, on the right at width. The ratio stays\n with the source-first child, not with the visual position.\n - **Accessibility:** reversing makes visual order disagree with DOM order, and\n focus order follows the DOM (WCAG 2.4.3 Focus Order). Put focusable content in\n **only one** of the two panels, or the tab order will not be linear. The\n pattern declares \\`reading-flow: flex-visual\\`, which fixes this properly where\n it is supported; support is not yet broad enough to rely on.\n- **Flex** — \\`flex\\`, \\`flex-row\\`, \\`flex-col\\`, \\`flex-row-reverse\\`, \\`flex-col-reverse\\`\n (all breakpoint-prefixable).\n- **Alignment** — \\`items-{start,center,end,stretch}\\`, \\`justify-{start,center,end,between}\\`,\n text align \\`text-{start,center,end}\\` (all breakpoint-prefixable).\n- **Display** — \\`block\\`, \\`inline\\`, \\`inline-block\\`, \\`flex\\`, \\`grid\\`, \\`hidden\\`\n (breakpoint-prefixable, e.g. \\`md-hidden\\`).\n- **Accessibility** — \\`sr-only\\` / \\`not-sr-only\\` (breakpoint-prefixable).\n- **State hooks** — \\`is-active\\`, \\`is-open\\` (styling flags toggled by JS / native state).\n\n## Spacing\n\nThe space scale is ${code(spaceNames)} exposed as \\`--space-<name>\\` tokens.\n\\`rhythm\\` margins consume these tokens; prefer \\`rhythm\\` for vertical flow rather than\nper-element margins.\n\nRule: **\\`gap-<name>\\`**, **\\`gap-x-<name>\\`** (column) and **\\`gap-y-<name>\\`** (row), name ∈\n${code(spaceNames)} — all breakpoint-prefixable (\\`md-gap-l\\`, \\`@md:gap-l\\`). These are the\nframework's own utilities in every format: the fluid steps are deliberately kept out of\nTailwind's \\`--spacing-*\\` namespace (named keys there shadow the size scales, so\n\\`max-w-7xl\\` would resolve to \\`var(--spacing-7xl)\\`), which means Tailwind's numeric\n\\`gap-4\\` still uses its own multiplier and coexists with these.\n\n## Typography\n\nRule: **\\`font-<role>\\`** — role ∈ ${code(typeRoles)}. Each role carries its own family,\nsize (from the type scale ${code(typeNames)}), tracking, transform, weight and \\`text-wrap\\`.\nFamilies: ${code(families)} (\\`--font-*\\`).\n\nBecause the role owns \\`text-wrap\\`, a heading is balanced and copy is \\`pretty\\` with **no\nclass at all** wherever \\`typography.headings\\` maps the bare element to a role. Override one\nelement with \\`text-{wrap,nowrap,balance,pretty}\\` — the per-element escape hatch, for markup\nthat carries no role class. (These four are Tailwind's own in the tailwind format.)\n\n## Colour\n\n**Functional tokens are the primary vocabulary** — classes name the *job*, not the tone, and\nevery one remaps automatically under \\`${DARK_SEL}\\` (background/text ends\nswap; \\`solid\\` fills stay mode-stable with a computed \\`on-\\` foreground). Prefer these over\nraw steps.\n\n**Role names are yours.** \\`colors.roles\\` is an open map: add a key, and the generator emits\nthat role's full token set, its dark flip and every utility below. Your config\ncurrently defines ${code(roles)}. Six of those are a **required core** — the framework's own\ncomponent CSS references \\`${REQUIRED_ROLES.join('`, `')}\\` with no fallback, so removing one\nleaves those components uncoloured (\\`vitops validate\\` warns). Everything beyond them is free.\n\nThe rule is one shape — **\\`<target>-<role>[-<variant>]\\`**, target ∈ \\`bg\\` \\`text\\` \\`icon\\`\n\\`border\\` — and the class name is exactly its token name minus \\`--color-\\`. Variants are\nordinal (\\`xx-muted\\` < \\`x-muted\\` < \\`muted\\` < bare < \\`bold\\` < \\`x-bold\\`) and sparse: only the\ncells that hold their contrast target exist.\n\n**Which cells exist depends on the role's \\`kind\\`:**\n\n*Surface roles* (page and panel colours):\n\n- **Backgrounds** — \\`bg-<role>\\` (the card/panel), \\`bg-<role>-muted\\` (the page behind it),\n \\`bg-<role>-x-muted\\` (well / inset), \\`bg-<role>-bold\\` and \\`-x-bold\\` (inverse surface).\n Elevation is *which* token you reach for, not a raised/sunken pair.\n- **Content** — \\`text-<role>\\` (body), \\`text-<role>-bold\\`, \\`text-<role>-muted\\` (secondary),\n \\`text-<role>-x-muted\\` (placeholder) and \\`-xx-muted\\` (disabled). The last two are\n contrast-exempt by design.\n- **Borders** — \\`border-<role>-muted\\` (hairline), \\`border-<role>\\`, \\`border-<role>-bold\\`\n (the one guaranteed to carry a boundary on its own).\n\n*Chromatic roles* (signal colours) — **there is no bare \\`bg-<role>\\`**; say tint or solid:\n\n- **Tints** — \\`bg-<role>-x-muted\\` (alert wash), \\`bg-<role>-muted\\` (badge).\n- **Solids** — \\`bg-<role>-solid\\`, \\`-solid-bold\\` (hover), \\`-solid-x-bold\\` (active), each\n pairing with \\`text-on-<role>\\` for a guaranteed-contrast foreground.\n- **Content** — \\`text-<role>\\`, \\`text-<role>-bold\\`. There is deliberately no\n \\`text-<role>-muted\\`: it could not hold its contrast target off a light surface, so soften\n coloured text with weight or size instead.\n- **Borders** — \\`border-<role>\\`, \\`border-<role>-bold\\` (decorative status edges).\n\nBoth kinds also get **\\`icon-<role>\\`** — a separate non-text tier, so a glyph may run more\nvivid than text — plus \\`glass\\` (translucent surface + backdrop blur), the \\`--overlay\\` scrim\nand \\`--color-border-focus\\` for focus rings.\n\nEveryday pairings, using the roles this config defines: page\n\\`bg-${roles[0] ?? 'neutral'}-muted\\`, cards \\`bg-${roles[0] ?? 'neutral'}\\` on top of it, body\n\\`text-${roles[0] ?? 'neutral'}\\`, captions \\`text-${roles[0] ?? 'neutral'}-muted\\`; buttons\n\\`bg-${roles[2] ?? roles[0] ?? 'ui-primary'}-solid text-on-${roles[2] ?? roles[0] ?? 'ui-primary'}\\`;\nalerts \\`bg-danger-x-muted text-danger\\`.\n\n**Raw scale** (secondary / fine control) — rule \\`<util>-<hue>-<step>\\` with util ∈\n${code(utils)}: every hue is an 11-step OKLCH scale generated from its seed (or fixed brand\ntones), numeric steps \\`50\\` … \\`950\\` (tinted near-white → tinted near-black) — e.g.\n\\`bg-${ramps[0] ?? 'brand'}-100\\`, \\`text-${ramps[0] ?? 'brand'}-800\\`. Hues: ${code(ramps)}.\n\n> **Raw scale classes are frozen — they do NOT remap in dark mode.**\n> \\`bg-${ramps[0] ?? 'brand'}-800\\` is that exact colour in every appearance. The automatic\n> dark flip described above applies **only** to the functional role tokens, because\n> \\`--color-<hue>-<step>\\` is emitted once and never re-pointed under \\`${DARK_SEL}\\`.\n> A raw step on a page that can switch appearance is a latent bug: it looks correct in\n> whichever mode you built it in and inverts in the other.\n>\n> If you are reaching for a raw step, you usually want a **role** instead — and roles are\n> extensible, so adding one is a two-line config change:\n>\n> | instead of | use | why |\n> | --- | --- | --- |\n> | \\`bg-<hue>-50\\` / \\`-950\\` | \\`bg-<role>\\` (surface kind) | the card plane, flips automatically |\n> | \\`bg-<hue>-100\\` / \\`-900\\` | \\`bg-<role>-muted\\` | the page, or a chromatic tint |\n> | \\`bg-<hue>-500\\`…\\`-700\\` | \\`bg-<role>-solid\\` | vivid fill, mode-stable, pairs with \\`text-on-<role>\\` |\n> | \\`text-<hue>-950\\` / \\`-50\\` | \\`text-<role>\\` | contrast-guaranteed body text |\n> | \\`text-<hue>-800\\` / \\`-200\\` | \\`text-<role>-muted\\` | secondary text |\n> | \\`border-<hue>-200\\` / \\`-800\\` | \\`border-<role>\\` | |\n>\n> Raw steps stay the right tool for genuinely fixed colours — a brand mark, a chart series,\n> an illustration — where the value must not move between appearances.\n\n## Shadows\n\nRule: **\\`drop-shadow-<size>\\`** — size ∈ ${code(shadows)} (applied as a \\`filter\\`, so it\nfollows non-rectangular shapes).\n\n## Animation\n\nAn effect carries no motion of its own — it sets \\`--<prop>-from\\`/\\`-to\\` and picks a keyframe.\nA **driver** supplies the motion, and you always compose one of each:\n\n- \\`animate-view\\` — plays as the element crosses the viewport\n- \\`animate-scroll\\` — scrubs against page scroll\n- \\`animate-trigger\\` — time-based; plays once when \\`.is-active\\` / \\`[data-active]\\` is set\n- \\`transition\\` — transitions the same from/to vars, so it reverses on a state flip\n\nRule: **\\`<effect>\\`** — effect ∈ ${code(effects)}. The state/flip prefixes above pair with\n\\`transition\\` and apply to every one of them.\n\nEach state matches the element **or its direct parent** (\\`.hover-<fx>:hover, :hover > .hover-<fx>\\`),\nwhich is what makes \\`reveal-*\\` usable: it rests at a zero-area \\`clip-path\\`, and \\`clip-path\\` clips\nhit-testing as well as painting, so the element itself can never be hovered.${\n keyframeOnly.length\n ? `\n\n${code(keyframeOnly)} animate \\`height\\`, the only stage that reflows and the only one behind a\nfeature gate: \\`0 → auto\\` is not interpolable without \\`interpolate-size: allow-keywords\\`, so\n\\`transition\\` declares \\`height\\` only inside an \\`@supports\\` for it. The \\`layout\\` **keyframe**\nhas the same dependency — this is not a limit of the transition driver.`\n : ''\n }\n\n**When it plays.** \\`animate-view\\` and \\`.is-active\\` are both timed off the element's **midpoint**:\nmotion starts once that midpoint is 10% of the viewport in, and a one-shot entrance completes at\n25%. Both stops are the element's position on screen rather than a fraction of its own height, so a\nsmall card and a full-bleed section behave alike. Shift the window with \\`--anim-start\\` /\n\\`--anim-end\\`, or replace it outright with \\`--anim-range\\`.\n\nComposed **journeys** chain multiple effects into one entrance: rule \\`<parts>-journey\\`\n(e.g. \\`fade-slide-journey\\`, \\`fade-scale-blur-journey\\`). They need a **keyframe** driver, not\n\\`transition\\`. A journey is entry → hold → exit, so it starts on that same 10% pivot but runs to the\nend of the exit phase — the hold occupies the middle of the crossing instead of the bottom edge of\nthe screen.\n\n**\\`stagger\\`** on a parent offsets each child by \\`--stagger-amount\\` (time-based drivers) and by\n\\`--stagger-range-step\\` (scroll-driven ones — \\`animation-delay\\` is ignored on a progress-based\ntimeline). Journeys set an explicit range and opt out.\n\n## Component patterns\n\nEach pattern is a base class \\`<pattern>\\` with interaction states (hover/active/focus-visible)\nbaked in; coloured patterns add role variants via rule **\\`<pattern>-<role>\\`**. (How the\npattern CSS is assembled — token cascade, \\`--p-<pattern>\\`-style override hooks, state\nshortcuts — is explained in [/concepts/patterns.md](../concepts/patterns.md).)\n\n- Patterns: ${code(patterns)}.\n- Roles (for coloured patterns — \\`badge\\`, \\`tag\\`, \\`status\\`, \\`cta\\`, \\`btn\\`, …):\n ${code(patternRoles)} — e.g. \\`badge-success\\`, \\`cta-danger\\`. A pattern that also styles an\n element accepts the bare role class too (\\`<button class=\"danger\">\\`). The default\n (unsuffixed) variant uses the pattern's \\`default_role\\`.\n- Shape primitives: \\`--br-<name>\\` radii — ${code(radii)}.\n`;\n}\n\n// ── design-system.json authoring reference (walked from the JSON Schema) ─────\n// Field docs are rendered from `jsonSchema`'s `description` metadata (authored\n// once in schema.ts via `desc()`), so this reference cannot drift from validation.\n\ninterface JsonSchemaNode {\n type?: string;\n description?: string;\n properties?: Record<string, JsonSchemaNode>;\n required?: string[];\n additionalProperties?: JsonSchemaNode | boolean;\n anyOf?: JsonSchemaNode[];\n items?: JsonSchemaNode;\n enum?: unknown[];\n}\n\nconst isPrimitive = (n: JsonSchemaNode): boolean =>\n !n.properties && !n.anyOf && n.type != null && n.type !== 'object' && n.type !== 'array';\n\nfunction typeLabel(node: JsonSchemaNode): string {\n if (node.enum) return node.enum.map(String).join(' | ');\n if (node.anyOf)\n return node.anyOf.every(isPrimitive) ? node.anyOf.map((v) => v.type).join(' | ') : 'one of';\n if (node.type === 'array') {\n const it = node.items;\n if (it?.enum) return `array of ${it.enum.map(String).join(' | ')}`;\n return it?.type && it.type !== 'object' ? `array of ${it.type}` : 'array';\n }\n if (node.type === 'object') {\n const ap = node.additionalProperties;\n return ap && typeof ap === 'object' ? 'map' : 'object';\n }\n return node.type ?? 'value';\n}\n\n/** A node's documentable children: object properties, map values, or array items. */\nfunction childEntries(\n node: JsonSchemaNode,\n): Array<{ label: string; node: JsonSchemaNode; required: boolean }> {\n if (node.properties) {\n const req = node.required ?? [];\n return Object.entries(node.properties).map(([k, v]) => ({\n label: k,\n node: v,\n required: req.includes(k),\n }));\n }\n const ap = node.additionalProperties;\n if (ap && typeof ap === 'object' && (ap.description || ap.properties || ap.anyOf))\n return [{ label: '<name>', node: ap, required: false }];\n if (node.items && (node.items.description || node.items.properties || node.items.anyOf))\n return [{ label: '[items]', node: node.items, required: false }];\n return [];\n}\n\nfunction renderSchemaNode(\n label: string,\n node: JsonSchemaNode,\n required: boolean,\n depth: number,\n out: string[],\n): void {\n const indent = ' '.repeat(depth);\n const meta = `(${typeLabel(node)}${required ? ', required' : ''})`;\n out.push(`${indent}- \\`${label}\\` ${meta}${node.description ? ` — ${node.description}` : ''}`);\n if (depth >= 3) return;\n if (node.anyOf && !node.anyOf.every(isPrimitive)) {\n for (const variant of node.anyOf) {\n out.push(`${indent} - *one of*${variant.description ? ` — ${variant.description}` : ''}`);\n for (const c of childEntries(variant))\n renderSchemaNode(c.label, c.node, c.required, depth + 2, out);\n }\n return;\n }\n for (const c of childEntries(node)) renderSchemaNode(c.label, c.node, c.required, depth + 1, out);\n}\n\nfunction renderAuthoring(): string {\n const schema = jsonSchema as unknown as JsonSchemaNode;\n const required = schema.required ?? [];\n const sections: string[] = [];\n for (const [key, node] of Object.entries(schema.properties ?? {})) {\n if (key === '$schema') continue;\n const parts: string[] = [`## \\`${key}\\`${required.includes(key) ? '' : ' *(optional)*'}`];\n if (node.description) parts.push('', node.description);\n const bullets: string[] = [];\n for (const c of childEntries(node)) renderSchemaNode(c.label, c.node, c.required, 0, bullets);\n if (bullets.length) parts.push('', ...bullets);\n sections.push(parts.join('\\n'));\n }\n return `${frontmatter({\n type: 'Config Reference',\n title: 'Vitops — design-system.json authoring reference',\n description:\n 'Every field of the design-system.json config, generated from the published JSON Schema so it always matches validation.',\n resource: DS_PATH,\n tags: ['config', 'schema', 'authoring', 'design-system'],\n })}\n\n# \\`design-system.json\\` authoring reference\n\nThe single source of truth every output format is generated from. Each consumer authors\ntheir own config — there is no shared canonical token set. The field docs below are\nrendered from the published JSON Schema, so they always match what \\`vitops validate\\`\nenforces.\n\n- Set \\`\"$schema\": \"${SCHEMA_URL}\"\\` in the config for editor autocomplete + validation.\n- Scaffold a starter config with \\`vitops init\\`; check one with \\`vitops validate\\`.\n- **This can be a standalone file, or live inside a site config.** Anywhere the\n toolchain takes a config — \\`--input\\`, the Vite plugin, the Astro integration's\n \\`css.input\\` — that file may be a \\`design-system.json\\` or the larger site config\n that embeds one under \\`designSystem.themes.<name>\\`. They are told apart by shape,\n and the fields below are the same either way. A site config additionally supplies\n the site-level facts generation reads (its default colour scheme, legal documents,\n icon sprite), so the path is declared once rather than per option.\n- The *why* behind each section: [colour system](concepts/color.md),\n [type & space scales](concepts/scales.md), [component patterns](concepts/patterns.md).\n- What each output format does with these tokens: [formats.md](formats.md).\n\n${sections.join('\\n\\n')}\n`;\n}\n\n// ── Output formats reference ──────────────────────────────────────────────────\nfunction renderFormats(ds: DesignSystem): string {\n const clashList = Array.from(TW_CLASH).sort();\n const spaceName = ds.spaceScale?.baseline ?? ds.spaceScale?.names?.[0] ?? 'm';\n return `${frontmatter({\n type: 'Formats Reference',\n title: 'Vitops — output formats (tailwind vs css vs bricks vs design)',\n description:\n 'What each vitops generate format emits, what the target platform provides instead, and the Tailwind-specific rules (which framework utilities are stripped in favour of Tailwind defaults).',\n resource: DS_PATH,\n tags: ['formats', 'tailwind', 'bricks', 'css', 'design', 'design-system'],\n })}\n\n# Output formats — \\`tailwind\\` vs \\`css\\` vs \\`bricks\\` vs \\`design\\`\n\nOne config, four targets: \\`vitops generate --format <tailwind|css|bricks|design>\\`. Three of\nthem are stylesheets, and across those the **class vocabulary is the same** (see\n[css/classes.md](css/classes.md)); what differs is which layers the generator emits versus\nwhich the platform provides, and the variant separator (\\`-\\` in CSS/Bricks, \\`:\\` / \\`@\\` in\nTailwind). The fourth, \\`design\\`, emits no CSS at all.\n\n\\`--format\\` takes a comma-separated list, so the brief composes with a stylesheet:\n\\`vitops generate --format css,design\\`.\n\n## \\`tailwind\\` — single-file Tailwind v4 layer\n\nEmits one self-contained \\`tailwind.css\\` (plus \\`tokens.json\\`): \\`@import \"tailwindcss\"\\`,\n\\`@theme\\` tokens, the framework's structural CSS + component patterns inlined, and\n\\`@utility\\` definitions for the bespoke families (type roles, animation effects,\nsplit ratios, track placement).\n\n**Use Tailwind's own utilities for these class names.** The framework's rules for them are\ndeliberately stripped from the bundle because Tailwind provides them natively — writing\nthem still works, but they are Tailwind's, not the framework's:\n\n${clashList.map((c) => `\\`${c}\\``).join(', ')}\n\nOther Tailwind-specific behaviour:\n\n- **Variants are Tailwind's job.** No pre-expanded breakpoint/state classes are emitted\n (the framework's \\`@container (min-width: …)\\` **variant** blocks are dropped; component\n container queries such as the sitenav's desktop switch are kept); use Tailwind syntax —\n \\`@md:split-1-2\\`, \\`hover:flip-fade-in\\`. Container breakpoints are registered as\n \\`--container-{sm,md,lg,xl}\\` = 30/48/64/80rem, backing the \\`@sm:\\`…\\`@xl:\\` variants.\n\n > **Three spellings, and only two of them work here.**\n >\n > | you write | in \\`tailwind\\` | note |\n > | --- | --- | --- |\n > | \\`@md:flex-row\\` | ✅ container query | the framework's breakpoints (48rem) |\n > | \\`md:flex-row\\` | ✅ media query | **Tailwind's** breakpoints, which differ — \\`sm:\\` is 40rem where \\`@sm:\\` is 30rem |\n > | \\`md-flex-row\\` | ❌ silently nothing | the css/bricks spelling; not emitted in this format |\n >\n > \\`md-*\\` is the trap: it is a real class in \\`css\\`/\\`bricks\\` and a no-op here, and\n > nothing errors — the element simply never changes at the breakpoint. Prefer \\`@md:\\`\n > so one vocabulary of breakpoints applies throughout.\n\n- **Overriding \\`--container-*\\` also moves Tailwind's width scale.** Registering the\n framework breakpoints in \\`@theme\\` re-points \\`max-w-sm\\`…\\`max-w-xl\\` at the same values,\n so \\`max-w-md\\` is 48rem here rather than Tailwind's stock 28rem. Use\n \\`max-w-(--container-md)\\` style arbitrary values if you need to be explicit.\n- **The space scale is NOT mapped into Tailwind's \\`--spacing-*\\` namespace** (that would\n corrupt Tailwind's numeric multipliers and \\`max-w-*\\` sizes). Numeric utilities like\n \\`p-4\\` keep Tailwind's 0.25rem meaning; use the design-system scale via arbitrary\n values — \\`p-(--space-${spaceName})\\`, \\`gap-(--space-${spaceName})\\`.\n- **Functional colour roles are plain \\`:root\\` variables, not \\`@theme\\` colours**, so\n Tailwind doesn't auto-derive utilities from them; the emitted \\`@utility\\` set\n (\\`bg-<role>\\`, \\`text-<role>-muted\\`, …) is the public API. The raw hue scales ARE\n \\`@theme\\` colours, so native \\`bg-<hue>-500\\`-style utilities work.\n\n This split is deliberate and load-bearing. When a token sits in \\`@theme\\` *and* an\n \\`@utility\\` of the derived name exists, Tailwind merges both into one rule with the\n \\`@theme\\` declaration last — regardless of source order. Only palette hues belong in\n \\`@theme\\`, where nothing competes for the name. Role tokens stay in a plain \\`:root\\`\n block, and \\`format-parity.test.ts\\` derives that guard from the emitted token names so\n it cannot go quiet if the grammar moves again.\n- **\\`colors.utilities\\` is a floor here, not a ceiling.** It controls which families get\n explicit role \\`@utility\\` rules, exactly as in \\`css\\`/\\`bricks\\`. But the raw hue scales\n are \\`@theme\\` colours, and Tailwind derives *every* colour family from those on demand\n (\\`ring-\\`, \\`divide-\\`, \\`accent-\\`, \\`caret-\\`, …), so hue-step utilities you did not enable\n still resolve in this format.\n\n## \\`css\\` — standalone bundle\n\nEmits a bundled, self-contained \\`styles.css\\` + \\`tokens.json\\` + \\`design-manifest.json\\`.\nThe colour and font/scale layers are fully included, and every utility family is\npre-expanded — including breakpoint/state variants with \\`-\\` separators\n(\\`md-split-1-2\\`, \\`hover-fade-in\\`). For non-Bricks, non-Tailwind consumers and the\ndocs build.\n\n**Cascade layers.** The bundle ships three, in precedence order:\n\n\\`\\`\\`\n@layer vitops.base, vitops.components, vitops.utilities;\n\\`\\`\\`\n\n- \\`vitops.base\\` — the reset (\\`box-sizing: border-box\\` on every element and pseudo-element,\n a 16px root, no body margin) and the pure \\`:root\\` token blocks. Lowest of the three, so\n your own reset overrides it — unlayered, or from a layer you declare before \\`vitops.base\\`.\n- \\`vitops.components\\` — the animation engine, the structural patterns (\\`.rhythm\\`,\n \\`.centered\\`, \\`.region\\`, \\`.split\\`, \\`.reveal\\`) and every UI pattern.\n- \\`vitops.utilities\\` — \\`bg-*\\`, \\`text-*\\`, \\`border-*\\`, \\`drop-shadow-*\\`, \\`font-*\\`,\n \\`gap-*\\`, animation effects, the layout utilities (\\`.m-*\\`, \\`.flex-*\\`, \\`.items-*\\`,\n \\`.split-<a>-<b>\\`, track placement) and the display/\\`sr-only\\` families.\n\nSo a utility overrides a pattern: \\`class=\"card bg-danger-muted\"\\` tints the card,\n\\`class=\"split flex-col\"\\` stacks the split, \\`class=\"table text-center\"\\` centres the table.\nYour own unlayered CSS beats all three — see [concepts/patterns.md](concepts/patterns.md) for\nthe override story and the one gotcha (a reset must be layered and ordered first).\n\nThe classification is by RULE, not by file: a partial that mixes patterns and utilities is\nsplit in two rather than shelved whole. \\`layout.css\\` (patterns) and \\`layout-utilities.css\\`\n(utilities) are the same family in two files for exactly this reason, and the \\`tailwind\\`\nformat reaches the same arrangement by its own route — patterns in \\`@layer components\\`,\nutilities as \\`@utility\\`.\n\nKnown gap: the \\`typography.headings\\` bare-element bindings (\\`h1\\`, \\`h2\\`, \\`body\\`) are\nemitted alongside \\`.font-<role>\\` and so sit in \\`vitops.utilities\\`, where a tag rule\noutranks every pattern — \\`<h2 class=\"pull-quote\">\\` keeps the heading's font-size in\n\\`css\\`/\\`bricks\\` and the pattern's in \\`tailwind\\`, which puts the bindings in \\`@layer base\\`.\nGive the element a \\`.font-<role>\\` class to pin it either way.\n\n## \\`bricks\\` — WordPress / Bricks Builder payload\n\nEmits the full deployable theme payload: \\`styles.min.css\\`, the Bricks import JSONs\n(\\`bricks-colors-{named,semantic}.json\\`, \\`bricks-variables.json\\`), \\`tokens.json\\`, the JS\nbundles (polyfills / elements / deferred), the Bricks element PHP under \\`bricks/\\`, and\nthis docs bundle under \\`docs/\\`.\n\n- **Bricks provides the token layer.** \\`color.css\\` and \\`type-tokens.css\\` are one-line\n stubs: the colour \\`:root\\` tokens, dark-mode overrides, colour utility classes, fonts,\n and type/space scales are generated live by Bricks' Color / Font / Variables Managers\n from the imported JSONs. Semantic palette entries carry \\`darkModeEnabled\\` + a \\`dark\\` ref so\n Bricks emits the dark-mode overrides on import.\n- Everything else (patterns, shadows, typography roles, animation effects, structural\n framework CSS) ships in \\`styles.min.css\\` as in the other formats.\n- Pattern states reference shadows by name, compiled to\n \\`filter: drop-shadow(var(--shadow-<name>))\\`.\n\n## \\`design\\` — the agent-facing brief\n\nEmits exactly one file, \\`DESIGN.md\\`, in the\n[google-labs-code/design.md](https://github.com/google-labs-code/design.md) format: YAML\nfront matter carrying the tokens (\\`colors\\`, \\`typography\\`, \\`rounded\\`, \\`spacing\\`,\n\\`components\\`, with \\`{group.token}\\` references) followed by a prose body carrying the\nrationale. It is meant to be run with \\`--out .\\` — DESIGN.md conventionally sits at a repo\nroot beside \\`AGENTS.md\\`, not in a build directory.\n\n**No CSS, no \\`tokens.json\\`, nothing else.** This format is a description of the system for\na tool that has to work without it — a coding agent in another repo, a Figma import, a\ndesigner. It is not a build target, and \\`vitops lint\\` does not accept it.\n\nThree things the format cannot represent, and what is emitted instead:\n\n| Ours | Why it doesn't fit | Emitted as |\n| --- | --- | --- |\n| fluid \\`clamp()\\` type / space steps | a spec \\`Dimension\\` is a number + px/em/rem | the **max** (desktop) value, with the prose saying so |\n| the automatic dark flip | the spec has no notion of a second appearance | **light** values only, with the flip explained in prose |\n| a \\`50%\\` radius | same \\`Dimension\\` restriction | dropped from \\`rounded\\`, named in the Shapes prose |\n\nRole tokens are emitted as \\`{colors.<hue>-<step>}\\` **references** into the raw ramps rather\nthan flattened hexes, so the role → ramp lineage survives the export. \\`on-solid\\` is the\nexception — it is a computed contrast literal with no step behind it.\n\n\\`meta.name\\` / \\`meta.description\\` in \\`design-system.json\\` supply the brand name and the\nOverview paragraph; everything else is derived from the config, so the brief cannot drift\nfrom what the other three formats build.\n`;\n}\n\n// ── Concept docs (colour / scales / patterns) ─────────────────────────────────\nfunction renderColorConcept(ds: DesignSystem): string {\n const hues = Object.keys(ds.colors.palette ?? {});\n const roles = Object.keys(ds.colors.roles ?? {});\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops colour system — seeded scales, target-prefixed tokens, automatic dark mode',\n description:\n 'How palette hues become 11-step OKLCH scales on a shared lightness ladder, how semantic roles derive target-prefixed tokens from them, and how dark mode flips automatically.',\n resource: DS_PATH,\n tags: ['color', 'oklch', 'dark-mode', 'design-system'],\n })}\n\n# Colour system\n\nAuthoring is two maps in \\`design-system.json\\` (see [authoring.md](../authoring.md)):\n\\`colors.palette\\` (hues) and \\`colors.roles\\` (semantic role → hue). Everything else —\nscales, role tokens, utilities, dark mode — is derived.\n\n## From seed to scale\n\nEach palette hue becomes an **11-step numeric OKLCH scale**, \\`--color-<hue>-50…950\\`,\nrunning tinted near-white → tinted near-black. Two authoring modes:\n\n- **Seeded** (\\`{ seed, anchors? }\\`): the scale is generated from one colour. The seed is\n preserved at its natural lightness step; \\`anchors\\` pin specific steps and the rest\n interpolate around them.\n- **Fixed** (\\`{ tones }\\`): a brand kit used verbatim — each authored tone lands at its\n nearest step, endpoints are tinted off-white/off-black, no interpolation.\n\nCurrent hues: ${code(hues)}.\n\n## The token grammar\n\nEvery colour token is named:\n\n\\`\\`\\`\n--color-<target>-<role>[-<variant>] target ∈ bg | text | icon | border\n\\`\\`\\`\n\nThe target sits **inside** the name on purpose. \\`--color-bg-danger-muted\\` and\n\\`--color-text-danger-muted\\` are different tokens, so there is nothing to arbitrate between\nthem — an earlier grammar put both on one \\`<family>-<role>-<modifier>\\` name and needed a\nprecedence rule, which made half the variants unreachable and the rest non-monotonic.\n\n**The token name is also the utility class name**, minus the \\`--color-\\` prefix. Write\n\\`class=\"bg-danger-muted\"\\` and you are using \\`--color-bg-danger-muted\\`. One vocabulary, not\ntwo (see [css/classes.md](../css/classes.md)).\n\nVariants are ordinal — \\`xx-muted\\` < \\`x-muted\\` < \\`muted\\` < (bare) < \\`bold\\` < \\`x-bold\\` — and\nthe tables are **sparse**: only cells that actually hold their contrast target exist.\n\\`bold\\` means *more emphatic in the current appearance*, not darker.\n\n## Role kinds\n\nA role in \\`colors.roles\\` (currently ${code(roles)}) is one of two kinds, and the kind decides\nwhich tokens exist:\n\n- **\\`surface\\`** — a page or panel colour. \\`bg-<role>\\` is the card, \\`bg-<role>-muted\\` the page\n behind it, \\`bg-<role>-x-muted\\` a well, \\`bg-<role>-bold\\` the inverse surface a tooltip sits\n on. Full text scale, and \\`border-<role>-bold\\` as the contrast-guaranteed boundary.\n- **\\`chromatic\\`** (the default, and what the bare-string form means) — a signal colour.\n Backgrounds split into *tints* (\\`bg-<role>-x-muted\\`, \\`bg-<role>-muted\\`) and *solids*\n (\\`bg-<role>-solid\\`, \\`-solid-bold\\`, \\`-solid-x-bold\\`). There is deliberately **no bare\n \\`bg-<role>\\`**: \"how loud?\" is a question the author answers. \\`text-on-<role>\\` is the\n guaranteed foreground for the solid family.\n\nPlus \\`--surface-glass\\` (translucent surface), \\`--overlay\\` (scrim) and\n\\`--color-border-focus\\` (the focus ring, taken from \\`ui-primary\\`'s solid tone).\n\n## Automatic dark mode\n\nDark mode re-points which step each token reads, under \\`${DARK_SEL}\\`:\nbackground and text ends of each scale swap, while the **solid family stays mode-stable**\nalong with the \\`text-on-<role>\\` foreground computed against it — so a filled button keeps\nits identity when the appearance flips. There is no per-appearance scheme grammar to author\nand no named steps: a role token means the same *job* in both appearances.\n\nRaw hue steps (\\`--color-<hue>-<step>\\`) are the exception — they are fixed values and are\n**not** re-pointed. Reach for a role token unless you specifically want a colour that\nignores the appearance.\n\nTwo attributes, one flip: \\`data-brx-theme\\` is Bricks' own (Bricks sets it on the\nWordPress target), \\`data-theme\\` is what the shipped \\`<color-scheme-toggle>\\` writes on\n\\`<html>\\`, so the toggle works on every other target. Set either.\n\nThe OS preference is a **second, opt-in block**. Set\n\\`designSystem.defaultColorScheme: \"system\"\\` in your site config and the same delta is emitted again inside\n\\`@media (prefers-color-scheme: dark)\\`, under\n\\`${SYSTEM_DARK_SEL}\\` — i.e. whenever no explicit choice has been made. That is what makes\n\\`<color-scheme-toggle>\\`'s \"System\" position resolve to the OS (it *removes* the attribute,\nso without this block it fell through to light), and it gives a no-JS page the OS\nappearance, which the toggle alone never could. An explicit light choice still wins.\n\nIt is opt-in rather than default because turning it on flips a site dark for dark-OS\nvisitors, which is the site's decision and not the design system's.\n\n## Contrast guarantees\n\nEnforced **at build time** — a violation fails \\`generate\\`, so an unreadable pairing cannot\nship. In both appearances:\n\n| tier | target | applies to |\n| --- | --- | --- |\n| text | APCA Lc ≥ 75 | \\`text-<role>\\` on the role's primary background |\n| secondary | Lc ≥ 60 | text on any other background plane; \\`text-<role>-muted\\`; \\`text-on-<role>\\` on its solid |\n| non-text | Lc ≥ 45 | \\`icon-<role>\\`, and a surface role's \\`border-<role>-bold\\` |\n\nTwo deliberate exemptions: \\`text-<role>-x-muted\\` (placeholders) and \\`-xx-muted\\` (disabled\ntext) are *required* to look unavailable, and holding them to the body-text bar would defeat\nthe affordance. Nothing else is exempt.\n\nChromatic text is checked against the **surface planes it actually sits on**, not only its\nown tints — coloured text appears over the page far more often than over its own wash.\n\nA \\`tones\\` kit thin enough that snapping can't cover a tier is reported rather than shipped;\nthe fix is another tone, and the failure says so.\n`;\n}\n\nfunction renderScalesConcept(ds: DesignSystem): string {\n const t = ds.typeScale;\n const s = ds.spaceScale;\n const scaleLine = (label: string, sc: typeof t): string =>\n sc\n ? `- **${label}**: base \\`${sc.base}\\` at step \\`${sc.names?.[(sc.baseStep ?? 1) - 1] ?? sc.baseStep}\\`, ratio ${sc.ratio}${sc.fluid ? ` (${sc.fluid.minRatio} below ${sc.fluid.minVw})` : ''}; steps ${code(sc.names ?? [])}.`\n : `- **${label}**: not configured.`;\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops type & space scales — fluid modular scales',\n description:\n 'How typeScale and spaceScale compile to clamp()-based fluid modular scales, and which utilities consume the resulting tokens.',\n resource: DS_PATH,\n tags: ['typography', 'spacing', 'fluid', 'modular-scale', 'design-system'],\n })}\n\n# Type & space scales\n\nBoth scales share one model (authored in \\`design-system.json\\` as \\`typeScale\\` /\n\\`spaceScale\\` — see [authoring.md](../authoring.md)): a **fluid modular scale**.\n\n## The model\n\n- \\`base\\` anchors the value at \\`baseStep\\`; every other step is a power of the \\`ratio\\`\n away (step n = base × ratio^(n − baseStep)).\n- With \\`fluid\\`, each step compiles to a **\\`clamp()\\`**: the scale uses \\`fluid.minRatio\\`\n at/below \\`fluid.minVw\\` and grows to \\`ratio\\` at \\`fluid.maxVw\\`, interpolating between —\n so large steps spread apart on wide viewports and compress on phones, with no\n breakpoint jumps. \\`baseline\\` names the pivot step that stays closest to \\`base\\`.\n- \\`names\\` become the token suffixes.\n\n${scaleLine('Type', t)}\n${scaleLine('Space', s)}\n\n## What consumes them\n\n- **Type**: \\`--text-<name>\\` tokens → typography role sizes (\\`font-<role>\\` classes,\n heading defaults) and text-size utilities.\n- **Space**: \\`--space-<name>\\` tokens → gap (\\`g\\`), spacing utilities, and \\`rhythm\\`\n (relationship-based vertical margins between headings, paragraphs, lists, media).\n Prefer \\`rhythm\\` for vertical flow over per-element margins.\n- In the \\`tailwind\\` format these stay in their own namespaces (\\`--text-*\\` via \\`@theme\\`,\n \\`--space-*\\` as plain vars) — see [formats.md](../formats.md) for why \\`--spacing-*\\` is\n deliberately not used.\n`;\n}\n\nfunction renderPatternsConcept(ds: DesignSystem): string {\n const items = (ds.patterns?.items ?? {}) as Record<string, { group?: string }>;\n const groups = Object.keys(ds.patterns?.groups ?? {});\n const patternNames = Object.keys(items);\n const hookTable = Object.entries(BASE_HOOK)\n .map(([prop, sfx]) => `| \\`${prop}\\` | \\`--${sfx}-<pattern>\\` |`)\n .join('\\n');\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops component patterns — token cascade, override hooks, states',\n description:\n 'How pattern CSS is assembled: the token cascade (defaults → groups → per-pattern overrides), per-pattern override-hook variables, state shortcuts, and role variants.',\n resource: DS_PATH,\n tags: ['patterns', 'components', 'cascade', 'css', 'design-system'],\n })}\n\n# Component patterns — the CSS chain\n\nPatterns (currently ${code(patternNames)}) are authored declaratively under \\`patterns\\` in\n\\`design-system.json\\` (see [authoring.md](../authoring.md)) and compiled to CSS in a\n**components cascade layer** — so utility classes, which live in a later layer, always win over\npattern styling without specificity fights. \\`class=\"card bg-danger-muted\"\\` tints the card.\n\nThe layer names differ by format, because each defers to its host:\n\n| format | layer stack (last wins) |\n| --- | --- |\n| \\`css\\`, \\`bricks\\` | \\`vitops.base\\` → \\`vitops.components\\` → \\`vitops.utilities\\` |\n| \\`tailwind\\` | Tailwind's own \\`theme\\` → \\`base\\` → \\`components\\` → \\`utilities\\` |\n\n**Your own CSS beats all of it.** Unlayered styles outrank every cascade layer regardless of\nspecificity, so a plain stylesheet, an Astro scoped \\`<style>\\`, or a Bricks-authored class\noverrides the framework with no \\`!important\\` and no specificity escalation. That is the\nintended override story.\n\nThe one thing to watch: a **reset** must be layered too, and ordered *below* the framework —\nleft unlayered it beats the very component rules it is meant to sit under (a bare\n\\`p { margin: 0 }\\` would defeat \\`.rhythm\\`). Declare the order before you load the stylesheet,\nsince layer precedence is fixed by first declaration:\n\n\\`\\`\\`html\n<style>@layer my.reset, vitops.base, vitops.components, vitops.utilities;</style>\n<link rel=\"stylesheet\" href=\"/styles.css\">\n\\`\\`\\`\n\nPut it *after* the link and \\`my.reset\\` becomes a new name introduced later — which sorts\n**last**, i.e. highest priority, and the reset wins. That is the one non-obvious step.\n\n## 1 — Token cascade\n\nShared geometry resolves through a variable chain, most-specific first:\n\n- \\`patterns.defaults\\` → \\`--<prop>-default\\` (cascade-wide fallbacks).\n- \\`patterns.groups.<group>\\` → \\`--<prop>-<group>\\` (e.g. groups ${code(groups)}); a pattern\n opts in via its \\`group\\` key.\n- Per-pattern: each grouped pattern gets aliases \\`--<prop>-<name>-group\\` →\n \\`var(--<prop>-<group>)\\`, and \\`overrides\\` replace individual aliases with literal values.\n- \\`patterns.radii\\` → \\`--br-<name>\\` shape primitives; \\`patterns.z\\` → \\`--z-tier-<name>\\`.\n\n## 2 — Base declarations & override hooks\n\nEach pattern's \\`base\\` block is emitted on its selector:\n\n- \\`class\\` only → \\`.<class ?? name>\\`, at normal class specificity.\n- \\`element\\` only → a **zero-specificity** \\`:where(<element>)\\` rule, so author CSS can always\n override it.\n- **both** → one \\`:where(<element>, .<class>)\\` rule (e.g. \\`:where(button, .btn)\\`). The element\n gets the styling with no class needed, the class carries it to any other tag, and — because the\n whole thing sits at zero specificity — any explicit class wins, including a louder pattern\n (\\`.cta\\`) or a component's own rule (\\`.dialog__close\\`).\n\nGeometry properties are wrapped in a **per-pattern override hook**:\n\n| base property | hook variable |\n| --- | --- |\n${hookTable}\n\ne.g. \\`padding: var(--p-btn, 0.4em 0.8em)\\` — a consumer restyles every button by setting\n\\`--p-btn\\` on \\`:root\\`, without touching the pattern. The hook is named after the pattern's\n**key**, not its class.\n\n\\`background\\` and \\`background-color\\` share the \\`bg\\` hook, since a pattern may author either.\nThat is what makes a pattern's fill **undoable** — a flat, border-only card:\n\n\\`\\`\\`html\n<!-- via the hook: applies wherever you set it, including :root for all cards -->\n<div class=\"card\" style=\"--bg-card: transparent; --ds-card: none\">…</div>\n\n<!-- or compose a utility, which reads better inline and is what most authors want -->\n<div class=\"card bg-transparent\" style=\"--ds-card: none\">…</div>\n\\`\\`\\`\n\n\\`bg-transparent\\` and \\`bg-inherit\\` are emitted for \\`css\\`/\\`bricks\\`; in \\`tailwind\\` they\ncome from Tailwind itself. There is no utility for the shadow, so \\`--ds-card: none\\` is the\nway to drop it in every format.\n\nRole variants are emitted as their own rules and are **not** wrapped, so setting \\`--bg-card\\`\ntunes the default fill without silently defeating \\`.card-danger\\`.\n\n## 3 — States\n\n\\`states\\` (hover / active / focus-visible) compile from shortcuts:\n\n- \\`step: n\\` — intensify the pattern's colour one rung: fills swap\n \\`--color-bg-<role>-solid\\` → \\`-solid-bold\\`; text patterns swap\n \\`--color-text-<role>\\` → \\`--color-text-<role>-bold\\`.\n- \\`scale: 0.97\\` — transform scale; \\`lift: \"<length>\"\\` — \\`translate: 0 calc(-1 * <length>)\\`.\n- \\`shadow: \"<name>\"\\` — \\`filter: drop-shadow(var(--shadow-<name>))\\`; \\`shadow: true\\` — the\n generic lift box-shadow.\n- \\`ring: true\\` — focus ring (\\`box-shadow\\` in the role's solid tone, or\n \\`--color-border-focus\\` when the pattern has no role; outline removed).\n- \\`css: { … }\\` — raw declarations escape hatch.\n\nAny pattern with states also gets a composed transition block (translate / scale / filter /\nbox-shadow / colours, \\`--interact-duration\\` / \\`--interact-easing\\` overridable). Hover\nrules are wrapped in \\`@media (hover: hover)\\` so touch devices never stick.\n\n## 4 — Role variants\n\n\\`roles\\` lists semantic colour variants: class patterns emit \\`.<pattern>-<role>\\`\n(\\`.badge-success\\`). A pattern with an \\`element\\` emits both the bare role class on the\nelement and the \\`-<role>\\` form (\\`:where(button, .btn).danger, .btn-danger\\`), so the same\nvariant works on a non-element host — both at class specificity, so neither outranks a\nplain class. Fill\npatterns set \\`background-color: var(--color-bg-<role>-solid)\\` +\n\\`color: var(--color-text-on-<role>)\\`; text patterns use \\`var(--color-text-<role>)\\`, the\ntoken guaranteed legible over a surface in both appearances. \\`default_role\\` colours the\nbare, unsuffixed pattern. States re-apply per variant with the variant's role.\n`;\n}\n\n// ── Reserved index.md listings (no frontmatter) ──────────────────────────────\nfunction renderTopIndex(): string {\n return `${INDEX_NOTE}\n\n# Vitops design system\n\nLLM-oriented documentation bundle (Open Knowledge Format) for the Vitops design system — a\nvariable-driven CSS framework plus progressively-enhanced web components, generated from\n\\`design-system.json\\` and published alongside the deployed theme.\n\n# Contents\n\n* [Authoring reference](authoring.md) - every design-system.json field, generated from the JSON Schema\n* [Output formats](formats.md) - tailwind vs css vs bricks vs design: what's emitted, what the platform provides, which utilities Tailwind owns\n* [Concepts](concepts/) - the colour system, type/space scales, and pattern CSS architecture\n* [CSS framework](css/) - the class vocabulary (colour, type, space, layout, animation, component patterns), stated as naming rules\n* [Bricks Builder](bricks/) - custom elements and how to style them\n`;\n}\n\nfunction renderIconsConcept(): string {\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops icons — one semantic vocabulary across icon sets',\n description:\n 'Semantic icon names that resolve per configured set, how the bundle is derived on a server build, and the three delivery paths (astro-icon, astro-iconset, SVG sprite).',\n resource: DS_PATH,\n tags: ['icons', 'svg', 'sprite', 'astro-icon', 'design-system'],\n })}\n\n# Icons\n\nIcons are named by **meaning**, not by set. \\`menu\\` resolves to \\`fa7-solid:bars\\`,\n\\`lucide:menu\\` or \\`ph:list\\` depending on which set the site configures, so changing\nsets is a config edit rather than a find-and-replace across templates.\n\nThe escape hatch is deliberate and always available: **a name containing \\`:\\` passes\nthrough untouched**. \\`<Icon name=\"simple-icons:zoho\" />\\` renders that exact glyph\nwhether or not the semantic map knows it.\n\n## Declaring them\n\nThe \\`icons\\` block lives in the **site config**, not \\`design-system.json\\` — it\ndescribes what a site uses, not what the design system defines.\n\n\\`\\`\\`json\n{\n \"icons\": {\n \"ui\": \"ph\",\n \"brand\": \"simple-icons\",\n \"weight\": \"bold\",\n \"semantic\": [\"menu\", \"close\", \"arrow-right\"],\n \"simple-icons\": [\"zoho\", \"cloudflare\"],\n \"sprite\": true\n }\n}\n\\`\\`\\`\n\n\\`ui\\` and \\`brand\\` pick which set a semantic name resolves against. Any other key is\nan iconify collection name with an explicit list, passed through verbatim.\n\n**\\`weight\\` is only meaningful for sets that encode weight in the icon NAME.**\nPhosphor does (\\`list\\`, \\`list-bold\\`, \\`list-fill\\`), so \\`ph\\` accepts it; Font Awesome\nsplits weights across collections instead (\\`fa7-solid\\` vs \\`fa7-regular\\`), so there\nthe weight is part of the prefix and this key is ignored.\n\n## Why the bundle list exists\n\nastro-icon is **zero-config on a static build**. Under \\`output: 'server'\\` it bundles\n*every icon in a set* unless given an \\`include\\` map — which is why projects end up\nhand-maintaining one.\n\nThe \\`icons\\` option on \\`getvitops()\\` derives it by scanning your source, merged with\nwhatever you declare. On a static build **no include is passed at all**: there is\nnothing to trim there, and a list could only drop a glyph the scan couldn't see.\n\nTwo failure modes, treated differently on purpose:\n\n- A name you **declared** that doesn't resolve is a config error and **throws**.\n- A name only the **scan** found and can't resolve just **warns** — a bare unmapped\n name is more often a local \\`src/icons/*.svg\\` than a mistake, and a dev server\n that dies on a template typo is worse than one that tells you.\n\nNames computed at runtime (\\`<Icon name={expr} />\\`) can't be read statically. They are\nreported with file and line, never guessed at — declare them in \\`semantic\\` or a\nper-set list. Run \\`vitops icons\\` to see the whole report.\n\n## Delivery\n\n| Path | Used by | Needs |\n| --- | --- | --- |\n| \\`astro-icon\\` / \\`astro-iconset\\` | Astro sites | the integration, an optional peer |\n| **SVG sprite** (\\`icons.svg\\`) | Bricks/WordPress, EmDash renderers, plain HTML | \\`icons.sprite: true\\` |\n\nThe sprite is the no-JavaScript path: \\`<svg><use href=\"/vitops/icons.svg#ph--list\"></svg>\\`.\nIds are the qualified name with \\`:\\` replaced by \\`--\\` (\\`:\\` is not valid in a fragment\nidentifier), **plus a set-independent \\`icon-<name>\\` alias for every semantic name** —\nso sprite markup survives an icon-set change the same way \\`resolveIcon\\` protects Astro\ncall sites.\n\nIn WordPress, \\`vitops_icon('menu')\\` and \\`[vitops_icon name=\"menu\"]\\` emit that markup,\nand a **Vitops → Icon** Bricks element wraps the same helper.\n\n⚠️ An external-file \\`<use>\\` is **same-origin only** and dead under \\`file://\\`. Serving\n\\`dist/\\` from a different origin makes every icon vanish with no console error.\n\n## Markup\n\nAlways the framework's \\`.icon\\` box:\n\n\\`\\`\\`html\n<span class=\"icon\" aria-hidden=\"true\"><svg>…</svg></span>\n\\`\\`\\`\n\n\\`.icon\\` sizes in \\`em\\` via \\`--icon-size\\` (default \\`1.25em\\`) and sets \\`fill: currentColor\\`,\nso an icon inherits the colour of whatever it sits in. Because \\`.cta\\` and\n\\`:where(button, .btn)\\` are already \\`inline-flex\\` with a \\`gap\\`, **a start or end icon is\nchild order — not a modifier class**.\n\nIcons are \\`aria-hidden\\` by default. Pass a label only when the icon carries meaning on\nits own; beside a text label it would be announced twice.\n\nNote \\`.icon-mask\\` is a different thing: the CSS-only adornment path used by\n\\`.link--icon::before\\`, where the glyph is a \\`mask-image\\` on a pseudo-element and there\nis no markup to hang an \\`<svg>\\` on.\n`;\n}\n\nfunction renderConceptsIndex(): string {\n return `${INDEX_NOTE}\n\n# Design-system concepts\n\n# Contents\n\n* [Colour system](color.md) - seeded OKLCH scales on a shared lightness ladder, target-prefixed tokens, automatic dark mode\n* [Type & space scales](scales.md) - fluid modular scales and the tokens they emit\n* [Component patterns](patterns.md) - token cascade, override hooks, states, role variants\n* [Icons](icons.md) - semantic names across icon sets, bundle derivation, sprite delivery\n`;\n}\n\nfunction renderCssIndex(): string {\n return `${INDEX_NOTE}\n\n# CSS framework\n\n# Contents\n\n* [Class vocabulary](classes.md) - every utility and component class, summarized by naming rule\n`;\n}\n\nfunction renderBricksIndex(): string {\n return `${INDEX_NOTE}\n\n# Bricks Builder integration\n\n# Styling\n\nPrefer adding the framework **CSS classes** — see [/css/classes.md](../css/classes.md) — in a\nBricks element's \"CSS classes\" field over hand-setting spacing, colour, or typography through\nthe Bricks Builder property panels. The classes encode the design system's tokens, responsive\ngrammar, and interaction states, so they stay consistent, respond to theme / dark mode, and\nupdate with the system. Values typed directly into Bricks' property controls are one-off,\ndrift from the system, and don't react to theme changes — reserve them for genuinely bespoke,\none-element cases.\n\n# Contents\n\n* [Elements reference](elements.md) - every custom Vitops element, its controls, defaults, seeded children and keywords\n* [Class vocabulary](../css/classes.md) - the framework CSS classes to apply to elements\n`;\n}\n\n/**\n * Build the OKF docs bundle for a config. Returns a `{ relPath: content }` map;\n * the caller writes it wherever the bundle should live (e.g. `<outDir>/docs`).\n */\nexport function generateDocs(ds: DesignSystem, assetsDir: string): Record<string, string> {\n const elementsDir = join(assetsDir, 'bricks', 'elements');\n return {\n 'index.md': renderTopIndex(),\n 'authoring.md': renderAuthoring(),\n 'formats.md': renderFormats(ds),\n 'concepts/index.md': renderConceptsIndex(),\n 'concepts/color.md': renderColorConcept(ds),\n 'concepts/scales.md': renderScalesConcept(ds),\n 'concepts/patterns.md': renderPatternsConcept(ds),\n 'concepts/icons.md': renderIconsConcept(),\n 'css/index.md': renderCssIndex(),\n 'css/classes.md': renderCssClasses(ds),\n 'bricks/index.md': renderBricksIndex(),\n 'bricks/elements.md': renderElementsDoc(elementsDir),\n };\n}\n","/**\n * `DESIGN.md` emitter — the `design` format.\n *\n * DESIGN.md (google-labs-code/design.md, alpha) is a single plain-text file that\n * gives AI coding agents a persistent, structured understanding of a visual\n * identity: YAML front matter carrying the tokens, then a prose body carrying the\n * *why*. It is the agent-facing sibling of `tokens.json` — where that file is a\n * verbatim dump for programmatic consumers, this one is curated for a reader.\n *\n * Three impedance mismatches between our schema and the spec, resolved the same\n * way every time (and stated in the prose so the file is self-describing):\n *\n * • **Fluid sizes are `clamp()`**; a spec `Dimension` is a bare number + px/em/rem.\n * → Emit the scale's **max** rem as the canonical size and say in the prose that\n * the real token is fluid. A `clamp()` string would fail every consumer's parse.\n * • **Dark mode has no first-class representation.** → `colors` carries the LIGHT\n * values; the Colors prose explains that the framework flips functionally at\n * runtime, so an agent that uses the role tokens gets dark mode for free and\n * should never hand-pick a dark value.\n * • **A role is not a ramp alias.** Functional tokens resolve to a ramp step, so\n * they are emitted as `{colors.<hue>-<step>}` **references** rather than\n * flattened hexes — that keeps the role → ramp lineage visible in the file,\n * which is the one thing a flattened export destroys. `on-solid` is the\n * exception: it is a computed contrast literal with no step behind it.\n */\nimport type { DesignSystem } from './schema.ts';\nimport { DARK_SEL, type RoleSpec, roleHue } from './shared.ts';\nimport { tokenClass, type ExpandedHue, type FunctionalRole } from './tokens.ts';\n\n/** Structural view of `generate.ts`'s ScaleStep (kept local to avoid a cycle). */\ninterface Step {\n name: string;\n value: string;\n max: string;\n}\n\nexport interface DesignMdCtx {\n ds: DesignSystem;\n expandedPalette: Record<string, ExpandedHue>;\n scaleRoles: FunctionalRole[];\n typeSteps: Step[];\n spaceSteps: Step[];\n shadows: Record<string, string> | undefined;\n}\n\ninterface PatternItem {\n group?: string;\n overrides?: Record<string, string>;\n element?: string;\n class?: string;\n fill?: boolean;\n default_role?: string;\n base?: Record<string, string>;\n states?: Record<string, Record<string, unknown>>;\n roles?: string[];\n}\n\n// ── minimal YAML writer ───────────────────────────────────────────────────────\n// Hand-rolled rather than pulled in as a dependency: the generator emits a fixed,\n// known shape (scalars two levels deep), and every string is double-quoted so\n// nothing here has to reason about YAML's plain-scalar edge cases — `#RRGGBB`\n// starting a comment, `{colors.x}` reading as a flow mapping, `2xl` as a key.\nconst q = (s: string) => `\"${s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n/** Keys are quoted only when they would not survive as a plain scalar. */\nconst key = (k: string) => (/^[A-Za-z_][A-Za-z0-9_-]*$/.test(k) ? k : q(k));\nconst scalar = (v: string | number) => (typeof v === 'number' ? String(v) : q(v));\n\nconst yamlMap = (name: string, entries: [string, string | number][], indent = ''): string =>\n entries.length === 0\n ? ''\n : `${indent}${name}:\\n` +\n entries.map(([k, v]) => `${indent} ${key(k)}: ${scalar(v)}`).join('\\n') +\n '\\n';\n\n// ── value resolution ──────────────────────────────────────────────────────────\n/** `var(--x)` → `x`, else undefined. Tolerates a fallback: `var(--x, y)` → `x`. */\nconst varName = (v: string): string | undefined => {\n const m = /^var\\(\\s*--([a-z0-9-]+)\\s*(?:,[^)]*)?\\)$/i.exec(v.trim());\n return m ? (m[1] as string) : undefined;\n};\n\n/** A spec `Dimension` is a number plus px / em / rem — nothing else parses. */\nconst isDimension = (v: string) => /^-?(?:\\d+\\.?\\d*|\\.\\d+)(?:px|em|rem)$/.test(v.trim());\n\n/**\n * Only these reach a `Color` slot. `inherit` / `currentColor` / `initial` are\n * valid CSS in a pattern's `base` and meaningless as a token value, so a\n * component that says `color: inherit` emits no `textColor` at all rather than\n * an unresolvable one.\n */\nconst isColorLiteral = (v: string) =>\n /^#[0-9a-f]{3,8}$/i.test(v.trim()) ||\n /^(?:rgba?|hsla?|hwb|oklch|oklab|lch|lab|color-mix)\\(/i.test(v.trim()) ||\n /^(?:transparent|white|black)$/i.test(v.trim());\n\nexport function emitDesignMd(ctx: DesignMdCtx): string {\n const { ds, expandedPalette, scaleRoles, typeSteps, spaceSteps, shadows } = ctx;\n const meta = ds.meta ?? {};\n const name = meta.name ?? 'Design System';\n const roleMap = ds.colors.roles as Record<string, RoleSpec>;\n const patterns = ds.patterns ?? {};\n const pDefaults = (patterns.defaults ?? {}) as Record<string, string>;\n const pRadii = (patterns.radii ?? {}) as Record<string, string>;\n const pGroups = (patterns.groups ?? {}) as Record<string, Record<string, string>>;\n const pItems = (patterns.items ?? {}) as Record<string, PatternItem>;\n\n // ── colors ─────────────────────────────────────────────────────────────────\n // Raw ramps first (they are what everything else references), then the\n // functional role tokens as refs into them, then the spec's recommended names\n // as refs into those. Three layers, each one hop from the last.\n const ramps: [string, string][] = [];\n for (const [hue, expanded] of Object.entries(expandedPalette))\n for (const [step, hex] of Object.entries(expanded.numeric)) ramps.push([`${hue}-${step}`, hex]);\n\n const rampNames = new Set(ramps.map(([k]) => k));\n /** `var(--color-<hue>-<step>)` → `{colors.<hue>-<step>}`; literals pass through. */\n const rampRef = (value: string): string => {\n const v = varName(value);\n const bare = v?.startsWith('color-') ? v.slice('color-'.length) : undefined;\n return bare && rampNames.has(bare) ? `{colors.${bare}}` : value;\n };\n\n const roleTokens: [string, string][] = [];\n for (const fr of scaleRoles)\n for (const [token, value] of Object.entries(fr.light))\n // Flattened as the utility class name (`bg-surface`, `text-on-danger`) —\n // the same string an agent would write in markup, so the brief and the\n // markup vocabulary are one thing rather than two.\n roleTokens.push([tokenClass(fr.role, token), rampRef(value)]);\n\n const colorNames = new Set([...rampNames, ...roleTokens.map(([k]) => k)]);\n /** Recommended-name alias, emitted only when the role behind it exists. */\n const aliasAs = (as: string, token: string): [string, string][] =>\n colorNames.has(token) ? [[as, `{colors.${token}}`]] : [];\n // The spec's non-normative recommended names (`primary`, `on-primary`,\n // `error`, …). Ours are role-scoped, so nothing here is a new value — each is\n // a one-hop reference, which is exactly what makes a generic DESIGN.md\n // consumer (and the linter's `primary`-must-exist rule) work against a\n // vocabulary that never uses those words.\n const interop: [string, string][] = [\n ...aliasAs('primary', 'bg-ui-primary-solid'),\n ...aliasAs('on-primary', 'text-on-ui-primary'),\n ...aliasAs('secondary', 'bg-ui-secondary-solid'),\n ...aliasAs('on-secondary', 'text-on-ui-secondary'),\n ...aliasAs('tertiary', 'bg-ui-accent-solid'),\n ...aliasAs('on-tertiary', 'text-on-ui-accent'),\n ...aliasAs('neutral', 'bg-neutral'),\n ...aliasAs('surface', 'bg-surface'),\n ...aliasAs('on-surface', 'text-surface'),\n ...aliasAs('error', 'bg-danger-solid'),\n ...aliasAs('on-error', 'text-on-danger'),\n ];\n\n // ── typography ─────────────────────────────────────────────────────────────\n const fonts = (ds.fonts ?? {}) as Record<string, string>;\n const families = (ds.typography?.families ?? {}) as Record<string, string>;\n /** `display` → `var(--font-display)` → the actual stack. */\n const fontStack = (family: string | undefined): string | undefined => {\n if (!family) return undefined;\n const declared = families[family];\n if (declared == null) return fonts[family];\n const v = varName(declared);\n const bare = v?.startsWith('font-') ? v.slice('font-'.length) : undefined;\n return (bare && fonts[bare]) ?? declared;\n };\n const textMax = new Map(typeSteps.map((s) => [s.name, s.max]));\n /** `var(--text-3xl)` → that step's MAX rem (a clamp() is not a Dimension). */\n const typeSize = (size: string | number | undefined): string | undefined => {\n if (size == null) return undefined;\n const raw = String(size);\n const v = varName(raw);\n const bare = v?.startsWith('text-') ? v.slice('text-'.length) : undefined;\n const resolved = bare != null ? textMax.get(bare) : raw;\n return resolved != null && isDimension(resolved) ? resolved : undefined;\n };\n\n const typoRoles = (ds.typography?.roles ?? {}) as Record<\n string,\n Record<string, string | number | undefined>\n >;\n const typography: [string, [string, string | number][]][] = [];\n for (const [role, spec] of Object.entries(typoRoles)) {\n const props: [string, string | number][] = [];\n const stack = fontStack(spec.family as string | undefined);\n if (stack) props.push(['fontFamily', stack]);\n const size = typeSize(spec.size);\n if (size) props.push(['fontSize', size]);\n if (spec.weight != null) props.push(['fontWeight', Number(spec.weight)]);\n const lh = spec['line-height'];\n if (lh != null) {\n const n = Number(lh);\n props.push(['lineHeight', Number.isFinite(n) ? n : String(lh)]);\n }\n const tracking = spec.tracking;\n if (tracking != null && isDimension(String(tracking)))\n props.push(['letterSpacing', String(tracking)]);\n if (props.length) typography.push([role, props]);\n }\n\n // ── rounded ────────────────────────────────────────────────────────────────\n // DEFAULT + the named radii + one entry per pattern GROUP, because a component\n // references its group's radius (`{rounded.control}`), not a bare literal —\n // the group alias layer is the whole point of the cascade.\n //\n // A spec `Dimension` is a number plus px/em/rem, so a bare `0` is rejected\n // even though it is perfectly good CSS: normalise it to `0px`, which is the\n // same value in every context a radius is used. A radius that is genuinely not\n // a Dimension (`50%`, for a circle) cannot be normalised and is dropped from\n // the map rather than emitted as an error — `unroundable` carries it into the\n // Shapes prose so it is stated, not lost.\n const unroundable: [string, string][] = [];\n const asDimension = (v: string): string | undefined => {\n const t = v.trim();\n if (isDimension(t)) return t;\n return /^-?0+(?:\\.0+)?$/.test(t) ? '0px' : undefined;\n };\n const rounded: [string, string][] = [];\n const pushRadius = (name: string, value: string) => {\n const dim = asDimension(value);\n if (dim) rounded.push([name, dim]);\n else unroundable.push([name, value]);\n };\n if (pDefaults.br) pushRadius('DEFAULT', pDefaults.br);\n for (const [n, v] of Object.entries(pRadii)) pushRadius(n, v);\n const roundedNames = new Set(rounded.map(([k]) => k));\n /** `var(--br-default)` → `{rounded.DEFAULT}`, `var(--br-pill, 999px)` → `{rounded.pill}`. */\n const roundedRef = (value: string): string => {\n const v = varName(value);\n const bare = v?.startsWith('br-') ? v.slice('br-'.length) : undefined;\n if (bare === 'default') return '{rounded.DEFAULT}';\n return bare && roundedNames.has(bare) ? `{rounded.${bare}}` : value;\n };\n for (const [group, props] of Object.entries(pGroups)) {\n if (props.br == null) continue;\n const ref = roundedRef(props.br);\n if (ref !== props.br) rounded.push([group, ref]);\n else pushRadius(group, props.br);\n }\n const roundedAll = new Set(rounded.map(([k]) => k));\n\n // ── spacing ────────────────────────────────────────────────────────────────\n // Max rem again: the emitted `--space-*` tokens are fluid clamps.\n const spacing: [string, string][] = [];\n if (ds.spaceScale?.base) spacing.push(['base', ds.spaceScale.base]);\n for (const s of spaceSteps)\n if (!spacing.some(([k]) => k === s.name)) spacing.push([s.name, s.max]);\n\n // ── components ─────────────────────────────────────────────────────────────\n /** Walk a pattern's geometry cascade: overrides → group → defaults. */\n const cascade = (p: PatternItem, prop: string): string | undefined =>\n p.overrides?.[prop] ?? (p.group ? pGroups[p.group]?.[prop] : undefined) ?? pDefaults[prop];\n\n /** A colour-ish CSS value → a `{colors.x}` ref, a literal, or nothing. */\n const colorValue = (value: string | undefined): string | undefined => {\n if (value == null) return undefined;\n const v = varName(value);\n if (v != null) {\n if (colorNames.has(v)) return `{colors.${v}}`;\n const bare = v.startsWith('color-') ? v.slice('color-'.length) : undefined;\n if (bare && colorNames.has(bare)) return `{colors.${bare}}`;\n return undefined;\n }\n return isColorLiteral(value) ? value.trim() : undefined;\n };\n\n /**\n * Resolve a `base` declaration that goes through the group alias layer\n * (`var(--br-card-group)` → the card's `br` cascade), and turn the result into\n * a `{rounded.*}` ref where one exists.\n */\n const geometry = (\n p: PatternItem,\n pname: string,\n baseProp: string,\n token: string,\n ): string | undefined => {\n const declared = p.base?.[baseProp];\n if (declared == null) return undefined;\n const v = varName(declared);\n if (v !== `${token}-${pname}-group`) return declared;\n const resolved = cascade(p, token);\n if (resolved == null) return undefined;\n if (token !== 'br') return resolved;\n const ref = roundedRef(resolved);\n if (ref !== resolved) return ref;\n // A bare literal here came from the group's own `br` — and the group IS a\n // `rounded` entry — UNLESS the pattern overrode it, in which case the value\n // is this pattern's alone and pointing at the group would be a lie.\n return p.overrides?.br == null && p.group && roundedAll.has(p.group)\n ? `{rounded.${p.group}}`\n : resolved;\n };\n\n const components: [string, [string, string][]][] = [];\n const roleVariants: string[] = [];\n for (const [pname, p] of Object.entries(pItems)) {\n if (!p.base) continue;\n const base = p.base;\n // Mirrors generate.ts's fill inference exactly — a component whose fill is\n // guessed differently here would describe colours the CSS never sets.\n const fills =\n p.fill ??\n (pname === 'button' ||\n pname === 'badge' ||\n base['background-color'] != null ||\n base['background'] != null);\n const props: [string, string][] = [];\n if (fills) {\n const bg =\n colorValue(base['background-color']) ??\n colorValue(base['background']) ??\n (p.default_role ? colorValue(`var(--color-bg-${p.default_role}-solid)`) : undefined);\n if (bg) props.push(['backgroundColor', bg]);\n }\n const fg =\n colorValue(base['color']) ??\n (fills && p.default_role ? colorValue(`var(--color-text-on-${p.default_role})`) : undefined);\n if (fg) props.push(['textColor', fg]);\n // A radius that didn't survive into `rounded` (a `50%` circle) would emit\n // either a broken reference or a non-Dimension literal here, so the property\n // is dropped instead; the Shapes prose names those patterns.\n const br = geometry(p, pname, 'border-radius', 'br');\n const brRef = /^\\{rounded\\.([^}]+)\\}$/.exec(br ?? '');\n if (brRef && roundedAll.has(brRef[1] as string)) props.push(['rounded', br as string]);\n else if (br && asDimension(br)) props.push(['rounded', asDimension(br) as string]);\n else if (br) {\n // The Shapes prose wants the value, not the plumbing: `var(--br-circle,\n // 50%)` is how the cascade spells it, `50%` is what the reader needs.\n const named = varName(br);\n const bare = named?.startsWith('br-') ? named.slice('br-'.length) : undefined;\n unroundable.push([pname, (bare ? pRadii[bare] : undefined) ?? br]);\n }\n const pad = geometry(p, pname, 'padding', 'p');\n if (pad) props.push(['padding', pad]);\n if (props.length) components.push([pname, props]);\n\n // A hover that carries `step` intensifies the pattern's own colour; that is\n // a real variant an agent must reproduce, so it gets its own entry (the\n // spec's `-hover` sibling-key convention).\n const hover = p.states?.hover;\n const dr = p.default_role;\n if (hover && typeof hover.step === 'number' && dr) {\n const strong = hover.step >= 1;\n const hv = fills\n ? colorValue(`var(--color-bg-${dr}-${strong ? 'solid-bold' : 'solid'})`)\n : colorValue(`var(--color-text-${dr}${strong ? '-bold' : ''})`);\n if (hv) components.push([`${pname}-hover`, [[fills ? 'backgroundColor' : 'textColor', hv]]]);\n }\n if (p.roles?.length)\n roleVariants.push(\n `\\`${pname}\\` → ${p.roles.map((r) => `\\`.${p.class ?? pname}-${r}\\``).join(', ')}`,\n );\n }\n\n // ── front matter ───────────────────────────────────────────────────────────\n const fm: string[] = ['---', 'version: alpha', `name: ${q(name)}`];\n if (meta.description) fm.push(`description: ${q(meta.description)}`);\n fm.push('colors:');\n fm.push(' # Raw hue ramps — 11 OKLCH steps each, tinted near-white → tinted near-black.');\n for (const [k, v] of ramps) fm.push(` ${key(k)}: ${scalar(v)}`);\n fm.push(' # Functional role tokens (LIGHT values). These are the public API: use these,');\n fm.push(' # not the raw steps, and dark mode resolves itself. See \"## Colors\" below.');\n for (const [k, v] of roleTokens) fm.push(` ${key(k)}: ${scalar(v)}`);\n if (interop.length) {\n fm.push(\" # Aliases for the spec's recommended names — references, not new values.\");\n for (const [k, v] of interop) fm.push(` ${key(k)}: ${scalar(v)}`);\n }\n if (typography.length) {\n fm.push('typography:');\n for (const [role, props] of typography) {\n fm.push(` ${key(role)}:`);\n for (const [k, v] of props) fm.push(` ${k}: ${scalar(v)}`);\n }\n }\n fm.push(yamlMap('rounded', rounded).trimEnd());\n fm.push(yamlMap('spacing', spacing).trimEnd());\n if (components.length) {\n fm.push('components:');\n for (const [cname, props] of components) {\n fm.push(` ${key(cname)}:`);\n for (const [k, v] of props) fm.push(` ${k}: ${scalar(v)}`);\n }\n }\n fm.push('---');\n\n return `${fm.filter(Boolean).join('\\n')}\\n\\n# ${name}\\n\\n${prose({\n ctx,\n name,\n meta,\n roleMap,\n ramps,\n rounded,\n unroundable,\n roleVariants,\n typography: typography.map(([r]) => r),\n })}`;\n}\n\n// ── prose body ────────────────────────────────────────────────────────────────\n/**\n * Section order is normative (Overview → Colors → Typography → Layout →\n * Elevation → Shapes → Components → Do's and Don'ts); a consumer that parses\n * sections positionally breaks if they are reordered.\n *\n * Every section interpolates live config, so this cannot drift into describing a\n * system the generator no longer emits — the same discipline `docs.ts` follows.\n */\nfunction prose(a: {\n ctx: DesignMdCtx;\n name: string;\n meta: { name?: string | undefined; description?: string | undefined };\n roleMap: Record<string, RoleSpec>;\n ramps: [string, string][];\n rounded: [string, string][];\n unroundable: [string, string][];\n roleVariants: string[];\n typography: string[];\n}): string {\n const { ctx, name, meta, roleMap, rounded, unroundable, roleVariants } = a;\n const { ds, expandedPalette, scaleRoles, typeSteps, spaceSteps, shadows } = ctx;\n const hues = Object.keys(expandedPalette);\n const roles = Object.keys(roleMap);\n const shadowNames = Object.keys(shadows ?? {});\n const typeNames = typeSteps.map((s) => s.name);\n const spaceNames = spaceSteps.map((s) => s.name);\n const bodyRole = ds.typography?.headings?.body ?? 'body';\n const s = (list: string[]) => list.map((x) => `\\`${x}\\``).join(', ');\n\n const overview =\n meta.description ??\n `${name} is a variable-driven design system: an OKLCH colour engine, fluid ` +\n `modular type and space scales, and a small set of component patterns, all ` +\n `expressed as CSS custom properties with utility classes over them.`;\n\n return `## Overview\n\n${overview}\n\nEvery value in this document is generated from a single \\`design-system.json\\` and\nemitted as CSS custom properties plus utility classes. **Prefer the class vocabulary\nover hand-written CSS** — \\`vitops docs classes\\` prints the full list, and \\`vitops lint\\`\nreports classes that resolve to nothing.\n\nThe token names below are the contract. Reach for a raw ramp step only when no\nfunctional role expresses what you mean.\n\n> Most tokens here are consumed by **utility classes**, not by the \\`components\\` block —\n> \\`bg-<role>\\`, \\`text-<role>-muted\\` and friends are the API. \\`design.md lint\\` reports\n> those as \\`orphaned-tokens\\`; that rule assumes a component-only system and does not\n> apply. Everything else it reports is worth reading.\n\n## Colors\n\n${hues.length} hue${hues.length === 1 ? '' : 's'} (${s(hues)}), each generated as an 11-step\nOKLCH scale from a seed — step \\`50\\` is a tinted near-white, \\`950\\` a tinted near-black,\nwith chroma damped toward both ends so the extremes read as neutral rather than washed.\n\n${roles.length} semantic **roles** map onto those hues:\n\n${roles.map((r) => `- \\`${r}\\` → \\`${roleHue(roleMap[r] as RoleSpec)}\\``).join('\\n')}\n\nA role is **not** an alias for a ramp. It resolves to tokens named\n\\`<target>-<role>[-<variant>]\\`, where target is one of \\`bg\\` \\`text\\` \\`icon\\` \\`border\\`. The\ntarget is part of the name on purpose: \\`bg-danger-muted\\` and \\`text-danger-muted\\` are\ndifferent tokens, so there is no ambiguity about which one a name refers to. **The token\nname is also the utility class name** — write \\`class=\"bg-danger-muted\"\\` and you are using\n\\`--color-bg-danger-muted\\`.\n\nVariants are ordinal: \\`xx-muted\\` < \\`x-muted\\` < \\`muted\\` < (bare) < \\`bold\\` < \\`x-bold\\`.\n\\`bold\\` means *more emphatic in the current appearance*, not darker.\n\nRoles come in two kinds, and the kind decides which tokens exist:\n\n- **surface** (page and panel colours) — \\`bg-<role>\\` is the card/panel, \\`bg-<role>-muted\\`\n the page behind it, \\`bg-<role>-x-muted\\` a well. Full text scale, \\`border-<role>-bold\\`\n as the contrast-guaranteed boundary.\n- **chromatic** (signal colours) — backgrounds are either *tints*\n (\\`bg-<role>-x-muted\\` / \\`-muted\\`) or *solids*\n (\\`bg-<role>-solid\\` / \\`-solid-bold\\` / \\`-solid-x-bold\\`). **There is no bare \\`bg-<role>\\`**:\n say how loud you mean. \\`text-on-<role>\\` is the guaranteed-contrast foreground for the\n solid family.\n\n**Dark mode is automatic, and this file only lists the light values.** The spec has no\nway to express a second appearance, so do not try to reconstruct one: the framework\nre-points each token at a different ramp step under \\`${DARK_SEL}\\`, so \\`bg-<role>\\`\nbecomes dark and \\`text-<role>\\` becomes light on their own. The solid family and\n\\`text-on-<role>\\` stay mode-stable by design, so a filled button keeps its identity.\n**An agent that styles with the role tokens gets dark mode for free; one that flattens\nthem to hexes breaks it.**\n\nContrast is enforced at build time, not by convention — a violation fails the build.\nText is held to APCA Lc 75 on a role's primary background and Lc 60 on its secondary\nplanes; icons and the surface boundary to Lc 45; and chromatic text is checked against\nthe *surface* planes it actually sits on, not just its own tints. Pairing\n\\`text-<role>\\` with \\`bg-<role>\\`, or \\`text-on-<role>\\` with \\`bg-<role>-solid\\`, is always\nsafe. Pairing a raw ramp step with another raw ramp step is not.\n\n## Typography\n\nFont stacks are named, and roles consume the name rather than the stack — so swapping a\ntypeface is one edit:\n\n${Object.entries((ds.fonts ?? {}) as Record<string, string>)\n .map(([n, stack]) => `- **${n}** — \\`${stack}\\``)\n .join('\\n')}\n\nType is a fluid modular scale: ${typeNames.length} steps (${s(typeNames)}) built from a\n${ds.typeScale?.base ?? '1rem'} base at a ${ds.typeScale?.ratio ?? 1.2} ratio${\n ds.typeScale?.fluid\n ? `, interpolating between a ${ds.typeScale.fluid.minRatio} ratio at ${ds.typeScale.fluid.minVw} viewport width and the full ratio at ${ds.typeScale.fluid.maxVw}`\n : ''\n }. **The \\`fontSize\\` values in the front matter are the maximum (desktop) sizes** — the\nreal tokens are \\`clamp()\\` expressions, which the spec's \\`Dimension\\` type cannot hold.\nNever hard-code the emitted number; use the scale (\\`--text-<step>\\`) or the role class.\n\nEach typography role is a class (\\`.font-<role>\\`): ${s(a.typography.map((t) => `font-${t}`))}.\nRoles also carry properties this format has no slot for — \\`text-transform\\`,\n\\`text-wrap\\`, and a \\`color\\` — so **apply the role class rather than copying its\nfront-matter properties**, or uppercase eyebrows and balanced headings silently\ndisappear. Base page text is bound to the \\`${bodyRole}\\` role, so prose inherits it.\n\n## Layout & Spacing\n\nSpacing is its own fluid modular scale: ${spaceNames.length} steps (${s(spaceNames)}) from a\n${ds.spaceScale?.base ?? '1rem'} base at a ${ds.spaceScale?.ratio ?? 1.25} ratio. As with type,\nthe front-matter values are the maxima and the live tokens are fluid.\n\nLayout is composed from utilities rather than bespoke CSS:\n\n- \\`.centered\\` — track-based centering: content sits in a centred measure while\n full-bleed children can still break out. Use it instead of \\`margin-inline: auto\\`.\n- \\`.rhythm\\` — vertical rhythm between flow children, so sibling spacing is one\n decision rather than per-element margins.\n- \\`.flex\\` / \\`.split-<a>-<b>\\` / \\`.grid\\` — the structural families, with container-query\n variants prefixed \\`sm-\\` / \\`md-\\` / \\`lg-\\` / \\`xl-\\` (30 / 48 / 64 / 80rem).\n \\`.split\\` is a two-column pair. Stack it with \\`.flex-col\\` and let a\n breakpoint-prefixed ratio un-stack it (\\`split flex-col md-split-1-2\\`);\n \\`.split-reverse\\` swaps the two panels. Reversing puts visual order out of step\n with DOM order, so keep focusable content in only one panel.\n\nBreakpoints are **container** queries, not viewport media queries: a component\nresponds to the space it is given, so the same markup works in a sidebar and a full-width\nsection.\n\n## Elevation & Depth\n\n${\n shadowNames.length\n ? `Depth comes from ${shadowNames.length} named shadow${shadowNames.length === 1 ? '' : 's'} (${s(shadowNames)}), applied as \\`--shadow-<name>\\` tokens or \\`.drop-shadow-<name>\\` utilities:\n\n${shadowNames.map((n) => `- \\`${n}\\` — \\`${(shadows ?? {})[n]}\\``).join('\\n')}\n\nEach value is deliberately a **single layer with no spread and no \\`inset\\`**: the same\ntoken feeds both \\`box-shadow\\` (pattern geometry) and \\`filter: drop-shadow()\\` (the\nutilities), and \\`drop-shadow()\\` rejects all three, which would drop the whole filter.`\n : `This system is flat: no shadow tokens are defined. Convey hierarchy with the\nsurface planes (\\`surface-bg\\` / \\`surface-bg-muted\\` / \\`surface-bg-bold\\`) and borders.`\n}\n\nSurfaces stack tonally as well: \\`surface-bg-bold\\` is the *raised* plane in both\nappearances, so a card on a page reads as lifted without any shadow at all.\n\n## Shapes\n\nCorner radii resolve through a cascade rather than being set per component:\n\\`--br-<pattern>\\` (your override hook) → \\`--br-<pattern>-group\\` → the group's radius →\n\\`--br-default\\`. Overriding one variable restyles every pattern in that tier.\n\n${rounded.map(([k, v]) => `- \\`${k}\\` — \\`${v}\\``).join('\\n')}\n\nChange a group's radius to restyle a whole tier; change \\`DEFAULT\\` to restyle everything\nthat has not opted out.\n${\n unroundable.length\n ? `\n**Not in the front matter above**, because the spec's \\`Dimension\\` type only holds\npx / em / rem — these are real radii in the system and have to be applied as CSS:\n\n${unroundable.map(([k, v]) => `- \\`${k}\\` — \\`${v}\\``).join('\\n')}`\n : ''\n}\n\n## Components\n\nPatterns are classes, not components — apply them to whatever element is semantically\ncorrect. Two tiers of button exist and the distinction is intent, not looks:\n\n- **\\`.cta\\`** is *persuasion* — filled, bolder, more padding, lifts on hover. Usually on an\n \\`<a>\\`, because a call to action usually navigates.\n- **\\`.btn\\`** is *affordance* — it only says \"this is interactive\". It is emitted at zero\n specificity for both \\`<button>\\` and \\`.btn\\`, so a bare \\`<button>\\` gets it with no class\n and **any** explicit class overrides it.\n\n${\n roleVariants.length\n ? `Role variants are systematic rather than enumerated above. A filled pattern's variant sets\n\\`background-color: var(--<role>-solid)\\` with \\`color: var(--<role>-on-solid)\\`; a text\npattern's sets \\`color: var(--color-<role>-bold)\\`:\n\n${roleVariants.map((r) => `- ${r}`).join('\\n')}`\n : ''\n}\n\nInteraction states are generated from a small grammar — \\`step\\` (intensify the colour),\n\\`scale\\`, \\`lift\\`, \\`shadow\\`, \\`ring\\` — so hover, active and focus-visible stay consistent\nacross every pattern. Focus rings are never removed, only restyled.\n\n## Do's and Don'ts\n\n- **Do** use functional role tokens (\\`ui-primary-solid\\`, \\`surface-bg\\`) over raw ramp steps.\n- **Do** pair \\`<role>-text\\` with \\`<role>-bg\\`, and \\`<role>-on-solid\\` with \\`<role>-solid\\` —\n those pairings are contrast-tested; arbitrary ones are not.\n- **Do** apply the \\`.font-<role>\\` classes rather than copying their font properties.\n- **Do** reach for a utility class before writing CSS; run \\`vitops lint\\` to catch classes\n that resolve to nothing.\n- **Don't** hard-code the \\`fontSize\\` / \\`spacing\\` numbers from the front matter — they are\n the maxima of fluid \\`clamp()\\` scales.\n- **Don't** flatten role tokens to hex values: that is exactly what breaks dark mode.\n- **Don't** invent a colour outside the ${hues.length} ramps${\n scaleRoles.length ? ` or the ${scaleRoles.length} roles` : ''\n }; add a hue to the config instead.\n- **Don't** edit this file by hand — it is generated from \\`design-system.json\\`. Change the\n config and re-run \\`vitops generate --format design\\`.\n`;\n}\n","/**\n * Company / site-level configuration schema — the umbrella around a\n * `design-system.json`-compliant `designSystem`.\n *\n * Authored with `zod/mini` (same instance the design-system schema uses), so the\n * two compose: `DesignSystemSchema` is embedded as `designSystem.themes.<theme>` and the\n * whole thing serialises to one JSON Schema via `z.toJSONSchema`. Everything a\n * generator needs derives from here: the `SiteConfig` type (`z.infer`), the\n * published JSON Schema (`siteJsonSchema`), and runtime validation (`validateSite`).\n *\n * Pure: no YAML/env/fs. `resolveSiteConfig` takes an already-parsed object; a\n * thin loader (reading YAML, injecting `SITE_ENV`) lives outside this module.\n */\nimport * as z from 'zod/mini';\nimport { desc, DesignSystemPatchSchema, type DesignSystem } from './schema.ts';\n\n// ── Primitives ────────────────────────────────────────────────────────────────\n\nconst LocalizableSchema = desc(\n z.union([z.string(), z.record(z.string(), z.string())]),\n 'A string, or a per-locale map of strings (`{ en: \"…\", fr: \"…\" }`).',\n);\n\nconst ImageRefSchema = z.union([\n z.string(),\n z.object({\n src: z.string(),\n alt: z.string(),\n width: z.optional(z.number()),\n height: z.optional(z.number()),\n }),\n]);\n\n// Attribute bags on generated HTML — constrained to serialisable scalars so the\n// exported JSON Schema still offers validation (vs. an opaque `unknown`).\nconst AttrValue = z.union([z.string(), z.number(), z.boolean()]);\nconst AttrsSchema = z.optional(z.record(z.string(), AttrValue));\n\nconst IsoDate = z.string().check(z.regex(/^\\d{4}-\\d{2}-\\d{2}$/)); // YYYY-MM-DD\nconst Iso4217 = z.string().check(z.regex(/^[A-Z]{3}$/)); // currency code\nconst DayOfWeek = z.enum([\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday',\n 'Sunday',\n]);\n\n// ── Design system ───────────────────────────────────────────────────────────────\n// Each `themes` entry is a full `DesignSystem` plus a localised `displayName` and\n// an optional `extends` (another entry's key). Entries are lenient (all top-level\n// fields optional) so an extending entry can be a partial patch; the resolved\n// theme is validated against the full `DesignSystemSchema` by `resolveTheme`.\n\nconst DesignSystemEntry = z.extend(DesignSystemPatchSchema, {\n displayName: desc(\n z.optional(LocalizableSchema),\n 'Human-readable theme name (localisable). The label a theme picker would show — nothing reads it yet, because nothing builds more than one theme (see `themes`).',\n ),\n extends: desc(\n z.optional(z.string()),\n 'Another `themes` key to inherit from; this entry then only supplies what it overrides.',\n ),\n});\n\n/**\n * The design system as a whole: the named themes plus the facts that describe the\n * system rather than any one theme.\n *\n * `themes` is nested rather than being the block itself because the block used to\n * BE the map — every key was a theme name, so there was nowhere to put\n * system-wide metadata without it colliding with a theme of that name.\n *\n * Note the two axes here are independent, and deliberately so. `defaultTheme`\n * picks a *theme* (an authored design system); `defaultColorScheme` picks an\n * *appearance* (light/dark), which every theme already has because the flip is\n * derived from one ramp rather than authored. \"Theme `elegant`, appearance\n * follows the OS\" has to be sayable, and a single union could not express it.\n */\nconst DesignSystemBlock = desc(\n z.strictObject({\n themes: desc(\n z.record(z.string(), DesignSystemEntry),\n 'Named themes. `default` is the base; others may `extends` another and supply a partial patch. Light/dark is NOT a theme — the functional tokens flip per appearance within each one, so `default` already has both. Only the default theme is built today; multi-theme output and a picker are not wired yet.',\n ),\n defaultTheme: desc(\n z.optional(z.string()),\n 'Which `themes` entry to use (convention: \"default\"). Validated against the map; selecting a non-default theme is not wired yet.',\n ),\n defaultColorScheme: desc(\n z.optional(z.enum(['light', 'dark', 'system'])),\n 'Initial appearance. `\"system\"` follows the OS via `prefers-color-scheme` and is what makes `<color-scheme-toggle>`\\'s \"System\" position resolve to anything — it removes the theme attribute, so without this the page falls through to light. It also gives a no-JS page the OS appearance. Defaults to `\"light\"`, because switching an existing site to `\"system\"` visibly flips it dark for dark-OS visitors.',\n ),\n }),\n 'The design system: named themes plus the system-wide facts (which theme, which appearance). A bare design system, or a bare theme map, is accepted as shorthand for `{ themes: … }`.',\n);\n\n// ── Locales ─────────────────────────────────────────────────────────────────────\n\nconst LocaleSchema = z.object({\n name: desc(z.string(), 'Display name of the locale (e.g. \"English\").'),\n tagline: desc(z.optional(z.string()), 'Site tagline in this locale.'),\n basePath: desc(z.optional(z.string()), 'URL prefix for this locale (e.g. \"/fr\").'),\n});\n\n// ── Domains ─────────────────────────────────────────────────────────────────────\n\nconst HttpRedirect = z.union([z.literal(301), z.literal(302), z.literal(307), z.literal(308)]);\n\nconst DomainAliasSchema = z.object({\n domain: z.string(),\n redirectType: HttpRedirect,\n redirectTo: z.string(),\n environment: z.optional(z.string()),\n});\n\n// ── Contact / address (schema.org-aligned) ──────────────────────────────────────\n\nconst PostalAddressSchema = desc(\n z.object({\n streetAddress: z.string(),\n addressLocality: desc(z.string(), 'City.'),\n addressRegion: desc(z.optional(z.string()), 'State / province.'),\n postalCode: z.optional(z.string()),\n addressCountry: desc(z.string(), 'Country (ISO 3166-1 alpha-2 preferred).'),\n }),\n 'schema.org `PostalAddress` field names, so JSON-LD generation is lossless.',\n);\n\nconst ContactObjectSchema = z.object({\n name: z.optional(z.string()),\n email: z.optional(z.email()),\n phone: z.optional(z.string()),\n address: z.optional(PostalAddressSchema),\n});\n\n// contact is either a string (location key reference) or an inline object\nconst ContactConfigSchema = z.union([z.string(), ContactObjectSchema]);\n\nexport type PostalAddress = z.infer<typeof PostalAddressSchema>;\nexport type ContactObject = z.infer<typeof ContactObjectSchema>;\n\n// ── Locations (schema.org LocalBusiness) ────────────────────────────────────────\n\nconst GeoSchema = z.object({\n latitude: z.number().check(z.gte(-90), z.lte(90)),\n longitude: z.number().check(z.gte(-180), z.lte(180)),\n});\n\n/** schema.org `OpeningHoursSpecification` — per-day open/close (24h `HH:MM`). */\nconst OpeningHoursSchema = z.object({\n dayOfWeek: z.array(DayOfWeek),\n opens: z.string().check(z.regex(/^\\d{2}:\\d{2}$/)),\n closes: z.string().check(z.regex(/^\\d{2}:\\d{2}$/)),\n});\n\n// Common schema.org LocalBusiness subtypes (extend as needed).\nconst LocalBusinessType = z.enum([\n 'LocalBusiness',\n 'Store',\n 'Restaurant',\n 'CafeOrCoffeeShop',\n 'ProfessionalService',\n 'MedicalBusiness',\n 'HealthAndBeautyBusiness',\n 'HomeAndConstructionBusiness',\n 'AutomotiveBusiness',\n 'FinancialService',\n 'LegalService',\n 'RealEstateAgent',\n 'Organization',\n]);\n\nconst LocationSchema = z.object({\n slug: z.optional(LocalizableSchema),\n name: LocalizableSchema,\n email: z.optional(z.email()),\n phone: z.optional(z.string()),\n address: z.optional(PostalAddressSchema),\n geo: z.optional(GeoSchema),\n hours: z.optional(z.array(OpeningHoursSchema)),\n type: z.optional(LocalBusinessType),\n description: z.optional(LocalizableSchema),\n areaServed: z.optional(z.array(z.string())),\n priceRange: z.optional(z.string()),\n paymentAccepted: z.optional(z.array(z.string())),\n currenciesAccepted: z.optional(Iso4217),\n knowsLanguage: z.optional(z.array(z.string())),\n});\n\n// ── Organization (schema.org Organization) ──────────────────────────────────────\n\nconst OrganizationSchema = z.object({\n name: z.optional(LocalizableSchema),\n legalName: z.optional(z.string()),\n foundingDate: z.optional(IsoDate),\n logo: z.optional(ImageRefSchema),\n email: z.optional(z.email()),\n phone: z.optional(z.string()),\n address: z.optional(PostalAddressSchema),\n taxID: z.optional(z.string()),\n vatID: z.optional(z.string()),\n sameAs: desc(z.optional(z.array(z.url())), 'Profile URLs → JSON-LD `sameAs` (mirrors `links`).'),\n});\n\n// ── DNS ──────────────────────────────────────────────────────────────────────\n\nconst DnsRecordType = z.enum(['A', 'AAAA', 'CNAME', 'TXT', 'MX', 'NS', 'SRV', 'CAA', 'PTR', 'SOA']);\n\nconst DnsRecordSchema = z.object({\n type: DnsRecordType,\n name: z.optional(z.string()),\n value: z.string(),\n ttl: z.optional(z.number().check(z.int(), z.positive())),\n proxied: z.optional(z.boolean()),\n});\n\nconst DnsDomainSchema = z.object({\n provider: z.optional(z.string()),\n nameservers: z.optional(z.array(z.string())),\n records: z.optional(z.array(DnsRecordSchema)),\n});\n\n// ── Environments ──────────────────────────────────────────────────────────────\n\nconst RobotsSchema = z.string(); // e.g. \"index,follow\" / \"noindex,nofollow\"\n\nconst EnvironmentSchema = z.object({\n url: desc(z.url(), 'Public origin of this environment.'),\n api: desc(z.optional(z.url()), 'API origin, when different from `url`.'),\n analytics: desc(z.optional(z.boolean()), 'Whether analytics fire in this environment.'),\n robots: desc(z.optional(RobotsSchema), 'Robots policy (e.g. \"noindex,nofollow\" for dev).'),\n variant: desc(z.optional(z.string()), 'Active `abTesting.variants` key for this environment.'),\n});\n\n// ── A/B testing ─────────────────────────────────────────────────────────────────\n\nconst AbVariantSchema = z.object({\n environment: z.string(),\n description: z.optional(z.string()),\n // Deliberate escape hatch: overrides are deep-merged into the raw config\n // before validation, so their shape is the config's own.\n overrides: z.optional(z.record(z.string(), z.unknown())),\n});\n\n// ── Fonts (Astro Fonts API projection) ──────────────────────────────────────────\n// Font *loading* — a serialisable projection of Astro's `fonts:[…]` config. A\n// loader maps `provider` (string) → `fontProviders.<name>()`. Distinct from the\n// design-system font *tokens* (`designSystem.themes.<theme>.fonts` / typography.families),\n// which reference the same `cssVariable`.\n\nconst FontProvider = z.enum([\n 'google',\n 'fontsource',\n 'adobe',\n 'bunny',\n 'fontshare',\n 'googleicons',\n 'npm',\n 'local',\n]);\nconst FontStyle = z.enum(['normal', 'italic']);\nconst FontDisplay = z.enum(['auto', 'block', 'swap', 'fallback', 'optional']);\nconst FontWeight = z.union([z.number(), z.string()]); // discrete, or a variable range like \"100 900\"\n\n/** A local-font face (`provider: 'local'`). */\nconst FontVariantSchema = z.object({\n src: z.array(z.string()),\n weight: z.optional(FontWeight),\n style: z.optional(FontStyle),\n unicodeRange: z.optional(z.array(z.string())),\n display: z.optional(FontDisplay),\n});\n\nexport const SiteFontSchema = z.object({\n name: z.string(),\n provider: FontProvider,\n cssVariable: z.string().check(z.regex(/^--/)),\n weights: z.optional(z.array(FontWeight)),\n styles: z.optional(z.array(FontStyle)),\n subsets: z.optional(z.array(z.string())),\n fallbacks: z.optional(z.array(z.string())),\n optimizedFallbacks: z.optional(z.boolean()),\n display: z.optional(FontDisplay),\n formats: z.optional(z.array(z.string())),\n unicodeRange: z.optional(z.array(z.string())),\n variants: z.optional(z.array(FontVariantSchema)), // local provider\n preload: desc(\n z.optional(\n z.union([\n z.boolean(),\n z.array(z.object({ weight: FontWeight, style: z.optional(FontStyle) })),\n ]),\n ),\n 'Emit `<Font preload />` for this family (true, or a list of weight/style faces).',\n ),\n});\n\n// ── Templates (nav / form / nodes) ──────────────────────────────────────────────\n\nconst PresentSchema = z.optional(z.record(z.string(), z.unknown()));\n\nconst NavItemSchema: z.ZodMiniType = z.object({\n label: z.optional(LocalizableSchema),\n image: z.optional(ImageRefSchema),\n href: z.optional(z.string()),\n icon: z.optional(z.string()),\n attrs: AttrsSchema,\n itemAttrs: AttrsSchema,\n submenu: z.optional(\n z.object({\n present: PresentSchema,\n get items() {\n return z.optional(z.array(NavItemSchema));\n },\n }),\n ),\n});\n\nconst FormFieldType = z.enum([\n 'text',\n 'email',\n 'tel',\n 'url',\n 'number',\n 'password',\n 'textarea',\n 'select',\n 'checkbox',\n 'radio',\n 'date',\n 'file',\n 'hidden',\n]);\n\nconst FormFieldSchema = z.object({\n name: z.string(),\n type: FormFieldType,\n label: z.optional(LocalizableSchema),\n required: z.optional(z.boolean()),\n validation: z.optional(z.string()), // regex source or named rule\n options: z.optional(\n z.union([z.string(), z.array(z.object({ label: z.string(), value: z.string() }))]),\n ),\n attrs: AttrsSchema,\n});\n\nconst ContentNodeSchema: z.ZodMiniType = z.object({\n tag: z.string(),\n attrs: AttrsSchema,\n text: z.optional(z.string()),\n get children() {\n return z.optional(z.array(ContentNodeSchema));\n },\n});\n\nconst TemplateSchema = z.union([\n z.object({\n type: z.literal('nav'),\n tags: z.optional(z.array(z.string())),\n present: PresentSchema,\n items: z.optional(z.array(NavItemSchema)),\n }),\n z.object({\n type: z.literal('form'),\n tags: z.optional(z.array(z.string())),\n present: PresentSchema,\n action: z.optional(z.string()),\n method: z.optional(z.enum(['get', 'post'])),\n fields: z.optional(z.array(FormFieldSchema)),\n submit: z.optional(z.record(z.string(), AttrValue)),\n honeypot: z.optional(z.boolean()),\n }),\n z.object({\n type: z.literal('nodes'),\n tags: z.optional(z.array(z.string())),\n nodes: z.optional(z.array(ContentNodeSchema)),\n }),\n]);\n\n// ── Galleries / testimonials ────────────────────────────────────────────────────\n\nconst GalleryImageSchema = z.object({\n src: z.string(),\n alt: LocalizableSchema,\n caption: z.optional(LocalizableSchema),\n});\n\nconst GallerySchema = z.object({\n title: z.optional(LocalizableSchema),\n tags: z.optional(z.array(z.string())),\n images: z.array(GalleryImageSchema),\n});\n\nconst TestimonialItemSchema = z.object({\n quote: LocalizableSchema,\n name: z.string(),\n role: z.optional(z.string()),\n rating: z.optional(z.number().check(z.gte(0), z.lte(5))),\n date: z.optional(IsoDate),\n});\n\nconst TestimonialGroupSchema = z.object({\n title: z.optional(LocalizableSchema),\n items: z.array(TestimonialItemSchema),\n});\n\n// ── Services (schema.org Offer) ─────────────────────────────────────────────────\n\nconst OfferSchema = z.object({\n name: z.optional(LocalizableSchema),\n price: z.optional(z.union([z.string(), z.number()])),\n priceCurrency: z.optional(Iso4217),\n availability: z.optional(z.string()),\n url: z.optional(z.url()),\n validFrom: z.optional(IsoDate),\n priceValidUntil: z.optional(IsoDate),\n});\n\nconst ServiceSchema = z.object({\n name: LocalizableSchema,\n description: z.optional(LocalizableSchema),\n slug: z.optional(LocalizableSchema),\n offers: z.optional(z.array(OfferSchema)),\n});\n\n// ── SEO / social ─────────────────────────────────────────────────────────────\n\nconst OpenGraphSchema = z.object({\n type: z.optional(z.string()),\n siteName: z.optional(z.string()),\n title: z.optional(LocalizableSchema),\n description: z.optional(LocalizableSchema),\n image: z.optional(ImageRefSchema),\n locale: z.optional(z.string()),\n});\n\nconst TwitterSchema = z.object({\n card: z.optional(z.enum(['summary', 'summary_large_image', 'app', 'player'])),\n site: z.optional(z.string()),\n creator: z.optional(z.string()),\n title: z.optional(LocalizableSchema),\n description: z.optional(LocalizableSchema),\n image: z.optional(ImageRefSchema),\n});\n\n// ── Indexing ────────────────────────────────────────────────────────────────────\n\n/**\n * What `vitops notify` needs to tell search engines a deploy happened.\n *\n * Scoped by what search engines actually accept, which is narrower than it looks:\n * Google exposes **no** \"request indexing\" API (the Search Console button is not in\n * its API, and URL Inspection is read-only), and it removed the sitemap ping\n * endpoint in 2023. So the sanctioned set is: an accurate sitemap, a Search Console\n * sitemap resubmit, an IndexNow ping — which Google does *not* honour but Bing,\n * Yandex, Naver, Seznam and Yep do — and a read-only inspection pass to find out\n * what Google actually did.\n *\n * Facts only, the same rule the legal block follows: this records what the site has\n * (a key, a property, which pages matter), never what to say about it.\n */\nconst IndexNowSchema = z.object({\n key: desc(\n z.string().check(z.regex(/^[a-zA-Z0-9-]{8,128}$/)),\n 'IndexNow key (8–128 chars, hex is conventional). NOT a secret — it is served publicly at `keyLocation` so the engine can verify you own the host. Generate one with `vitops notify --new-key`.',\n ),\n keyLocation: desc(\n z.optional(z.url()),\n 'Absolute URL of the key file. Defaults to `<canonical>/<key>.txt`; set it only when the file lives elsewhere.',\n ),\n endpoint: desc(\n z.optional(z.url()),\n 'IndexNow endpoint (default `https://api.indexnow.org/indexnow`). Any participating engine shares submissions with the rest, so one is normally enough.',\n ),\n});\n\nconst SearchConsoleSchema = z.object({\n siteUrl: desc(\n z.string(),\n 'The property exactly as Search Console identifies it — `sc-domain:acme.ca` for a domain property, or the URL-prefix form `https://acme.ca/`. A mismatch here is a 403, not a \"not found\".',\n ),\n resubmitSitemap: desc(\n z.optional(z.boolean()),\n 'Re-submit the sitemap through the Search Console API on each notify (default true when `searchConsole` is set). This is the automated equivalent of the manual resubmit in the UI.',\n ),\n});\n\nconst IndexingSchema = z.object({\n sitemapUrl: desc(\n z.optional(z.url()),\n 'The sitemap to submit and to diff for changed URLs. Defaults to `<canonical>/sitemap-index.xml`.',\n ),\n indexNow: desc(\n z.optional(IndexNowSchema),\n 'IndexNow submission (Bing, Yandex, Naver, Seznam, Yep — not Google). Omit to skip the channel.',\n ),\n searchConsole: desc(\n z.optional(SearchConsoleSchema),\n 'Google Search Console property. Needs a service-account credential in `VITOPS_GSC_SERVICE_ACCOUNT` or `GOOGLE_APPLICATION_CREDENTIALS` at run time — never put the key in this file.',\n ),\n priorityUrls: desc(\n z.optional(z.array(z.url())),\n 'The pages whose indexing actually matters. `vitops notify --check` inspects these and exits non-zero if Google has not indexed one. Kept explicit because URL Inspection is quota-bound (2000/day), so checking every page is neither affordable nor informative.',\n ),\n});\n\n// ── Legal ───────────────────────────────────────────────────────────────────────\n\n/**\n * Which template set the generated legal documents are written against. This is\n * a closed enum rather than a free string because an unrecognised value would\n * otherwise silently fall back to the wrong body of law; `validateSite` rejects\n * anything without a registered template. Add a member here and a matching entry\n * in `legal/templates/index.ts` — the two are checked against each other.\n */\nexport const JURISDICTIONS = ['ca'] as const;\nconst JurisdictionSchema = z.enum(JURISDICTIONS);\nexport type Jurisdiction = (typeof JURISDICTIONS)[number];\n\n/**\n * A third party that receives personal information. The generator derives the\n * ones it can see (analytics IDs, Turnstile, the deploy platform); this is for\n * the rest, which no other part of the config implies.\n *\n * Deliberately facts, not prose: the config records *what is true*, the template\n * owns *how it is said*. That keeps a policy correct when the wording changes.\n */\nconst ProcessorSchema = z.object({\n name: desc(z.string(), 'The provider, as a reader would recognise it (e.g. \"Stripe\").'),\n purpose: desc(\n z.string(),\n 'Why they receive it, as a noun phrase that reads after \"for\" (e.g. \"payment processing\").',\n ),\n country: desc(\n z.optional(z.string()),\n 'Where they process it, as it should read in a sentence (e.g. \"the United States\"). Feeds the cross-border-transfer disclosure.',\n ),\n privacyUrl: z.optional(z.url()),\n});\n\n// ── Top-level schema ────────────────────────────────────────────────────────────\n\nexport const SiteConfigSchema = z.object({\n defaultLocale: desc(\n z.string(),\n 'The locale used when none is specified; must be a `locales` key.',\n ),\n locales: desc(\n z.record(z.string(), LocaleSchema),\n 'Locales the site is published in, keyed by BCP 47 tag (e.g. \"en\", \"fr\").',\n ),\n organization: desc(\n z.optional(OrganizationSchema),\n 'schema.org Organization details for JSON-LD (name, legalName, logo, tax IDs, sameAs profiles).',\n ),\n contact: desc(\n z.optional(ContactConfigSchema),\n 'Primary contact: either a `locations` key (string reference) or an inline name/email/phone/address object.',\n ),\n domains: desc(\n z.optional(\n z.object({\n canonical: desc(z.url(), 'The canonical origin used for absolute URLs and SEO.'),\n aliases: desc(\n z.optional(z.array(DomainAliasSchema)),\n 'Alias domains and how they redirect to the canonical one.',\n ),\n }),\n ),\n 'Canonical domain + redirecting aliases.',\n ),\n primaryLocation: desc(\n z.optional(z.string()),\n 'The main `locations` key (for JSON-LD and defaults).',\n ),\n locations: desc(\n z.optional(z.record(z.string(), LocationSchema)),\n 'Physical locations (schema.org LocalBusiness): address, geo, opening hours, service area.',\n ),\n services: desc(\n z.optional(z.record(z.string(), ServiceSchema)),\n 'Services offered (schema.org Service/Offer): name, description, slug, price offers.',\n ),\n links: desc(\n z.optional(\n z.object({\n googleMaps: z.optional(z.url()),\n instagram: z.optional(z.url()),\n facebook: z.optional(z.url()),\n x: z.optional(z.url()),\n linkedin: z.optional(z.url()),\n youtube: z.optional(z.url()),\n github: z.optional(z.url()),\n }),\n ),\n 'Public profile URLs (also feed JSON-LD `sameAs` via `organization.sameAs`).',\n ),\n dns: desc(\n z.optional(z.record(z.string(), DnsDomainSchema)),\n 'Desired DNS state per domain (provider, nameservers, records) — declarative reference, not applied automatically.',\n ),\n cloudflare: desc(\n z.optional(z.record(z.string(), z.unknown())),\n 'Deliberate escape hatch for provider-specific Cloudflare settings — out of scope to model here.',\n ),\n environments: desc(\n z.record(z.string(), EnvironmentSchema),\n 'Deploy environments (production, dev, …): URL, API origin, analytics toggle, robots policy, active A/B variant.',\n ),\n abTesting: desc(\n z.optional(\n z.object({\n enabled: z.boolean(),\n cookieName: z.optional(z.string()),\n cookieMaxAge: desc(z.optional(z.number().check(z.int(), z.positive())), 'Seconds.'),\n splitRatio: desc(\n z.optional(z.number().check(z.gte(0), z.lte(1))),\n 'Fraction of traffic sent to the variant (0–1).',\n ),\n variants: desc(\n z.optional(z.record(z.string(), AbVariantSchema)),\n 'Named variants; each targets an environment and may deep-merge config `overrides`.',\n ),\n }),\n ),\n 'A/B testing: cookie-based split plus named variants whose `overrides` patch the config per environment.',\n ),\n\n designSystem: DesignSystemBlock,\n\n fonts: desc(\n z.optional(z.array(SiteFontSchema)),\n 'Font LOADING (a serialisable projection of the Astro Fonts API: provider, weights, subsets, preload). Font TOKENS live in `designSystem.themes.<theme>.fonts` and reference the same `cssVariable`.',\n ),\n\n tags: desc(\n z.optional(z.record(z.string(), z.unknown())),\n 'Free-form content-tag taxonomy (site-specific; not interpreted by the generator).',\n ),\n postTypes: desc(\n z.optional(z.record(z.string(), z.unknown())),\n 'Free-form content-type definitions (site-specific; not interpreted by the generator).',\n ),\n galleries: desc(\n z.optional(z.record(z.string(), GallerySchema)),\n 'Named image galleries (title, tags, images with localisable alt/caption).',\n ),\n testimonials: desc(\n z.optional(z.record(z.string(), TestimonialGroupSchema)),\n 'Named testimonial groups (quote, name, role, rating, date).',\n ),\n templates: desc(\n z.optional(z.record(z.string(), TemplateSchema)),\n 'Named content templates rendered at SSR time: `nav` (menu trees), `form` (field lists + submit), or `nodes` (raw element trees).',\n ),\n navigation: desc(\n z.optional(\n z.object({\n activeTemplate: desc(\n z.optional(\n z.object({\n default: desc(z.optional(z.string()), 'A `templates` key.'),\n breakpoints: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Breakpoint name → `templates` key overrides.',\n ),\n }),\n ),\n 'Which nav template is active, optionally per breakpoint.',\n ),\n }),\n ),\n 'Site navigation settings (which nav template renders where).',\n ),\n seo: desc(\n z.optional(\n z.object({\n titleTemplate: desc(z.optional(z.string()), 'Page-title pattern (e.g. \"%s · Acme\").'),\n descriptionTemplate: z.optional(z.string()),\n robots: desc(z.optional(RobotsSchema), 'e.g. \"index,follow\" / \"noindex,nofollow\".'),\n googleSiteVerification: z.optional(z.string()),\n bingSiteVerification: z.optional(z.string()),\n openGraph: z.optional(OpenGraphSchema),\n twitter: z.optional(TwitterSchema),\n indexing: desc(\n z.optional(IndexingSchema),\n 'How `vitops notify` tells search engines about a deploy: which sitemap, IndexNow key, Search Console property, and which pages to verify afterwards.',\n ),\n }),\n ),\n 'SEO defaults: title/description templates, robots policy, verification tokens, Open Graph + Twitter cards, and post-deploy indexing notification.',\n ),\n analytics: desc(\n z.optional(\n z.object({\n googleAnalyticsId: z.optional(z.string()),\n plausibleDomain: z.optional(z.string()),\n googleTagManagerId: z.optional(z.string()),\n clarityId: desc(z.optional(z.string()), 'Microsoft Clarity project ID.'),\n matomo: desc(\n z.optional(\n z.object({\n url: desc(z.string(), 'Instance base URL (self-hosted, or `*.matomo.cloud`).'),\n siteId: desc(z.string(), 'Site ID within that instance.'),\n cookies: desc(\n z.optional(z.boolean()),\n 'Default false — Matomo runs cookieless (`disableCookies`), which is what lets the cookie notice state positively that it sets none.',\n ),\n }),\n ),\n 'Matomo instance.',\n ),\n }),\n ),\n 'Analytics provider IDs (gated per environment via `environments.<env>.analytics`). Which provider is set is also what the generated privacy policy and cookie notice disclose — see `legal`.',\n ),\n notifications: desc(\n z.optional(z.object({ email: z.optional(z.email()) })),\n 'Where site notifications (e.g. form submissions) are sent.',\n ),\n tracking: desc(\n z.optional(\n z.object({\n enabled: z.optional(z.boolean()),\n platforms: z.optional(z.array(z.string())),\n }),\n ),\n 'Marketing/conversion tracking toggles per platform.',\n ),\n security: desc(\n z.optional(\n z.object({\n turnstile: z.optional(\n z.object({\n siteKey: desc(z.optional(z.string()), 'Cloudflare Turnstile site key (public).'),\n }),\n ),\n }),\n ),\n 'Security integrations (bot protection).',\n ),\n legal: desc(\n z.optional(\n z.object({\n jurisdiction: desc(\n z.optional(JurisdictionSchema),\n 'Which legal template set the generated documents use. Default `ca`.',\n ),\n privacyPolicy: z.optional(\n z.object({\n enabled: z.boolean(),\n url: z.optional(z.url()),\n lastUpdated: z.optional(IsoDate),\n privacyOfficer: desc(\n z.optional(ContactConfigSchema),\n 'Who privacy requests go to. Falls back to `contact`, then `primaryLocation`.',\n ),\n retention: desc(\n z.optional(z.string()),\n 'How long personal information is kept, in prose (e.g. \"24 months after last contact\").',\n ),\n processors: desc(\n z.optional(z.array(ProcessorSchema)),\n 'Third parties that receive personal information and cannot be inferred from the rest of the config (payment processors, CRMs, mail senders). Known providers implied by `analytics`, `security` and `deployment` are added automatically — list only the rest.',\n ),\n }),\n ),\n termsOfService: z.optional(\n z.object({\n enabled: z.boolean(),\n url: z.optional(z.url()),\n lastUpdated: z.optional(z.nullable(IsoDate)),\n governingLaw: desc(\n z.optional(z.string()),\n 'Governing-law clause, in prose (e.g. \"the Province of Ontario\"). Defaults from the contact address.',\n ),\n }),\n ),\n cookieConsent: z.optional(\n z.object({\n enabled: z.boolean(),\n type: desc(z.optional(z.enum(['opt-in', 'opt-out'])), 'Consent model.'),\n position: z.optional(z.enum(['top', 'bottom', 'center'])),\n categories: z.optional(z.array(z.string())),\n }),\n ),\n }),\n ),\n 'Legal pages: which documents exist, where they live, and the facts the generated prose asserts.',\n ),\n icons: desc(\n z.optional(\n // LOOSE on purpose. The per-set keys below are the sets `iconMap` knows\n // semantically, but the value shape is \"any iconify collection name → a\n // list of icons\", which is open-ended by definition. A closed object\n // silently DROPPED unlisted collections (`icons: { ph: [...] }` vanished\n // in validateSite with no error) while `generateIconInclude`'s parameter\n // type advertised `[prefix: string]` — so the config validated, the icons\n // never bundled, and the failure only showed as missing glyphs in prod.\n z.looseObject({\n ui: desc(z.optional(z.string()), 'Icon set used for UI chrome (e.g. \"lucide\", \"ph\").'),\n brand: desc(z.optional(z.string()), 'Icon set used for brand marks.'),\n weight: desc(\n z.optional(z.string()),\n 'Weight for suffix-weighted sets like Phosphor (\"regular\" | \"bold\" | \"duotone\" | \"fill\" | \"light\" | \"thin\"). Ignored by sets that split weights across collections, e.g. Font Awesome.',\n ),\n sprite: desc(\n z.optional(z.boolean()),\n 'Emit an SVG sprite (icons.svg) alongside the stylesheet, for consumers that cannot run an icon integration (Bricks/WordPress, EmDash renderers).',\n ),\n semantic: desc(z.optional(z.array(z.string())), 'Named semantic icons to include.'),\n 'fa7-solid': z.optional(z.array(z.string())),\n 'fa7-regular': z.optional(z.array(z.string())),\n 'fa7-light': z.optional(z.array(z.string())),\n 'fa7-thin': z.optional(z.array(z.string())),\n 'fa7-brands': z.optional(z.array(z.string())),\n 'simple-icons': z.optional(z.array(z.string())),\n 'material-symbols': z.optional(z.array(z.string())),\n lucide: z.optional(z.array(z.string())),\n ph: z.optional(z.array(z.string())),\n }),\n ),\n 'Icon sets and the specific icons to bundle from each (keys are iconify collection names).',\n ),\n favicon: desc(\n z.optional(\n z.object({\n source: desc(z.string(), 'Source image (SVG/PNG) the favicon set is generated from.'),\n lowResSource: desc(\n z.optional(z.string()),\n 'Alternate source for small raster sizes (16/32px) when the main source scales down poorly.',\n ),\n name: desc(z.optional(z.string()), 'App name for the generated web manifest / PWA.'),\n themeColor: desc(\n z.optional(z.string()),\n 'PWA theme color (also `<meta name=\"theme-color\">`).',\n ),\n backgroundColor: desc(z.optional(z.string()), 'PWA background color.'),\n }),\n ),\n 'Favicon/PWA asset generation (consumed by `@getvitops/utils` favicon tooling).',\n ),\n deployment: desc(\n z.optional(\n z.object({\n platform: z.optional(z.string()),\n buildCommand: z.optional(z.string()),\n deployCommand: z.optional(z.string()),\n outputDirectory: z.optional(z.string()),\n type: z.optional(z.string()),\n }),\n ),\n 'How the site is built and deployed (platform, commands, output directory) — informational for tooling.',\n ),\n});\n\nexport type SiteConfig = z.infer<typeof SiteConfigSchema>;\n/** One `fonts[]` entry — a serialisable projection of an Astro Fonts API family. */\nexport type SiteFont = z.infer<typeof SiteFontSchema>;\n/** The `seo.indexing` block — what `vitops notify` reads. */\nexport type SiteIndexing = z.infer<typeof IndexingSchema>;\n/** IndexNow submission settings. The `key` is public by design. */\nexport type SiteIndexNow = z.infer<typeof IndexNowSchema>;\n/** Google Search Console property settings. The credential is never in the config. */\nexport type SiteSearchConsole = z.infer<typeof SearchConsoleSchema>;\n\n// ── JSON Schema + validation ────────────────────────────────────────────────────\n\nexport const SITE_SCHEMA_URL = 'https://unpkg.com/@getvitops/generator/site.schema.json';\n\n/** The published JSON Schema (draft-2020-12), derived from the zod schema. */\nexport const siteJsonSchema = {\n $id: SITE_SCHEMA_URL,\n ...z.toJSONSchema(SiteConfigSchema, { target: 'draft-2020-12' }),\n};\n\nexport type SiteValidationResult =\n | { ok: true; data: SiteConfig; errors: [] }\n | { ok: false; data: undefined; errors: z.core.$ZodIssue[] };\n\ntype Issue = z.core.$ZodIssue;\nconst issue = (path: (string | number)[], message: string): Issue =>\n ({ code: 'custom', path, message }) as Issue;\n\n/**\n * Validate a raw (already parsed) config: shape via zod, then the cross-field\n * integrity that JSON Schema can't express (referential keys, extends acyclicity).\n * These live only here — the published JSON Schema enforces shape, not integrity.\n */\nexport function validateSite(input: unknown): SiteValidationResult {\n const parsed = z.safeParse(SiteConfigSchema, input);\n if (!parsed.success) return { ok: false, data: undefined, errors: parsed.error.issues };\n const cfg = parsed.data;\n const errors: Issue[] = [];\n const has = (m: Record<string, unknown> | undefined, k: string) => !!m && k in m;\n\n if (!has(cfg.locales, cfg.defaultLocale))\n errors.push(issue(['defaultLocale'], `defaultLocale \"${cfg.defaultLocale}\" is not in locales`));\n\n const themes = cfg.designSystem?.themes ?? {};\n const defaultTheme = cfg.designSystem?.defaultTheme;\n\n if (!has(themes, 'default') && defaultTheme == null)\n errors.push(issue(['designSystem', 'themes'], 'themes must include a \"default\" entry'));\n\n if (defaultTheme != null && !has(themes, defaultTheme))\n errors.push(\n issue(\n ['designSystem', 'defaultTheme'],\n `defaultTheme \"${defaultTheme}\" is not in designSystem.themes`,\n ),\n );\n\n for (const [key, entry] of Object.entries(themes)) {\n if (entry.extends != null && !has(themes, entry.extends))\n errors.push(\n issue(\n ['designSystem', 'themes', key, 'extends'],\n `extends \"${entry.extends}\" is not a themes key`,\n ),\n );\n }\n // extends acyclicity + each resolved theme is a complete DesignSystem\n for (const key of Object.keys(themes)) {\n try {\n resolveTheme(themes as Record<string, DesignSystemEntryT>, key);\n } catch (e) {\n errors.push(issue(['designSystem', 'themes', key], (e as Error).message));\n }\n }\n\n if (cfg.primaryLocation != null && !has(cfg.locations, cfg.primaryLocation))\n errors.push(\n issue(['primaryLocation'], `primaryLocation \"${cfg.primaryLocation}\" is not in locations`),\n );\n if (typeof cfg.contact === 'string' && !has(cfg.locations, cfg.contact))\n errors.push(issue(['contact'], `contact \"${cfg.contact}\" is not a locations key`));\n\n for (const [name, v] of Object.entries(cfg.abTesting?.variants ?? {}))\n if (!has(cfg.environments, v.environment))\n errors.push(\n issue(\n ['abTesting', 'variants', name, 'environment'],\n `environment \"${v.environment}\" is not in environments`,\n ),\n );\n for (const [i, a] of (cfg.domains?.aliases ?? []).entries())\n if (a.environment != null && !has(cfg.environments, a.environment))\n errors.push(\n issue(\n ['domains', 'aliases', i, 'environment'],\n `environment \"${a.environment}\" is not in environments`,\n ),\n );\n\n const templates = cfg.templates;\n const at = cfg.navigation?.activeTemplate;\n if (at?.default != null && !has(templates, at.default))\n errors.push(\n issue(\n ['navigation', 'activeTemplate', 'default'],\n `template \"${at.default}\" is not in templates`,\n ),\n );\n for (const [bp, tpl] of Object.entries(at?.breakpoints ?? {}))\n if (!has(templates, tpl))\n errors.push(\n issue(\n ['navigation', 'activeTemplate', 'breakpoints', bp],\n `template \"${tpl}\" is not in templates`,\n ),\n );\n\n // Legal. An enabled document is a promise to publish a specific, correct\n // sentence — so the inputs those sentences interpolate are required here\n // rather than allowed to render as a blank. `jurisdiction` needs no check:\n // the enum rejects an unregistered value at parse time.\n const privacy = cfg.legal?.privacyPolicy;\n if (typeof privacy?.privacyOfficer === 'string' && !has(cfg.locations, privacy.privacyOfficer))\n errors.push(\n issue(\n ['legal', 'privacyPolicy', 'privacyOfficer'],\n `privacyOfficer \"${privacy.privacyOfficer}\" is not a locations key`,\n ),\n );\n if (privacy?.enabled) {\n if (resolvePrivacyContact(cfg) == null)\n errors.push(\n issue(\n ['legal', 'privacyPolicy'],\n 'privacyPolicy.enabled requires a contact for privacy requests — set legal.privacyPolicy.privacyOfficer, contact, or organization.email/address',\n ),\n );\n if (cfg.domains?.canonical == null)\n errors.push(\n issue(\n ['legal', 'privacyPolicy'],\n 'privacyPolicy.enabled requires domains.canonical — the policy states where information is held',\n ),\n );\n }\n\n // Indexing. Both defaults (the sitemap URL and the IndexNow key location) are\n // built from `domains.canonical`, so without it the block is unresolvable —\n // and the failure would otherwise surface at deploy time, as a submission\n // against `undefined/sitemap-index.xml`, rather than here.\n const indexing = cfg.seo?.indexing;\n if (indexing != null && cfg.domains?.canonical == null) {\n if (indexing.sitemapUrl == null)\n errors.push(\n issue(\n ['seo', 'indexing', 'sitemapUrl'],\n 'seo.indexing needs domains.canonical to derive the sitemap URL — set one, or state sitemapUrl explicitly',\n ),\n );\n if (indexing.indexNow != null && indexing.indexNow.keyLocation == null)\n errors.push(\n issue(\n ['seo', 'indexing', 'indexNow', 'keyLocation'],\n 'seo.indexing.indexNow needs domains.canonical to derive the key location — set one, or state keyLocation explicitly',\n ),\n );\n }\n\n if (errors.length) return { ok: false, data: undefined, errors };\n return { ok: true, data: cfg, errors: [] };\n}\n\n/**\n * Resolve who privacy requests go to: the explicit privacy officer, else the\n * site contact, else the primary location, else the organization itself.\n *\n * Exported because `validateSite` and the legal-document derivation must agree\n * on it exactly — a config that validates must be one the policy can render, and\n * two copies of this precedence would drift into a policy with a blank address.\n */\nexport function resolvePrivacyContact(cfg: SiteConfig): ContactObject | undefined {\n // A location's `name` is Localizable and a contact's is a plain string; the\n // name is not used in the rendered address, so drop it rather than pick a locale.\n const deref = (c: string | ContactObject | undefined): ContactObject | undefined => {\n if (c == null) return undefined;\n if (typeof c !== 'string') return c;\n const loc = cfg.locations?.[c];\n return loc && { email: loc.email, phone: loc.phone, address: loc.address };\n };\n const org = cfg.organization;\n const candidates = [\n deref(cfg.legal?.privacyPolicy?.privacyOfficer),\n deref(cfg.contact),\n deref(cfg.primaryLocation),\n org && { email: org.email, phone: org.phone, address: org.address },\n ];\n // A contact with no reachable channel is not a contact — skip to the next.\n return candidates.find((c) => c != null && (c.email != null || c.address != null));\n}\n\n// ── Theme resolution (extends) ──────────────────────────────────────────────────\n\ntype DesignSystemEntryT = Partial<DesignSystem> & { displayName?: unknown; extends?: string };\n\n/**\n * Resolve a design-system theme by following its `extends` chain and deep-merging\n * base → child (child wins; arrays replace wholesale, correct for token overrides).\n * Throws on unknown keys or an `extends` cycle. The result is a plain\n * `DesignSystem` (validate it against `DesignSystemSchema` for completeness).\n */\nexport function resolveTheme(\n designSystem: Record<string, DesignSystemEntryT>,\n key: string,\n): DesignSystem {\n const chain: DesignSystemEntryT[] = [];\n const seen = new Set<string>();\n let cur: string | undefined = key;\n while (cur != null) {\n if (seen.has(cur)) throw new Error(`extends cycle in designSystem at \"${cur}\"`);\n seen.add(cur);\n const entry: DesignSystemEntryT | undefined = designSystem[cur];\n if (entry == null) throw new Error(`designSystem theme \"${cur}\" not found`);\n chain.unshift(entry);\n cur = entry.extends;\n }\n const out: Record<string, unknown> = {};\n for (const entry of chain) {\n const { extends: _e, displayName: _d, ...ds } = entry;\n deepMerge(out, ds as Record<string, unknown>);\n }\n return out as DesignSystem;\n}\n\n/**\n * Normalise the two `designSystem` shorthands to the canonical\n * `{ themes: { … } }` shape.\n *\n * Both are keyed off what CANNOT be a theme name in the other reading:\n * - `colors` → a bare `DesignSystem` was written inline.\n * - `themes` → already canonical.\n * - neither → the legacy bare theme map, from before the block gained\n * system-wide fields. Every config authored against the old schema takes this\n * branch, which is what keeps the change forgiving at runtime even though the\n * published JSON Schema moved.\n */\nfunction normaliseDesignSystem(raw: Record<string, unknown>): void {\n const ds = raw.designSystem as Record<string, unknown> | undefined;\n if (ds == null || typeof ds !== 'object') return;\n if ('themes' in ds) return;\n raw.designSystem = 'colors' in ds ? { themes: { default: ds } } : { themes: ds };\n}\n\n/**\n * Resolve a raw (already-parsed) config into a validated `SiteConfig`:\n * 1. strip YAML nulls,\n * 2. normalise the `designSystem` shorthands to `{ themes: … }`,\n * 3. apply the active A/B variant's `overrides` (by `siteEnv`),\n * 4. validate (shape + cross-field).\n * Pure — no YAML/env access. A loader supplies `siteEnv`.\n *\n * Steps 2 and 3 are in this order deliberately. Normalising first means an\n * `abTesting` override always addresses the canonical shape\n * (`designSystem.themes.<name>`), whatever shorthand the base config used. With\n * the merge first, an override's key path depended on how the base happened to be\n * written — so the same patch hit a different place in two configs that were\n * otherwise equivalent.\n */\nexport function resolveSiteConfig(input: unknown, siteEnv = 'production'): SiteConfig {\n const raw = stripNulls(input) as Record<string, unknown>;\n\n normaliseDesignSystem(raw);\n\n const envConfig = (raw.environments as Record<string, { variant?: string }> | undefined)?.[\n siteEnv\n ];\n if (envConfig?.variant) {\n const overrides = (\n raw.abTesting as { variants?: Record<string, { overrides?: Record<string, unknown> }> }\n )?.variants?.[envConfig.variant]?.overrides;\n if (overrides) {\n // An override may itself use a shorthand; normalise it to the same shape or\n // deepMerge would nest a bare map under the canonical one.\n normaliseDesignSystem(overrides);\n deepMerge(raw, overrides);\n }\n }\n\n const result = validateSite(raw);\n if (!result.ok) {\n const msg = result.errors.map((e) => ` ${e.path.join('.')}: ${e.message}`).join('\\n');\n throw new Error(`Invalid site config:\\n${msg}`);\n }\n return result.data;\n}\n\n// ── Accepting either config kind ────────────────────────────────────────────────\n\n/**\n * Is this raw config a `SiteConfig` rather than a bare `design-system.json`?\n *\n * The discriminator is **total**, not a heuristic, and both halves are load-\n * bearing: `SiteConfigSchema` cannot validate without a `designSystem` (a config\n * lacking one fails `validateSite` with `themes must include a \"default\" entry`),\n * and `DesignSystemSchema` is strict, so a `designSystem` key in a design system\n * is an `unrecognized_keys` error. No document can be read as both, and no\n * document that is neither reaches here without failing validation anyway.\n *\n * Deliberately shape-based rather than filename-based: consumers name this file\n * whatever suits them (`company.json`, `site.json`, `vitops.config.json`), and a\n * rule keyed to a name would silently stop working the moment someone renamed it.\n */\nexport function isSiteConfig(raw: unknown): boolean {\n return typeof raw === 'object' && raw != null && !Array.isArray(raw) && 'designSystem' in raw;\n}\n\n/** What a config file turned out to hold. */\nexport interface ResolvedInput {\n /** The design system to build from — a resolved theme, if the input was a `SiteConfig`. */\n designSystem: DesignSystem;\n /** The site config, when that is what the input was. */\n site?: SiteConfig;\n /** Which `themes` key was selected. Absent for a bare `design-system.json`. */\n theme?: string;\n}\n\n/**\n * Resolve a raw config of either kind into the design system to build from.\n *\n * Every entry point that used to take a `design-system.json` goes through this,\n * so a consumer who keeps their tokens inside the larger site config points the\n * same option at that file instead of maintaining a second one. The site config\n * is handed back too, because the parts of generation that depend on site-level\n * facts (`designSystem.defaultColorScheme`, the legal documents, the icon\n * sprite) would otherwise need the same path declared a second time.\n *\n * The returned `designSystem` is **not** validated here — the caller does that,\n * so it can say which file and which theme the errors belong to. Validation of\n * the site config itself has already happened (`resolveSiteConfig` throws).\n */\nexport function resolveInput(\n raw: unknown,\n opts: { theme?: string; siteEnv?: string } = {},\n): ResolvedInput {\n if (!isSiteConfig(raw)) {\n if (opts.theme != null)\n throw new Error(\n `theme \"${opts.theme}\" was requested, but this is a design-system.json — it holds one ` +\n 'design system and no `themes` map. Point at a site config to select a theme.',\n );\n return { designSystem: raw as DesignSystem };\n }\n const site = resolveSiteConfig(raw, opts.siteEnv);\n const themes = (site.designSystem?.themes ?? {}) as Record<string, DesignSystemEntryT>;\n const theme = opts.theme ?? site.designSystem?.defaultTheme ?? 'default';\n if (!(theme in themes))\n throw new Error(\n `designSystem.themes has no \"${theme}\" entry (found: ${Object.keys(themes).join(', ') || 'none'})`,\n );\n return { designSystem: resolveTheme(themes, theme), site, theme };\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────────\n\n/** Strip nulls (YAML `~`/`null`) → undefined so optional fields validate. */\nexport function stripNulls(obj: unknown): unknown {\n if (obj === null) return undefined;\n if (Array.isArray(obj)) return obj.map(stripNulls);\n if (obj && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const stripped = stripNulls(value);\n if (stripped !== undefined) result[key] = stripped;\n }\n return result;\n }\n return obj;\n}\n\n/** Deep-merge `source` into `target` (in place). Arrays replace wholesale. */\nexport function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>) {\n for (const key of Object.keys(source)) {\n const s = source[key];\n const t = target[key];\n if (\n s &&\n typeof s === 'object' &&\n !Array.isArray(s) &&\n t &&\n typeof t === 'object' &&\n !Array.isArray(t)\n ) {\n deepMerge(t as Record<string, unknown>, s as Record<string, unknown>);\n } else {\n target[key] = s;\n }\n }\n}\n","/**\n * What the config already tells us about third parties that receive personal\n * information.\n *\n * A privacy policy's riskiest sentence is the one naming service providers: if\n * it says \"Plausible\" while the site runs Google Analytics, the document is a\n * compliance defect, not a typo. The site config already records which analytics\n * ID is set, whether Turnstile is deployed and where the site is hosted — so the\n * sentence derives from those signals rather than from a hand-maintained string\n * that drifts the moment someone swaps providers.\n *\n * Presence of the key is the signal, matching how `analytics` already works\n * (provider identity is implied by which ID is set, not by an enum).\n *\n * This table is deliberately small and covers only what the schema can imply.\n * Everything else — payment processors, CRMs, mail senders — is declared by the\n * consumer in `legal.privacyPolicy.processors`, which flows through the same\n * pipeline. This is not a directory of the web; it's the set of providers the\n * toolchain itself can vouch for.\n */\nimport type { SiteConfig } from '../site.ts';\n\nexport interface Processor {\n /** The provider as a reader would recognise it. */\n name: string;\n /** Reads after \"for\": \"…to Stripe for payment processing\". */\n purpose: string;\n /** Reads inside a sentence: \"…including the United States\". */\n country?: string | undefined;\n privacyUrl?: string | undefined;\n /**\n * Cookies this provider sets. An empty array is meaningful and not the same as\n * `undefined`: it asserts the provider is cookieless (Plausible), which the\n * cookie notice states positively rather than omitting.\n */\n cookies?: string[] | undefined;\n /** A user-facing opt-out, when the provider offers one. */\n optOut?: string | undefined;\n}\n\n/**\n * The providers the config can imply. Keyed for testability — a test can assert\n * a given config resolves to a given key without matching on prose.\n */\nexport const KNOWN_PROCESSORS = {\n googleAnalytics: {\n name: 'Google Analytics',\n purpose: 'website analytics',\n country: 'the United States',\n privacyUrl: 'https://policies.google.com/privacy',\n cookies: ['_ga', '_gid'],\n optOut: 'https://tools.google.com/dlpage/gaoptout',\n },\n googleTagManager: {\n name: 'Google Tag Manager',\n purpose: 'tag management',\n country: 'the United States',\n privacyUrl: 'https://policies.google.com/privacy',\n cookies: [],\n },\n plausible: {\n name: 'Plausible Analytics',\n purpose: 'website analytics',\n country: 'the European Union',\n privacyUrl: 'https://plausible.io/privacy',\n // Plausible sets no cookies and stores no cross-site identifiers. Stated as\n // an empty list rather than omitted, so the cookie notice can say so.\n cookies: [],\n },\n clarity: {\n name: 'Microsoft Clarity',\n purpose: 'session replay and heatmaps',\n country: 'the United States',\n privacyUrl: 'https://privacy.microsoft.com/privacystatement',\n // Clarity records what a visitor does on the page, not just that they were\n // here, so the purpose says \"session replay\" rather than \"analytics\" — a\n // reader deciding whether to consent needs to know they may be recorded.\n cookies: ['_clck', '_clsk', 'MUID'],\n optOut: 'https://privacy.microsoft.com/privacystatement',\n },\n // Matomo appears twice on purpose: whether it sets cookies is a *configuration*\n // choice (`analytics.matomo.cookies`), and the notice says something materially\n // different in each case. One entry with a conditional cookie list would put\n // that branch in the prose layer, where the rule is that templates own wording\n // and never facts.\n matomo: {\n name: 'Matomo',\n purpose: 'website analytics',\n privacyUrl: 'https://matomo.org/privacy-policy/',\n cookies: ['_pk_id', '_pk_ses'],\n },\n matomoCookieless: {\n name: 'Matomo',\n purpose: 'website analytics',\n privacyUrl: 'https://matomo.org/privacy-policy/',\n // `disableCookies` is on: Matomo stores no identifier on the device. The\n // empty list is the assertion — see the Processor.cookies note above.\n cookies: [],\n },\n turnstile: {\n name: 'Cloudflare Turnstile',\n purpose: 'bot protection on forms',\n country: 'the United States',\n privacyUrl: 'https://www.cloudflare.com/privacypolicy/',\n cookies: ['cf_clearance'],\n },\n cloudflare: {\n name: 'Cloudflare',\n purpose: 'website hosting and content delivery',\n country: 'the United States',\n privacyUrl: 'https://www.cloudflare.com/privacypolicy/',\n cookies: [],\n },\n vercel: {\n name: 'Vercel',\n purpose: 'website hosting',\n country: 'the United States',\n privacyUrl: 'https://vercel.com/legal/privacy-policy',\n cookies: [],\n },\n netlify: {\n name: 'Netlify',\n purpose: 'website hosting',\n country: 'the United States',\n privacyUrl: 'https://www.netlify.com/privacy/',\n cookies: [],\n },\n} satisfies Record<string, Processor>;\n\nexport type KnownProcessorKey = keyof typeof KNOWN_PROCESSORS;\n\n/** Substring → hosting provider. `deployment.platform` is a free-form string. */\nconst HOSTING_PATTERNS: [RegExp, KnownProcessorKey][] = [\n [/cloudflare|workers|pages\\.dev/i, 'cloudflare'],\n [/vercel/i, 'vercel'],\n [/netlify/i, 'netlify'],\n];\n\n/**\n * Which known providers this config implies, in a stable order (analytics →\n * security → hosting) so the rendered sentence doesn't churn between builds.\n *\n * Returns keys rather than processors so a caller can test the detection\n * independently of the prose attached to it.\n */\nexport function detectProcessorKeys(site: SiteConfig): KnownProcessorKey[] {\n const keys: KnownProcessorKey[] = [];\n const analytics = site.analytics;\n if (analytics?.googleAnalyticsId) keys.push('googleAnalytics');\n if (analytics?.googleTagManagerId) keys.push('googleTagManager');\n if (analytics?.plausibleDomain) keys.push('plausible');\n if (analytics?.clarityId) keys.push('clarity');\n // Cookieless is the default, matching the tag the Astro integration emits\n // (`_paq.push(['disableCookies'])` unless `cookies: true`). The two must agree:\n // a notice claiming no cookies while the tag sets them is the defect this whole\n // table exists to prevent.\n if (analytics?.matomo) keys.push(analytics.matomo.cookies ? 'matomo' : 'matomoCookieless');\n if (site.security?.turnstile?.siteKey) keys.push('turnstile');\n\n const platform = site.deployment?.platform;\n const hosting = platform && HOSTING_PATTERNS.find(([re]) => re.test(platform))?.[1];\n // Turnstile already names Cloudflare; listing it twice reads as sloppy and\n // implies two relationships where there is one.\n if (hosting && !keys.includes(hosting)) keys.push(hosting);\n return keys;\n}\n\n/**\n * Every processor this policy must disclose: the ones implied by the config,\n * then the ones the consumer declared.\n *\n * Consumer entries come last and are never deduplicated against the built-ins —\n * an explicit declaration is a statement of fact we have no grounds to drop.\n */\nexport function resolveProcessors(site: SiteConfig): Processor[] {\n const detected = detectProcessorKeys(site).map((k) =>\n matomoCountry(KNOWN_PROCESSORS[k] as Processor, site),\n );\n const declared = site.legal?.privacyPolicy?.processors ?? [];\n return [...detected, ...declared];\n}\n\n/**\n * Matomo is the one provider whose location the config actually knows.\n *\n * Matomo Cloud is hosted in the EU; a self-hosted instance is wherever the\n * consumer put it, which is very often their own infrastructure in their own\n * country. So the cross-border transfer sentence is asserted only for the case we\n * can see. Naming a transfer that isn't happening is the same class of error as\n * omitting one that is — the config records facts, and \"we don't know\" is a fact.\n */\nfunction matomoCountry(processor: Processor, site: SiteConfig): Processor {\n if (processor.name !== 'Matomo') return processor;\n const url = site.analytics?.matomo?.url ?? '';\n return /\\.matomo\\.cloud/i.test(url) ? { ...processor, country: 'the European Union' } : processor;\n}\n","/**\n * Site config → the facts a legal document asserts.\n *\n * The division of labour here is the whole point: **the config records facts,\n * the template owns prose.** Nothing in this module writes a sentence a lawyer\n * would need to review, and nothing in a template invents a fact. That is what\n * lets the wording be corrected without touching a consumer's config, and a\n * consumer's provider to change without touching the prose.\n *\n * Everything it returns is derived from config the site already has to hold to\n * function — which analytics ID is set, which forms exist, where it deploys —\n * plus the facts a consumer declares in `legal.privacyPolicy`. There is no\n * source of truth here beyond `SiteConfig`.\n *\n * Pure: no I/O, no clock. `lastUpdated` comes from the config rather than\n * `Date.now()` so a rebuild produces a byte-identical document.\n */\nimport { t } from '@getvitops/utils';\nimport { resolvePrivacyContact, type ContactObject, type SiteConfig } from '../site.ts';\nimport { resolveProcessors, type Processor } from './providers.ts';\n\n/**\n * The facts every legal template renders from.\n *\n * List-shaped fields are `string[]`, not pre-joined strings, because they land\n * in bullet positions: a template that splices an empty string into a list emits\n * a stray `-` bullet, and that is exactly the kind of silent breakage a\n * published policy must not have.\n */\nexport interface PolicyVars {\n businessName: string;\n url: string;\n /** Reads after \"at\": \"…contact our Privacy Officer at <this>.\" */\n mailingAddress: string;\n lastUpdated: string | undefined;\n /** Extra retention sentence, when the consumer stated one. */\n retention: string | undefined;\n /** A consumer-supplied governing-law phrase, which wins over the two below. */\n governingLaw: string | undefined;\n /** Province/territory, spelled out — \"Ontario\", never \"ON\". */\n governingProvince: string | undefined;\n governingCountry: string;\n\n /** Circumstances in which personal information is collected. */\n collectionReasons: string[];\n /** Categories of personal information collected. */\n piiCollected: string[];\n /** What the browser sends automatically. */\n techInfo: string[];\n /** Why that technical information is used. */\n techInfoPurposes: string[];\n /** What cookies track. */\n cookieTracked: string[];\n /** Why cookies are used. */\n cookiePurposes: string[];\n /** A sentence about the consent tool, or `undefined` when there is none. */\n cookieTool: string | undefined;\n /** How collected information is used. */\n usePurposes: string[];\n /** Choices a visitor has. */\n optOutOptions: string[];\n /** The subset of `optOutOptions` about cookies — an e-mail unsubscribe link is\n * not a cookie choice, and listing it in a cookie notice reads as padding. */\n cookieOptOutOptions: string[];\n\n processors: Processor[];\n /** Reads after \"including\": \"…the United States and the European Union\". */\n countries: string | undefined;\n consentModel: 'opt-in' | 'opt-out' | 'none';\n cookieCategories: string[];\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────────\n\n/** \"A\", \"A and B\", \"A, B and C\". */\nexport function list(items: string[]): string {\n if (items.length <= 1) return items[0] ?? '';\n return `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`;\n}\n\n/** Order-preserving dedupe — the bullet lists are assembled from several sources. */\nconst uniq = (items: (string | undefined)[]): string[] => [\n ...new Set(items.filter((s): s is string => !!s)),\n];\n\n/**\n * Render a contact into the phrase that follows \"at\". Prefers e-mail (the\n * channel a reader can actually use from the page) and adds the postal address\n * when there is one, because access and correction requests are commonly posted.\n */\nfunction formatContact(contact: ContactObject | undefined): string {\n if (!contact) return '';\n const a = contact.address;\n const postal =\n a &&\n [\n a.streetAddress,\n a.addressLocality,\n [a.addressRegion, a.postalCode].filter(Boolean).join(' '),\n a.addressCountry,\n ]\n .filter(Boolean)\n .join(', ');\n if (contact.email && postal) return `${contact.email}, or by mail at ${postal}`;\n return contact.email ?? postal ?? '';\n}\n\n/**\n * What a form field actually collects, as a noun phrase.\n *\n * Typed fields carry their meaning (`email` is an e-mail address in any form);\n * `text` does not, so it falls back to the field's name. A policy that under-\n * describes what a form collects is the failure mode worth avoiding, so an\n * unrecognised text field lands in a catch-all bullet rather than being dropped.\n */\nfunction fieldPhrase(name: string, type: string): string | undefined {\n switch (type) {\n // `hidden` is not visitor-supplied and a honeypot exists to be left empty —\n // describing either as collected information would be inaccurate.\n case 'hidden':\n return undefined;\n case 'email':\n return 'your e-mail address';\n case 'tel':\n return 'your telephone number';\n case 'url':\n return 'any website address you provide';\n case 'date':\n return 'any dates you provide';\n case 'file':\n return 'any files or documents you upload';\n case 'textarea':\n return 'the content of the messages you send us';\n case 'number':\n return 'any numeric details you provide';\n case 'password':\n return 'account credentials';\n case 'select':\n case 'radio':\n case 'checkbox':\n return 'your answers to the questions we ask';\n default:\n break;\n }\n if (/name/i.test(name)) return 'your name';\n if (/compan|organi|business/i.test(name)) return 'your company or organization name';\n if (/address|street|city|province|state|postal|zip|country/i.test(name))\n return 'your mailing address';\n return 'the other details you enter in our forms';\n}\n\nconst PROVINCES: Record<string, string> = {\n AB: 'Alberta',\n BC: 'British Columbia',\n MB: 'Manitoba',\n NB: 'New Brunswick',\n NL: 'Newfoundland and Labrador',\n NS: 'Nova Scotia',\n NT: 'Northwest Territories',\n NU: 'Nunavut',\n ON: 'Ontario',\n PE: 'Prince Edward Island',\n QC: 'Quebec',\n SK: 'Saskatchewan',\n YT: 'Yukon',\n};\n\n/**\n * `addressRegion` is conventionally a two-letter code, which is right for a\n * postal address and wrong inside a governing-law clause — \"the laws of ON\" is\n * not a sentence a lawyer would sign off. Anything already spelled out (or from\n * another country) passes through untouched.\n */\nfunction expandProvince(region: string | undefined): string | undefined {\n if (!region) return undefined;\n return PROVINCES[region.toUpperCase()] ?? region;\n}\n\n/** Every field across every `form` template, honeypots excluded. */\nfunction formFields(site: SiteConfig): { name: string; type: string }[] {\n const out: { name: string; type: string }[] = [];\n for (const tpl of Object.values(site.templates ?? {})) {\n if (tpl.type !== 'form') continue;\n for (const f of tpl.fields ?? []) out.push({ name: f.name, type: f.type });\n }\n return out;\n}\n\n// ── Derivation ──────────────────────────────────────────────────────────────────\n\nexport function derivePolicyVars(site: SiteConfig): PolicyVars {\n const locale = site.defaultLocale;\n const org = site.organization;\n const legal = site.legal;\n const privacy = legal?.privacyPolicy;\n const processors = resolveProcessors(site);\n const fields = formFields(site);\n const hasForms = fields.length > 0;\n // Any configured provider counts, whether its config is an ID string\n // (`googleAnalyticsId`) or an object (`matomo`). Checking only for strings\n // would silently under-report a Matomo-only site as having no analytics at all.\n const hasAnalytics = Object.values(site.analytics ?? {}).some((v) =>\n typeof v === 'string' ? v.length > 0 : !!v,\n );\n const cookieProcessors = processors.filter((p) => p.cookies?.length);\n const consent = legal?.cookieConsent;\n const contact = resolvePrivacyContact(site);\n\n const businessName =\n org?.legalName ?? (org?.name != null ? t(org.name, locale, locale) : undefined) ?? 'we';\n\n const collectionReasons = uniq([\n 'contact us through e-mail, telephone, mail or other correspondence',\n hasForms ? 'submit one of the forms on our Site' : undefined,\n site.services && Object.keys(site.services).length > 0\n ? 'register for a service we provide'\n : undefined,\n fields.some((f) => /newsletter|subscribe|mailing/i.test(f.name))\n ? 'register to receive our newsletter'\n : undefined,\n ]);\n\n // Only claim to collect what a configured form actually asks for. With no\n // forms, the generic categories stand in — the site still receives whatever a\n // visitor sends by e-mail.\n const piiCollected = uniq([\n ...(hasForms\n ? fields.map((f) => fieldPhrase(f.name, f.type))\n : [\n 'your full name',\n 'contact information, such as your address, telephone number, or e-mail address',\n ]),\n 'any other personal information that you choose to submit to us',\n ]);\n\n // Session replay is a materially different disclosure from page-view analytics\n // and cannot be folded into `hasAnalytics`: a policy that lists \"the pages you\n // view\" while the site records mouse movement, scrolling and clicks is\n // under-disclosing, not summarising.\n const hasSessionReplay = !!site.analytics?.clarityId;\n\n const techInfo = uniq([\n 'your domain name',\n 'your numerical IP address',\n hasAnalytics ? 'the pages you view and the files you request' : undefined,\n hasAnalytics ? 'the type of browser and operating system you use' : undefined,\n hasAnalytics ? 'the address of the site that referred you' : undefined,\n hasSessionReplay\n ? 'a recording of how you interacted with a page, including mouse movement, scrolling and clicks'\n : undefined,\n ]);\n\n const techInfoPurposes = uniq([\n hasAnalytics ? 'measure the performance of our Site' : undefined,\n hasSessionReplay ? 'see where visitors encounter difficulty using our Site' : undefined,\n site.security?.turnstile?.siteKey\n ? 'protect our Site and its forms from automated abuse'\n : undefined,\n 'better understand how visitors use our Site',\n 'improve our Site to better meet your needs',\n ]);\n\n const ab = site.abTesting;\n const cookieTracked = uniq([\n 'your IP address',\n 'the type of web browser and operating system used',\n 'the pages of the Site visited',\n ab?.enabled ? 'which version of a page you were shown' : undefined,\n hasSessionReplay ? 'how you moved through and interacted with a page' : undefined,\n ]);\n\n const cookiePurposes = uniq([\n 'keep the Site functioning as you move between pages',\n hasAnalytics ? 'understand how our Site is used, in aggregate' : undefined,\n hasSessionReplay ? 'recognise a returning visit as part of the same session' : undefined,\n ab?.enabled ? 'keep you on a consistent version of the Site between visits' : undefined,\n site.security?.turnstile?.siteKey ? 'distinguish visitors from automated traffic' : undefined,\n ]);\n\n const cookieTool = consent?.enabled\n ? consent.type === 'opt-in'\n ? 'You may also choose which categories of cookies to allow using the consent banner shown when you first visit our Site, and you may change that choice at any time.'\n : 'You may also withdraw your consent to non-essential cookies at any time using the consent controls on our Site.'\n : undefined;\n\n const usePurposes = uniq([\n 'respond to your inquiries',\n 'supply you with requested products or services',\n site.notifications?.email\n ? 'route your message to the appropriate person in our organization'\n : undefined,\n site.tracking?.enabled ? 'measure the effectiveness of our marketing' : undefined,\n 'send you informational or promotional communication',\n 'carry out other purposes that are disclosed to you and to which you consent',\n 'carry out any other purpose permitted or required by law',\n ]);\n\n const cookieOptOutOptions = uniq([\n 'You may configure your browser to refuse cookies, though parts of our Site may not function as intended.',\n consent?.enabled ? cookieTool : undefined,\n ...processors\n .filter((p) => p.optOut)\n .map((p) => `You may opt out of ${p.name} directly at ${p.optOut}.`),\n ]);\n\n const optOutOptions = uniq([\n 'You may unsubscribe from any commercial e-mail we send using the \"unsubscribe\" link in that e-mail.',\n ...cookieOptOutOptions,\n ]);\n\n const countries = list(uniq(processors.map((p) => p.country)));\n\n const address = contact?.address ?? org?.address;\n\n return {\n businessName,\n url: site.domains?.canonical ?? '',\n mailingAddress: formatContact(contact),\n lastUpdated: privacy?.lastUpdated,\n retention: privacy?.retention,\n governingLaw: legal?.termsOfService?.governingLaw,\n governingProvince: expandProvince(address?.addressRegion),\n governingCountry: address?.addressCountry ?? 'Canada',\n collectionReasons,\n piiCollected,\n techInfo,\n techInfoPurposes,\n cookieTracked,\n cookiePurposes,\n cookieTool,\n usePurposes,\n optOutOptions,\n cookieOptOutOptions,\n processors,\n countries: countries || undefined,\n consentModel: consent?.enabled ? (consent.type ?? 'opt-in') : 'none',\n cookieCategories: consent?.categories ?? [],\n };\n}\n","/**\n * The legal documents are authored in markdown; consumers need markdown, HTML\n * and EmDash Portable Text. This parses the markdown **once** into a small block\n * model, and the three outputs render from that.\n *\n * The subset is **closed by construction** — we author every template, so the\n * parser does not need to be a markdown implementation, it needs to be exactly\n * as capable as the templates are. That is why it *throws* on anything outside\n * the subset rather than passing it through: an unrecognised construct that\n * silently degrades to a paragraph is how a published policy ends up with a\n * literal `| --- |` in it. A template that grows a table fails the test suite\n * instead.\n *\n * Supported, and nothing else:\n * block `#`/`##`/`###` headings, `- ` bullets, `> ` quote, paragraphs\n * inline `**strong**`, `` `code` ``\n *\n * HTML rendering delegates to `nodesToHtml` from `@getvitops/utils`, which\n * already solves escaping and void elements — this module maps to `ContentNode`\n * and stops there.\n */\nimport { nodesToHtml, type ContentNode } from '@getvitops/utils';\n\nexport interface Span {\n text: string;\n strong?: boolean;\n code?: boolean;\n}\n\nexport type Block =\n | { kind: 'heading'; level: 1 | 2 | 3; spans: Span[] }\n | { kind: 'paragraph'; spans: Span[] }\n | { kind: 'list'; items: Span[][] }\n | { kind: 'quote'; spans: Span[] };\n\n/** Constructs that look like markdown but are outside the subset. */\nconst UNSUPPORTED: [RegExp, string][] = [\n [/^#{4,}\\s/, 'headings deeper than ###'],\n [/^\\s*\\d+[.)]\\s/, 'ordered lists'],\n [/^\\s*```/, 'code fences'],\n [/^\\s*\\|/, 'tables'],\n [/^\\s*[*+]\\s/, 'bullets other than `- `'],\n [/^\\s+-\\s/, 'nested lists'],\n];\n\n// Bold and code spans, in one pass so a `**` inside backticks stays literal.\nconst INLINE = /(\\*\\*[^*]+\\*\\*|`[^`]+`)/g;\n\nfunction parseInline(text: string, where: string): Span[] {\n const spans: Span[] = [];\n let last = 0;\n for (const m of text.matchAll(INLINE)) {\n const token = m[0];\n if (m.index > last) spans.push({ text: text.slice(last, m.index) });\n if (token.startsWith('`')) spans.push({ text: token.slice(1, -1), code: true });\n else spans.push({ text: token.slice(2, -2), strong: true });\n last = m.index + token.length;\n }\n if (last < text.length) spans.push({ text: text.slice(last) });\n\n // Check what's left as literal text, so `**bold**` doesn't trip the `*` guard\n // and a cookie name like `_ga` (already inside a code span) doesn't either.\n for (const span of spans) {\n if (span.strong || span.code) continue;\n if (/!?\\[[^\\]]*\\]\\(/.test(span.text))\n throw new Error(\n `legal template uses links or images, which are outside the subset: ${where}`,\n );\n if (span.text.includes('**'))\n throw new Error(`legal template has an unmatched \\`**\\`: ${where}`);\n if (span.text.includes('`'))\n throw new Error(`legal template has an unmatched backtick: ${where}`);\n }\n return spans;\n}\n\n/** Markdown (our subset) → blocks. Throws on anything it does not model. */\nexport function parseMarkdown(md: string): Block[] {\n const blocks: Block[] = [];\n const lines = md.split('\\n');\n let paragraph: string[] = [];\n\n const flush = () => {\n if (paragraph.length === 0) return;\n const text = paragraph.join(' ');\n blocks.push({ kind: 'paragraph', spans: parseInline(text, text.slice(0, 60)) });\n paragraph = [];\n };\n\n for (const line of lines) {\n for (const [re, what] of UNSUPPORTED)\n if (re.test(line))\n throw new Error(`legal template uses ${what}, outside the subset: ${line}`);\n\n if (line.trim() === '') {\n flush();\n continue;\n }\n\n const heading = /^(#{1,3})\\s+(.*)$/.exec(line);\n if (heading) {\n flush();\n blocks.push({\n kind: 'heading',\n level: heading[1]!.length as 1 | 2 | 3,\n spans: parseInline(heading[2]!.trim(), line),\n });\n continue;\n }\n\n const quote = /^>\\s+(.*)$/.exec(line);\n if (quote) {\n flush();\n blocks.push({ kind: 'quote', spans: parseInline(quote[1]!.trim(), line) });\n continue;\n }\n\n const bullet = /^-\\s+(.*)$/.exec(line);\n if (bullet) {\n flush();\n const item = parseInline(bullet[1]!.trim(), line);\n // Consecutive `- ` lines are one list; a blank line between them starts a\n // new one, which is what markdown means and what the templates rely on.\n const prev = blocks[blocks.length - 1];\n if (prev?.kind === 'list') prev.items.push(item);\n else blocks.push({ kind: 'list', items: [item] });\n continue;\n }\n\n paragraph.push(line.trim());\n }\n flush();\n return blocks;\n}\n\n// ── ContentNode / HTML ──────────────────────────────────────────────────────────\n\nfunction spanNodes(spans: Span[]): ContentNode[] {\n return spans.map((s) =>\n s.strong ? { tag: 'strong', text: s.text } : s.code ? { tag: 'code', text: s.text } : s.text,\n );\n}\n\n/**\n * Blocks → `ContentNode[]`, the framework-agnostic tree the site config already\n * uses for `templates` of type `nodes` and `NodeRenderer.astro` already renders.\n */\nexport function toContentNodes(blocks: Block[]): ContentNode[] {\n return blocks.map((b): ContentNode => {\n switch (b.kind) {\n case 'heading':\n return { tag: `h${b.level}`, children: spanNodes(b.spans) };\n case 'paragraph':\n return { tag: 'p', children: spanNodes(b.spans) };\n case 'quote':\n return { tag: 'blockquote', children: [{ tag: 'p', children: spanNodes(b.spans) }] };\n case 'list':\n return {\n tag: 'ul',\n children: b.items.map((item) => ({ tag: 'li', children: spanNodes(item) })),\n };\n }\n });\n}\n\nexport function toHtmlFragment(blocks: Block[]): string {\n return nodesToHtml(toContentNodes(blocks));\n}\n\n// ── Portable Text (EmDash) ──────────────────────────────────────────────────────\n\n/**\n * Blocks → EmDash Portable Text, matching the shape already seeded in\n * `packages/create/templates/emdash/seed/seed.json`.\n *\n * Two deliberate mappings:\n * - the `# ` heading is **dropped** — in EmDash the page title is a field\n * (`data.title`), and repeating it as the first content block renders twice;\n * - the review blockquote becomes a `vitops.banner` with `tone: \"warning\"`,\n * which is exactly the block the hand-written placeholder pages used.\n *\n * `_key`s are derived from position rather than randomness, so regenerating an\n * unchanged config produces an identical seed and a clean diff.\n */\nexport function toPortableText(blocks: Block[], prefix: string): unknown[] {\n const out: unknown[] = [];\n blocks.forEach((b, i) => {\n const key = `${prefix}-${i}`;\n if (b.kind === 'heading' && b.level === 1) return;\n\n if (b.kind === 'quote') {\n out.push({\n _type: 'vitops.banner',\n _key: key,\n message: b.spans.map((s) => s.text).join(''),\n tone: 'warning',\n dismissible: false,\n });\n return;\n }\n\n const block = (spans: Span[], k: string, extra: Record<string, unknown>) => ({\n _type: 'block',\n _key: k,\n markDefs: [],\n children: spans.map((s, j) => ({\n _type: 'span',\n _key: `${k}-${j}`,\n text: s.text,\n marks: [s.strong && 'strong', s.code && 'code'].filter(Boolean),\n })),\n ...extra,\n });\n\n if (b.kind === 'list') {\n b.items.forEach((item, j) =>\n out.push(block(item, `${key}-${j}`, { style: 'normal', listItem: 'bullet', level: 1 })),\n );\n return;\n }\n\n out.push(block(b.spans, key, { style: b.kind === 'heading' ? `h${b.level}` : 'normal' }));\n });\n return out;\n}\n","/**\n * Pieces every legal template shares.\n *\n * Kept deliberately tiny: anything that grows here is prose leaking out of the\n * jurisdiction-specific templates into a shared file, which is how a document\n * ends up asserting something that isn't true of the body of law it claims to\n * follow. Formatting helpers belong here; sentences almost never do.\n */\nimport type { PolicyVars } from '../derive.ts';\n\n/**\n * The banner every generated document opens with.\n *\n * Not optional and not configurable. These documents are rendered from a\n * template by a build tool, not drafted for a specific business by someone who\n * can be asked follow-up questions — and the one failure mode with real\n * consequences is a consumer publishing one as-is. It is a blockquote so it\n * renders as a callout in HTML and as a warning banner in EmDash.\n */\nexport const REVIEW_NOTICE =\n \"> Generated from this site's configuration. It is a starting point, not legal advice — have it reviewed before you publish it, and make sure it matches what your site actually does.\";\n\n/** A markdown bullet list. Empty in, empty out — never a stray `-`. */\nexport function bullets(items: string[]): string {\n return items.map((item) => `- ${item}`).join('\\n');\n}\n\n/**\n * Taken from config rather than the clock, so a rebuild of an unchanged config\n * produces a byte-identical document.\n */\nexport function updatedLine(v: Pick<PolicyVars, 'lastUpdated'>): string {\n return v.lastUpdated ? `\\nLast updated: ${v.lastUpdated}\\n` : '';\n}\n","/**\n * Cookie notice — Canada.\n *\n * The one document here that is almost entirely derived: which cookies a site\n * sets follows from which providers it uses, and the config already knows that.\n * The prose is a frame around `v.processors` and `v.cookieCategories`.\n *\n * Rendered as headings and bullets rather than a table, deliberately — the\n * markdown subset the renderer supports is closed, and a table would widen it\n * for one document. Bullets also survive a narrow viewport, which a four-column\n * cookie table does not.\n */\nimport { list, type PolicyVars } from '../derive.ts';\nimport { bullets, REVIEW_NOTICE, updatedLine } from './shared.ts';\n\nexport function cookiesCa(v: PolicyVars): string {\n return `# Cookie Notice\n${updatedLine(v)}\n${REVIEW_NOTICE}\n\nThis notice explains how ${v.businessName} uses cookies and similar technologies on ${v.url} (the \"Site\"). It supplements our Privacy Policy.\n\n## What Cookies Are\n\nA cookie is a small text file that a website asks your browser to store. Cookies let a site remember things between pages and between visits — for example, that you have already dismissed a message. Similar technologies, such as local storage, do much the same thing.\n\n## What We Use Them For\n\n${bullets(v.cookiePurposes)}\n\nCookies used on this Site may track:\n\n${bullets(v.cookieTracked)}\n\n${providersSection(v)}${categoriesSection(v)}\n## Your Choices\n\n${bullets(v.cookieOptOutOptions)}\n\nMost browsers let you see which cookies are stored, delete them individually or in bulk, and block them entirely. Blocking all cookies will stop parts of the Site from working as intended.\n\n## Contact\n\nIf you have questions about our use of cookies, please contact us at ${v.mailingAddress}.\n`;\n}\n\n/**\n * \"This site sets no cookies\" is a real and increasingly common answer — a\n * cookieless analytics provider is a selling point, not an omission. Saying it\n * plainly beats an empty section that reads as an oversight.\n */\nfunction providersSection(v: PolicyVars): string {\n const setting = v.processors.filter((p) => p.cookies?.length);\n const cookieless = v.processors.filter((p) => p.cookies?.length === 0);\n\n if (setting.length === 0) {\n const named = cookieless.length\n ? ` The third party ${cookieless.length === 1 ? 'service' : 'services'} we use on this Site — ${list(\n cookieless.map((p) => p.name),\n )} — ${cookieless.length === 1 ? 'does' : 'do'} not set cookies of ${\n cookieless.length === 1 ? 'its' : 'their'\n } own.`\n : '';\n return `## Cookies Set on This Site\n\nBeyond the cookies strictly necessary to serve and secure the Site, we do not set cookies.${named}\n`;\n }\n\n return `## Cookies Set on This Site\n\n${bullets(\n setting.map(\n (p) =>\n // Cookie names go in code spans, not bare: `_ga, _gid` in running markdown\n // is a matched pair of underscores, which a downstream renderer turns into\n // emphasis and eats the names.\n `**${p.name}** (${p.purpose}) — ${(p.cookies ?? []).map((c) => `\\`${c}\\``).join(', ')}${\n p.privacyUrl ? `. Privacy policy: ${p.privacyUrl}` : ''\n }`,\n ),\n)}\n${\n cookieless.length\n ? `\\nWe also use ${list(cookieless.map((p) => p.name))}, which ${\n cookieless.length === 1 ? 'does' : 'do'\n } not set cookies of ${cookieless.length === 1 ? 'its' : 'their'} own.\\n`\n : ''\n}`;\n}\n\n/** Only meaningful when a consent tool actually offers the categories. */\nfunction categoriesSection(v: PolicyVars): string {\n if (v.consentModel === 'none' || v.cookieCategories.length === 0) return '';\n return `\n## Cookie Categories\n\nOur consent controls group cookies into the following categories, which you can accept or decline${\n v.consentModel === 'opt-in'\n ? ' before any non-essential cookie is set'\n : ' at any time after your first visit'\n }:\n\n${bullets(v.cookieCategories)}\n`;\n}\n","/**\n * Privacy policy — Canada (PIPEDA).\n *\n * Ported from the pandoc prototype at `packages/core/legal-templates/`. Two\n * things changed in the port and both are load-bearing:\n *\n * 1. `${var}` is now real TypeScript interpolation rather than a pandoc Lua\n * filter, so an unresolved variable is a compile error. The filter left\n * unknown keys as the literal text `${key}` — which would ship a live\n * privacy policy containing `${countries}`.\n * 2. Lists are built from arrays, not by splicing a string into a fixed bullet.\n * An empty derived value used to produce a stray `- ; and` bullet.\n *\n * The prose is jurisdiction-specific: it names the Office of the Privacy\n * Commissioner of Canada and frames transfers as \"outside of Canada\". Do not\n * reuse it for another jurisdiction — add a sibling template instead.\n */\nimport type { PolicyVars } from '../derive.ts';\nimport { bullets, REVIEW_NOTICE, updatedLine } from './shared.ts';\n\nexport function privacyCa(v: PolicyVars): string {\n return `# Privacy Policy\n${updatedLine(v)}\n${REVIEW_NOTICE}\n\nThis is the privacy policy of ${v.businessName} (\"Business\"). It summarizes what personal information we collect and how we use and disclose this information.\n\nBy using our website (the \"Site\"), you signify your consent to the terms of our Privacy Policy. If you do not agree with any terms of this Privacy Policy, please do not use this Site or submit any personal information to us, or use the preference tools we provide to adjust your settings. This Privacy Policy also describes certain choices you have on how we use your personal information.\n\nWe reserve the right to modify this Privacy Policy at any time. We will reflect any such modifications to this Privacy Policy on our Site. We suggest that you periodically consult this Privacy Policy. Your continued use of the Site after any such changes constitutes your acceptance of this Privacy Policy, as revised.\n\n**Privacy Policy Summary.**\n\n${bullets([\n 'What Personal Information We Collect',\n 'How We Use Personal Information',\n 'How We Share Personal Information',\n 'Your Choices',\n])}\n\n## Full Privacy Policy\n\n### What Personal Information We Collect and How We Collect It\n\nPersonal information is information about an identifiable individual. We collect personal information only for purposes that a reasonable person would consider appropriate in the circumstances and only with your knowledge and consent, except where otherwise required or permitted by law. Business collects personal information when you voluntarily provide it through our Site or when you provide it to us through other means. For example, we may collect personal information when you:\n\n${bullets(v.collectionReasons)}\n\nThe personal information we may collect will depend on the service you request and may include:\n\n${bullets(v.piiCollected)}\n\n### How Business Collects Information Through Technological Means\n\nWhen you visit our Site, we may collect information that is automatically sent to us by your web browser. This information may include:\n\n${bullets(v.techInfo)}\n\nWe use this information to:\n\n${bullets(v.techInfoPurposes)}\n\nThe amount of information that is sent by your web browser depends on the browser and settings you use. Please refer to the instructions provided by your browser if you want to learn more about what information it sends to websites you visit or how you may change or restrict this.\n\nBusiness may use cookies and other similar devices on this Site to enhance functionality. These devices may track information which includes:\n\n${bullets(v.cookieTracked)}\n\nWe use this information to:\n\n${bullets(v.cookiePurposes)}\n\nIf you wish to disable cookies, refer to your browser help menu to learn how.${v.cookieTool ? ` ${v.cookieTool}` : ''}\n\n### How Business Uses and Discloses Personal Information\n\nThe personal information we collect may be used by Business for the purposes for which it was collected, as provided in this Privacy Policy, or for other purposes that are disclosed to you and to which you consent.\n\nFor example, we may use your personal information to:\n\n${bullets(v.usePurposes)}\n\n${providersSection(v)}\n\nBusiness reserves the right to transfer personal information in the event that we merge with or are acquired by a third party. We also may disclose your personal information for any other purpose required or permitted by law or to which you consent.\n\n### Your Choices\n\n${bullets(v.optOutOptions)}\n\n### How We Protect Personal Information\n\nThe security of your personal information is important to us. We protect your personal information in our control through appropriate security safeguards against loss, theft, unauthorized access, disclosure, copying, use or modification. These safeguards include physical measures (such as locked filing cabinets), organizational measures (such as employee training and restricted access), and technological measures (such as encryption and passwords). Personal information may be accessed by persons within our organization who require such access to carry out the purposes described in this Privacy Policy, or such other purposes as permitted or required by law. Personal information we collect is maintained with the source of the information at ${v.url}.\n\nWe retain personal information that we collect only as long as necessary for the purposes for which it was collected or to meet legal requirements. We destroy personal information when it is no longer needed for such purposes.${v.retention ? ` In general, we keep personal information for ${v.retention}.` : ''}\n\nIt is important to understand that no security measures are absolute. We cannot guarantee the safety of any information you provide to us.\n${transferSection(v)}\n### Accessing and Correcting Your Personal Information\n\nYou have a right to access your personal information and to request a correction to it if you believe it is inaccurate. If you have submitted personal information and would like to have access to it, or if you would like to have it corrected, please contact us using the contact information provided below. We may require you verify your identity before allowing you to access your personal information.\n\n### How to Contact Us\n\nIf you have any questions regarding this Privacy Policy, to submit a complaint, or to access or correct your information, please contact our Privacy Officer at ${v.mailingAddress}. If you are not satisfied with our response to your privacy concerns, you may contact the Office of the Privacy Commissioner of Canada at www.priv.gc.ca or 1-800-282-1376.\n`;\n}\n\n/**\n * Named separately because a site with no third parties at all should not claim\n * to have service providers, and one with them owes the reader their identity —\n * \"we may share with service providers\" without naming them is the vaguest and\n * least useful sentence a policy can contain.\n */\nfunction providersSection(v: PolicyVars): string {\n if (v.processors.length === 0)\n return 'We do not transfer personal information to third party service providers.';\n return `We may transfer personal information to third party service providers that assist us with carrying out these purposes. When we transfer personal information to service providers, we require them to protect the information in a manner consistent with our privacy practices and applicable privacy laws. These service providers are:\n\n${bullets(\n v.processors.map(\n (p) => `${p.name}, for ${p.purpose}${p.privacyUrl ? ` (privacy policy: ${p.privacyUrl})` : ''}`,\n ),\n)}\n\nWe remain responsible for personal information in the possession of our service providers.`;\n}\n\n/** Omitted entirely when nothing leaves the country — a false claim otherwise. */\nfunction transferSection(v: PolicyVars): string {\n if (!v.countries) return '';\n return `\n### We May Transfer Personal Information to Other Countries\n\nSome or all of the personal information we collect may be stored or processed in jurisdictions outside of Canada, including ${v.countries}. As a result, this information may be subject to access requests from governments, courts or law enforcement in those jurisdictions according to laws in those jurisdictions.\n`;\n}\n","/**\n * Terms of service — Canada.\n *\n * Unlike the privacy policy, this has no prototype in the repo to port: the\n * prose is new. It is written as **generic website terms** — the clauses almost\n * every informational site needs (acceptable use, intellectual property,\n * disclaimer, limitation of liability, governing law) and nothing more.\n *\n * It deliberately does NOT cover the things that actually vary between\n * businesses and carry the most risk: sales and refunds, subscriptions and\n * renewals, user-generated content and its moderation, accounts and\n * termination, professional advice, or anything sector-regulated. A site doing\n * any of those needs clauses drafted for it — the review banner says so, and\n * this file should not grow them, because a template that half-covers payments\n * is more dangerous than one that visibly omits them.\n */\nimport type { PolicyVars } from '../derive.ts';\nimport { bullets, REVIEW_NOTICE, updatedLine } from './shared.ts';\n\nexport function termsCa(v: PolicyVars): string {\n return `# Terms of Service\n${updatedLine(v)}\n${REVIEW_NOTICE}\n\nThese terms govern your use of ${v.url} (the \"Site\"), operated by ${v.businessName} (\"we\", \"us\"). By accessing or using the Site, you agree to these terms. If you do not agree to them, please do not use the Site.\n\nWe may change these terms from time to time. The version published on the Site is the one that applies, and your continued use of the Site after a change means you accept the revised terms.\n\n## Use of the Site\n\nYou may use the Site for lawful purposes only. You agree not to:\n\n${bullets([\n 'use the Site in any way that breaches any applicable law or regulation',\n 'attempt to gain unauthorized access to the Site, its servers, or any connected system',\n 'interfere with or disrupt the operation of the Site, including by introducing malicious code',\n 'collect or harvest information about other users of the Site',\n 'reproduce, duplicate, or resell any part of the Site except as these terms permit',\n])}\n\nWe may suspend or withdraw access to the Site, in whole or in part, at any time and without notice.\n\n## Intellectual Property\n\nUnless stated otherwise, the content of the Site — including text, graphics, logos, and layout — is owned by or licensed to us and is protected by copyright and other intellectual property laws. You may view, download, and print content from the Site for your own personal, non-commercial use. Any other use requires our prior written permission.\n\n## Accuracy of Information\n\nWe take reasonable care to keep the Site accurate and current, but we make no representation or warranty that the content is complete, accurate, or up to date. Content on the Site is provided for general information only and should not be relied on as advice for your particular circumstances.\n\n## Third Party Links and Services\n\nThe Site may link to, or rely on, websites and services operated by others. We do not control those sites and services and are not responsible for their content, availability, or practices. A link is not an endorsement.\n\n## Disclaimer\n\n**The Site is provided \"as is\" and \"as available\", without warranty of any kind, whether express or implied.** To the fullest extent permitted by law, we disclaim all warranties, including implied warranties of merchantability, fitness for a particular purpose, and non-infringement. We do not warrant that the Site will be uninterrupted, secure, or error free.\n\n## Limitation of Liability\n\n**To the fullest extent permitted by law, we will not be liable for any indirect, incidental, special, consequential, or punitive damages, or for any loss of profits, revenue, data, or goodwill, arising out of or in connection with your use of the Site** — whether the claim is based in contract, tort, or any other legal theory, and whether or not we were advised of the possibility of such damages.\n\nNothing in these terms excludes or limits liability that cannot be excluded or limited under applicable law.\n\n## Privacy\n\nOur handling of personal information is described in our Privacy Policy, which forms part of these terms.\n\n## Governing Law\n\nThese terms are governed by the laws of ${governingLaw(v)}. You agree to the exclusive jurisdiction of the courts of that jurisdiction for any dispute arising out of or in connection with these terms or the Site.\n\n## Contact\n\nIf you have questions about these terms, please contact us at ${v.mailingAddress}.\n`;\n}\n\n/**\n * Canadian law is split between the provinces and the federal Parliament, so the\n * conventional clause names both. Without a province we can only name the\n * country — better a broader clause than one asserting a province we guessed.\n */\nfunction governingLaw(v: PolicyVars): string {\n if (v.governingLaw) return v.governingLaw;\n return v.governingProvince\n ? `${v.governingProvince} and the federal laws of ${v.governingCountry} applicable therein`\n : v.governingCountry;\n}\n","/**\n * The jurisdiction registry.\n *\n * Adding a jurisdiction is: author the three templates, add one key here, add\n * one member to `JURISDICTIONS` in `site.ts`. The `satisfies` below makes the\n * second and third steps a compile error if you skip either — a config could\n * otherwise name a jurisdiction with no templates behind it and silently render\n * against the wrong body of law.\n *\n * Every jurisdiction owes all three documents. A partial set would mean\n * `legal.termsOfService.enabled` silently emitting nothing.\n */\nimport type { Jurisdiction } from '../../site.ts';\nimport type { PolicyVars } from '../derive.ts';\nimport { cookiesCa } from './cookies.ca.ts';\nimport { privacyCa } from './privacy.ca.ts';\nimport { termsCa } from './terms.ca.ts';\n\nexport type LegalDoc = 'privacy' | 'terms' | 'cookies';\n\nexport type DocSet = Record<LegalDoc, (v: PolicyVars) => string>;\n\nexport const TEMPLATES = {\n ca: { privacy: privacyCa, terms: termsCa, cookies: cookiesCa },\n} satisfies Record<Jurisdiction, DocSet>;\n\n/** Stable output order, independent of which docs a given config enables. */\nexport const DOC_ORDER: LegalDoc[] = ['privacy', 'terms', 'cookies'];\n\n/** Output filename stem per document — also the Bricks shortcode's allowlist. */\nexport const DOC_SLUGS: Record<LegalDoc, string> = {\n privacy: 'privacy-policy',\n terms: 'terms-of-service',\n cookies: 'cookie-notice',\n};\n","/**\n * Generate a site's legal documents from its config.\n *\n * Shaped after `generateDocs` rather than after a `generate()` format, and the\n * reason is structural: `generate()` is keyed to a **`DesignSystem`**, while a\n * privacy policy renders from a **`SiteConfig`**. Bolting it on as a `Format`\n * would mean a format that ignores its own input. So this is a sibling public\n * function that returns a `{ relPath: content }` map and lets each caller write\n * it where it belongs — the CLI to stdout or a directory, the bricks build into\n * `dist/legal/`, the Astro integration into a content collection.\n *\n * Pure: no filesystem, no clock, no shared state.\n */\nimport { derivePolicyVars, type PolicyVars } from './derive.ts';\nimport { parseMarkdown, toContentNodes, toHtmlFragment, toPortableText } from './render.ts';\nimport { DOC_ORDER, DOC_SLUGS, TEMPLATES, type LegalDoc } from './templates/index.ts';\nimport type { SiteConfig } from '../site.ts';\nimport type { ContentNode } from '@getvitops/utils';\n\nexport type LegalOutput = 'md' | 'html' | 'portable-text';\n\nexport interface GenerateLegalOptions {\n /** Which documents to render. Defaults to those enabled in the config. */\n docs?: LegalDoc[];\n /** Output format. Default `md`. */\n output?: LegalOutput;\n}\n\nconst EXT: Record<LegalOutput, string> = {\n md: 'md',\n html: 'html',\n 'portable-text': 'json',\n};\n\n/** Which documents the config asks for, in a stable order. */\nexport function enabledDocs(site: SiteConfig): LegalDoc[] {\n const legal = site.legal;\n const on: Record<LegalDoc, boolean> = {\n privacy: !!legal?.privacyPolicy?.enabled,\n terms: !!legal?.termsOfService?.enabled,\n cookies: !!legal?.cookieConsent?.enabled,\n };\n return DOC_ORDER.filter((d) => on[d]);\n}\n\n/** Render one document to markdown. The other outputs derive from this. */\nexport function renderMarkdown(site: SiteConfig, doc: LegalDoc, vars?: PolicyVars): string {\n const jurisdiction = site.legal?.jurisdiction ?? 'ca';\n // `validateSite` rejects an unregistered jurisdiction, so this is a guard for\n // callers that skipped validation rather than an expected path.\n const set = TEMPLATES[jurisdiction];\n if (!set) throw new Error(`no legal templates for jurisdiction \"${jurisdiction}\"`);\n return set[doc](vars ?? derivePolicyVars(site));\n}\n\n/**\n * Render one document as a `ContentNode` tree — the framework-agnostic shape the\n * site config already uses for `templates` of type `nodes`, so an Astro consumer\n * can hand it to `NodeRenderer` instead of injecting a string of HTML.\n */\nexport function renderNodes(site: SiteConfig, doc: LegalDoc): ContentNode[] {\n return toContentNodes(parseMarkdown(renderMarkdown(site, doc)));\n}\n\n/**\n * Every enabled legal document, keyed by output path.\n *\n * Documents are keyed by filename (`privacy-policy.md`) rather than by document\n * id so a caller can write the map verbatim.\n */\nexport function generateLegal(\n site: SiteConfig,\n opts: GenerateLegalOptions = {},\n): Record<string, string> {\n const output = opts.output ?? 'md';\n const docs = opts.docs ?? enabledDocs(site);\n // Derived once: every document asserts the same facts, and re-deriving per\n // document would let them disagree if the derivation ever stopped being pure.\n const vars = derivePolicyVars(site);\n\n const out: Record<string, string> = {};\n for (const doc of docs) {\n const md = renderMarkdown(site, doc, vars);\n const slug = DOC_SLUGS[doc];\n const content =\n output === 'md'\n ? md\n : output === 'html'\n ? toHtmlFragment(parseMarkdown(md))\n : JSON.stringify(toPortableText(parseMarkdown(md), slug), null, 2) + '\\n';\n out[`${slug}.${EXT[output]}`] = content;\n }\n return out;\n}\n\nexport { derivePolicyVars, type PolicyVars } from './derive.ts';\nexport { detectProcessorKeys, KNOWN_PROCESSORS, resolveProcessors } from './providers.ts';\nexport type { KnownProcessorKey, Processor } from './providers.ts';\nexport { parseMarkdown, toContentNodes, toHtmlFragment, toPortableText } from './render.ts';\nexport type { Block, Span } from './render.ts';\nexport { DOC_ORDER, DOC_SLUGS, TEMPLATES } from './templates/index.ts';\nexport type { DocSet, LegalDoc } from './templates/index.ts';\n","/**\n * Build an SVG sprite from an icon `include` map.\n *\n * This is the delivery path for consumers that cannot run an icon integration:\n * Bricks/WordPress, EmDash's renderers, anything rendering HTML outside an Astro\n * build. Markup is `<svg><use href=\"…/icons.svg#ph--caret-down\"/></svg>` — no\n * runtime JS and no network call, which is what keeps it inside the tier rules\n * (a runtime-fetching element would be behaviour JS with no fallback to enhance).\n *\n * The icon DATA comes from the `@iconify-json/*` collections, which stay optional\n * peers loaded dynamically: `@iconify-json/ph` alone is ~4.5 MB and the semantic\n * map spans five sets, so depending on them directly would be indefensible for\n * every consumer who never asks for a sprite.\n */\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { IconifyJSON } from '@iconify/types';\nimport { getIconData, iconToSVG, replaceIDs } from '@iconify/utils';\n\nexport interface IconSpriteOptions {\n /** Exactly `generateIconInclude()`'s shape: collection → icon names. */\n include: Record<string, string[]>;\n /**\n * Extra ids pointing at an already-included icon, e.g. `{ 'icon-menu': 'ph:list' }`,\n * so a consumer can reference a semantic name without knowing the set.\n */\n aliases?: Record<string, string>;\n /**\n * Directory to resolve `@iconify-json/*` from. Defaults to `process.cwd()`.\n *\n * Load-bearing: the collections are the CONSUMER's dependency, not this\n * package's, so a bare `import('@iconify-json/ph/…')` from inside the\n * generator resolves against the generator's own node_modules and misses them\n * entirely — which reads as \"not installed\" on a project that has them.\n */\n resolveFrom?: string;\n /** Injected in tests so the emitter can run without any @iconify-json/* installed. */\n loadSet?: (prefix: string) => Promise<IconifyJSON | null>;\n}\n\nexport interface IconSpriteResult {\n svg: string;\n /** Every `<symbol>` id emitted, in order. */\n ids: string[];\n /** `prefix:name` entries that were asked for but not found. */\n missing: string[];\n}\n\n/**\n * `ph:caret-down` → `ph--caret-down`.\n *\n * The one place this grammar lives. `Icon.astro` mirrors it and `icon.test.ts`\n * guards the pair, because a drift here resolves `<use>` to nothing and renders\n * as an empty box rather than an error.\n */\nexport function spriteId(qualified: string): string {\n return qualified.replace(':', '--');\n}\n\n/**\n * Default loader: the collection JSON shipped by `@iconify-json/<prefix>`.\n *\n * Resolved through a `createRequire` rooted at the consumer's directory, then\n * imported by absolute path — a bare specifier would resolve against this\n * package instead, where the collections deliberately aren't installed.\n */\nasync function loadCollection(prefix: string, from: string): Promise<IconifyJSON | null> {\n try {\n const req = createRequire(pathToFileURL(join(from, 'noop.js')));\n const path = req.resolve(`@iconify-json/${prefix}/icons.json`);\n const mod = await import(pathToFileURL(path).href, { with: { type: 'json' } });\n return (mod.default ?? mod) as IconifyJSON;\n } catch {\n return null;\n }\n}\n\nexport async function buildIconSprite(o: IconSpriteOptions): Promise<IconSpriteResult> {\n const from = o.resolveFrom ?? process.cwd();\n const load = o.loadSet ?? ((prefix: string) => loadCollection(prefix, from));\n const symbols: string[] = [];\n const ids: string[] = [];\n const missing: string[] = [];\n /** qualified name → its rendered body+viewBox, so an alias can reuse it. */\n const rendered = new Map<string, { viewBox: string; body: string }>();\n\n for (const [prefix, names] of Object.entries(o.include)) {\n if (!names?.length) continue;\n const set = await load(prefix);\n if (!set) {\n throw new Error(\n `[vitops icons] Cannot build the sprite: the \"${prefix}\" icon set is not installed. ` +\n `Run \\`pnpm add -D @iconify-json/${prefix}\\`, or drop it from your icons config.`,\n );\n }\n for (const name of names) {\n // getIconData resolves aliases and parent chains, so `include` can name\n // either a real icon or one of the set's own aliases.\n const data = getIconData(set, name);\n if (!data) {\n missing.push(`${prefix}:${name}`);\n continue;\n }\n const built = iconToSVG(data, { height: 'none' });\n // MANDATORY. Two icons carrying the same internal gradient/clip id would\n // otherwise collide once concatenated into one document, and the second\n // silently renders with the first's paint.\n const body = replaceIDs(built.body);\n const id = spriteId(`${prefix}:${name}`);\n rendered.set(`${prefix}:${name}`, { viewBox: built.attributes.viewBox, body });\n ids.push(id);\n symbols.push(`<symbol id=\"${id}\" viewBox=\"${built.attributes.viewBox}\">${body}</symbol>`);\n }\n }\n\n for (const [alias, target] of Object.entries(o.aliases ?? {})) {\n const hit = rendered.get(target);\n if (!hit) {\n missing.push(`${target} (aliased as ${alias})`);\n continue;\n }\n // The body is DUPLICATED rather than nested as <use href=\"#target\"> inside\n // the symbol. Nested-use is legal but unreliable precisely under an\n // external-file <use>, which is exactly how this sprite is consumed; a\n // handful of duplicated paths in a ~40 KB file is the cheaper trade.\n ids.push(alias);\n symbols.push(`<symbol id=\"${alias}\" viewBox=\"${hit.viewBox}\">${hit.body}</symbol>`);\n }\n\n const svg =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" style=\"display:none\" aria-hidden=\"true\">` +\n symbols.join('') +\n `</svg>\\n`;\n\n return { svg, ids, missing };\n}\n\n/**\n * One icon's renderable parts, for inlining into markup.\n *\n * Exists because `<Icon />` cannot go through astro-icon: its `./components`\n * entry is a TypeScript file that Vite must transform, so it can only be\n * reached by a statically-analysable import — and a static import is exactly\n * what made the optional peer mandatory for anyone rendering Popover, Details\n * or Drawer. Reading the collection directly sidesteps the peer entirely and\n * shares this file's loader with the sprite, so both paths draw the same glyph.\n */\nexport async function loadIconSvg(\n qualified: string,\n opts?: { resolveFrom?: string; loadSet?: (prefix: string) => Promise<IconifyJSON | null> },\n): Promise<{ viewBox: string; body: string } | null> {\n const i = qualified.indexOf(':');\n if (i <= 0) return null;\n const prefix = qualified.slice(0, i);\n const name = qualified.slice(i + 1);\n const from = opts?.resolveFrom ?? process.cwd();\n const load = opts?.loadSet ?? ((p: string) => loadCollection(p, from));\n const set = await load(prefix);\n if (!set) return null;\n const data = getIconData(set, name);\n if (!data) return null;\n const built = iconToSVG(data, { height: 'none' });\n // Same id-collision guard as the sprite: several inlined icons share one\n // document, so an un-rewritten gradient id would cross-render.\n return { viewBox: built.attributes.viewBox, body: replaceIDs(built.body) };\n}\n","/**\n * Pure, parameterized port of the Vitops design-system generator.\n *\n * `generate({ input, format, outDir })` reads a consumer's `design-system.json`,\n * validates it, and emits consumer-ready output for the chosen format into\n * `outDir`. Unlike the original CWD-bound script it mutates no shared state: every\n * generated token layer is built in memory and either bundled (css/bricks) or\n * inlined (tailwind) before writing.\n *\n * Framework-static assets (the hand-written CSS partials, the Bricks PHP + loader,\n * and the pre-built JS bundles) live under `assets/` in this package and are read /\n * copied from there — they are the same for every consumer.\n */\nimport { readFileSync, writeFileSync, mkdirSync, cpSync, existsSync, readdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createHash } from 'node:crypto';\nimport { transform } from 'lightningcss';\nimport { validate, type DesignSystem } from './schema.ts';\nimport { generateDocs } from './docs.ts';\nimport { emitDesignMd } from './design-md.ts';\nimport { generateLegal } from './legal/index.ts';\nimport { buildIconSprite } from './icons-sprite.ts';\nimport { resolveInput, resolveSiteConfig, type SiteConfig } from './site.ts';\nimport { generateIconInclude, resolveIcon } from '@getvitops/utils';\nimport {\n BASE_HOOK,\n DARK_SEL,\n SYSTEM_DARK_SEL,\n TW_CLASH,\n type RoleSpec,\n roleHue,\n roleKind,\n} from './shared.ts';\nimport {\n checkContrast,\n expandPalette,\n functionalRole,\n ladderWarnings,\n monotonicityErrors,\n NUMERIC_STEPS,\n tokenClass,\n tokenVar,\n type ExpandedHue,\n type FunctionalRole,\n} from './tokens.ts';\n\nexport type Format = 'bricks' | 'css' | 'tailwind' | 'design';\n\n/**\n * Formats that emit a stylesheet. `design` is the odd one out — it emits a\n * single `DESIGN.md` brief and no CSS at all — so anything that expects to\n * import the generator's output (the Vite plugin's injected stylesheet, the\n * Astro integration) types against this narrower set.\n */\nexport type StylesheetFormat = Exclude<Format, 'design'>;\n\nexport interface GenerateOptions {\n /**\n * The config to build from — a path, or an already-parsed object.\n *\n * **Either kind is accepted.** A bare `design-system.json`, or the larger\n * `SiteConfig` that embeds one (commonly `company.json` / `site.json`), in\n * which case the design system is `designSystem.themes[theme]` with its\n * `extends` chain resolved. The two are told apart by shape, not by filename —\n * see `isSiteConfig`.\n *\n * Passing a site config here also supplies `site`, so the site-level facts\n * generation depends on (`designSystem.defaultColorScheme`, the legal\n * documents, the icon sprite) don't need the same path declared twice. Each of\n * those is still gated on a field in that config, so nothing new appears\n * unless the config asks for it.\n */\n input: string | DesignSystem | SiteConfig;\n /** Output target. Default: 'bricks'. */\n format?: Format;\n /** Directory to write outputs into. Default: 'dist'. */\n outDir?: string;\n /** Override the framework asset root (advanced/testing). */\n assetsDir?: string;\n /**\n * Which `designSystem.themes` entry to build. Default: the config's\n * `defaultTheme`, else `default`. An error on a bare `design-system.json`,\n * which holds one design system and no themes map.\n */\n theme?: string;\n /**\n * Environment whose A/B variant applies to the site config, wherever it came\n * from (`input` or `site`). Default: `'production'`.\n */\n siteEnv?: string;\n /**\n * The site config, when it is a *different* file from `input` — enabling\n * legal-document output into `<outDir>/legal/*.html` and supplying\n * `designSystem.defaultColorScheme`.\n *\n * Redundant when `input` is already a site config; set both and this one wins.\n */\n site?: string | SiteConfig;\n /**\n * Emit the `prefers-color-scheme: dark` block (see `BuildOptions`).\n *\n * Normally this comes from the site config's `designSystem.defaultColorScheme: \"system\"`, which\n * is where the fact belongs. This is the escape hatch for consumers with a\n * `design-system.json` and no site config at all: requiring a whole\n * `SiteConfig` — which must carry a full `designSystem` — to set one boolean\n * would be out of proportion. Set explicitly, it wins over the site config.\n */\n systemColorScheme?: boolean;\n}\n\nexport interface GenerateResult {\n format: Format;\n outDir: string;\n written: string[];\n}\n\nconst HERE = dirname(fileURLToPath(import.meta.url));\nconst DEFAULT_ASSETS = join(HERE, '..', 'assets');\n\n// ── colour machinery ─────────────────────────────────────────────────────────\n// Every hue is an 11-step numeric OKLCH scale on a shared lightness ladder (see\n// tokens.ts); every role resolves to `--color-<target>-<role>[-<variant>]`.\n// Dark mode re-points which step each token reads; the solid family is stable.\nconst UTILITY_PROPS: Record<string, string> = {\n bg: 'background-color',\n text: 'color',\n icon: 'color',\n border: 'border-color',\n outline: 'outline-color',\n fill: 'fill',\n stroke: 'stroke',\n};\n\n/**\n * Which token target a utility family draws from. Four families have tokens of\n * their own; the other three are aliases, because an SVG fill wants the icon\n * tier (3:1, may run vivid) and an outline wants the border tier — minting\n * separate tokens for them would be three more things to keep in contrast.\n */\nconst UTILITY_SOURCE: Record<string, string> = {\n bg: 'bg',\n text: 'text',\n icon: 'icon',\n border: 'border',\n outline: 'border',\n fill: 'icon',\n stroke: 'icon',\n};\n\n/** The target segment of a token key (`bg-solid-bold` → `bg`). */\nconst targetOf = (key: string): string => {\n const i = key.indexOf('-');\n return i === -1 ? key : key.slice(0, i);\n};\n\nexport interface ColorUtility {\n /** Class name, without the leading dot. */\n cls: string;\n /** CSS property the class sets. */\n prop: string;\n /** `var(--…)` reference the class resolves to. */\n value: string;\n}\n\n/**\n * The framework's container breakpoints. `sm-`/`md-`/`lg-`/`xl-` prefixes in the\n * css/bricks formats; `@sm:`/`@md:`/… in tailwind, where they are registered as\n * `--container-*` in `@theme` and Tailwind expands the variants itself.\n */\nexport const BREAKPOINTS: readonly (readonly [string, string])[] = [\n ['sm', '30rem'],\n ['md', '48rem'],\n ['lg', '64rem'],\n ['xl', '80rem'],\n] as const;\n\n/**\n * Gap utilities over the space scale, emitted from one list into all three\n * formats — same arrangement as `roleColorUtilities`, for the same reason.\n *\n * These did not exist. `vitops docs css` advertised a `g` class that was never\n * emitted, so the honest answer for a css/bricks consumer was an inline\n * `style=\"gap: …\"`, which is what this repo's own `index.html` does throughout.\n * Tailwind does not fill the hole either: the fluid space steps are deliberately\n * kept OUT of Tailwind's `--spacing-*` namespace (named keys there shadow the\n * size scales — `max-w-7xl` would resolve to `var(--spacing-7xl)`), so `gap-md`\n * is not something Tailwind can derive on its own. Measured against\n * tailwindcss@4.3.3: an explicit `@utility gap-md` is honoured, coexists with\n * the built-in numeric `gap-4`, and picks up variants (`@md:gap-md`).\n *\n * The whole matrix is emitted rather than a useful-looking subset: an undefined\n * step produces no rule and no error in either format, so a missing\n * `md-gap-x-2xl` would be indistinguishable from a working one.\n */\nexport function gapUtilities(steps: { name: string }[]): ColorUtility[] {\n const FAMILIES: [string, string][] = [\n ['gap', 'gap'],\n ['gap-x', 'column-gap'],\n ['gap-y', 'row-gap'],\n ];\n return steps.flatMap(({ name }) =>\n FAMILIES.map(([prefix, prop]) => ({\n cls: `${prefix}-${name}`,\n prop,\n value: `var(--space-${name})`,\n })),\n );\n}\n\n/**\n * Every role colour utility, each class name emitted EXACTLY once.\n *\n * There is now a single axis. The target lives *inside* the token name, so\n * `bg-danger-muted` and `text-danger-muted` are different tokens and the\n * collision the old plane/stop precedence rule existed to arbitrate cannot\n * arise. Both the css/bricks and tailwind paths render from this one list, which\n * is what keeps the three formats in step; `format-parity.test.ts` holds them\n * there.\n *\n * The class name IS the token name minus `--color-`, so there is no separate\n * naming rule to drift — see `tokenClass` in tokens.ts.\n */\nexport function roleColorUtilities(\n roles: readonly FunctionalRole[],\n utilities: readonly string[],\n): ColorUtility[] {\n const out: ColorUtility[] = [];\n for (const fr of roles) {\n for (const fam of utilities) {\n const source = UTILITY_SOURCE[fam];\n if (source == null) continue;\n for (const key of Object.keys(fr.light)) {\n if (targetOf(key) !== source) continue;\n const canonical = tokenClass(fr.role, key);\n // Alias families keep the token but rename the leading segment:\n // `border-danger-bold` → `outline-danger-bold`.\n const cls = fam === source ? canonical : fam + canonical.slice(source.length);\n out.push({\n cls,\n prop: UTILITY_PROPS[fam] as string,\n value: `var(${tokenVar(fr.role, key)})`,\n });\n }\n }\n }\n return out;\n}\n\n/** Render the shared set as plain rules (css/bricks formats). */\nconst colorUtilityRules = (u: ColorUtility[]): string =>\n u.map(({ cls, prop, value }) => `.${cls} { ${prop}: ${value}; }`).join('\\n');\n\nconst decls = (obj: Record<string, string>, indent = ' ') =>\n Object.entries(obj)\n .map(([k, v]) => `${indent}${k}: ${v};`)\n .join('\\n');\n\n// ── fluid modular scale ───────────────────────────────────────────────────────\ninterface ScaleConfig {\n base: string;\n ratio: number;\n steps?: number;\n names?: string[];\n baseStep?: number;\n baseline?: string;\n fluid?: { minVw: string; maxVw: string; minRatio: number };\n}\ninterface ScaleStep {\n name: string;\n value: string;\n max: string;\n offset: number;\n}\nconst round = (n: number) => Number(n.toFixed(4)).toString();\nconst rem = (v: string) => parseFloat(v);\nconst buildScale = (s: ScaleConfig): ScaleStep[] => {\n const names = s.names ?? Array.from({ length: s.steps ?? 0 }, (_, i) => String(i + 1));\n const base = rem(s.base);\n const baseStep = s.baseStep ?? Math.ceil(names.length / 2);\n const baselineIdx = s.baseline ? names.indexOf(s.baseline) : baseStep - 1;\n return names.map((name, i) => {\n const k = i - (baseStep - 1);\n const vMax = base * Math.pow(s.ratio, k);\n const max = `${round(vMax)}rem`;\n let value = max;\n if (s.fluid) {\n const { minVw, maxVw, minRatio } = s.fluid;\n const vMin = base * Math.pow(minRatio, k);\n const lo = Math.min(vMin, vMax);\n const hi = Math.max(vMin, vMax);\n if (lo !== hi) {\n const slope = (vMax - vMin) / (rem(maxVw) - rem(minVw));\n const intercept = vMin - slope * rem(minVw);\n const sign = slope < 0 ? '-' : '+';\n const pref = `calc(${round(intercept)}rem ${sign} ${round(Math.abs(slope * 100))}vw)`;\n value = `clamp(${round(lo)}rem, ${pref}, ${round(hi)}rem)`;\n }\n }\n return { name, value, max, offset: i - baselineIdx };\n });\n};\n\n// ── typography ─────────────────────────────────────────────────────────────────\ninterface TypographyRole {\n family?: string;\n [key: string]: string | number | undefined;\n}\nconst TYPO_KEYMAP: Record<string, [string, string]> = {\n family: ['font-family', 'ff'],\n size: ['font-size', 'fs'],\n weight: ['font-weight', 'fw'],\n style: ['font-style', 'fst'],\n 'line-height': ['line-height', 'lh'],\n tracking: ['letter-spacing', 'ls'],\n 'text-decoration': ['text-decoration', 'td'],\n 'text-transform': ['text-transform', 'tt'],\n 'text-wrap': ['text-wrap', 'tw'],\n color: ['color', 'color'],\n};\n/**\n * Wrong spellings worth naming explicitly, because each is a plausible reading of\n * the key it isn't. `transform`/`decoration` were documented in the schema for a\n * while and shipped title-case navigation to production; `letter-spacing` and\n * `font-*` are the natural guesses for keys we chose to shorten.\n */\nconst ALSO_MEANT: Record<string, string> = {\n transform: 'text-transform',\n decoration: 'text-decoration',\n 'letter-spacing': 'tracking',\n wrap: 'text-wrap',\n 'font-family': 'family',\n 'font-size': 'size',\n 'font-weight': 'weight',\n 'font-style': 'style',\n lineHeight: 'line-height',\n};\nconst TYPO_IDENTITY: Record<string, string> = {\n 'font-style': 'normal',\n 'letter-spacing': 'normal',\n 'text-decoration': 'none',\n 'text-transform': 'none',\n 'text-wrap': 'wrap',\n};\n\n// ── animation state defaults ─────────────────────────────────────────────────\nconst STATE_DEFAULT: Record<string, string> = {\n opacity: '1',\n 'translate-x': '0',\n 'translate-y': '0',\n 'scale-x': '1',\n 'scale-y': '1',\n rotate: '0deg',\n blur: '0px',\n shadow: '0 0 0 transparent',\n brightness: '1',\n grayscale: '0',\n contrast: '1',\n saturate: '1',\n sepia: '0',\n 'hue-rotate': '0deg',\n clip: 'none',\n // The layout stage. `.transition` only declares `height` inside\n // `@supports (interpolate-size: allow-keywords)`, since `0 → auto` is not\n // interpolable without it — but the default belongs here either way, so the\n // flip resolves to the element's natural height rather than to nothing.\n height: 'auto',\n};\n\ninterface Pattern {\n group?: string;\n overrides?: Record<string, string>;\n element?: string;\n class?: string;\n fill?: boolean;\n default_role?: string;\n base?: Record<string, string>;\n states?: Record<string, Record<string, unknown>>;\n roles?: string[];\n}\n\nconst id = (key: string) => createHash('sha256').update(key).digest('hex').slice(0, 6);\n\n/**\n * The in-memory output of building a design system. String fields are CSS/JSON\n * ready to write; the generated CSS partials feed the css/bricks bundler.\n */\ninterface Built {\n generated: Record<string, string>; // filename (under generated/) -> css\n bricksColorsNamed: string;\n bricksColorsSemantic: string;\n bricksVariables: string;\n tokensJson: string;\n designManifest: string;\n tailwind: string;\n designMd: string;\n // captured for the tailwind bundler\n twTypeTokensCss: string;\n twPatternTokensCss: string;\n patternsCss: string;\n}\n\n// Exported for tests only — deliberately NOT re-exported from index.ts, so the\n// package's public API stays `generate` / `generateDocs` / `validate`.\nexport interface BuildOptions {\n /**\n * Also flip to dark when the OS asks and no explicit choice has been made —\n * `@media (prefers-color-scheme: dark)`.\n *\n * A build flag rather than a `DesignSystem` field: it describes what a *site*\n * wants, not what the system defines, so it comes from the site config's\n * `designSystem.defaultColorScheme` and `generate()` stays keyed to a `DesignSystem`.\n * Off by default, because turning it on flips a site dark for dark-OS users.\n */\n systemColorScheme?: boolean;\n}\n\nexport function build(\n ds: DesignSystem,\n format: Format,\n assetsDir: string,\n buildOpts: BuildOptions = {},\n): Built {\n const BRICKS = format === 'bricks';\n // Every hue expands to its 11-step numeric OKLCH scale; every role resolves\n // to functional tokens over its hue. Dark mode is the automatic flip.\n const expandedPalette = expandPalette(ds.colors.palette as Record<string, unknown>);\n const roleMap = ds.colors.roles as Record<string, RoleSpec>;\n const scaleRoles: FunctionalRole[] = [];\n for (const [role, spec] of Object.entries(roleMap)) {\n const hueName = roleHue(spec);\n const hue = expandedPalette[hueName];\n if (hue == null) throw new Error(`role \"${role}\" references unknown palette hue \"${hueName}\"`);\n scaleRoles.push(functionalRole(role, hueName, hue, roleKind(spec)));\n }\n const surfaceRole = scaleRoles.find((r) => r.role === 'surface');\n // The focus ring is role-less by default, so it needs one nominated source.\n // `ui-primary` is the interaction hue — a ring in the brand colour would drift\n // away from the buttons and links it appears on.\n const focusRole = scaleRoles.find((r) => r.role === 'ui-primary') ?? scaleRoles[0];\n\n // A pinned brand colour that sits off the shared lightness ladder is legal —\n // the author asked for that exact colour — but past ~0.03 L the hue reads\n // visibly heavier or lighter than its siblings at that step, so say so.\n for (const w of ladderWarnings(expandedPalette)) console.warn(`[vitops] ${w}`);\n\n // A pinned colour far enough off the ladder can leave the ramp non-monotonic —\n // some step lighter than the one above it. That is an error, not a warning:\n // `snap`, the mode-stable solid family and the dark tables all assume the\n // order, so an inverted ramp runs hover states backwards. Same reasoning as the\n // contrast contract below — this is exactly the drift the fixed ladder exists\n // to eliminate, and it is always author-caused, so it is always actionable.\n {\n const errors = monotonicityErrors(expandedPalette);\n if (errors.length) throw new Error(errors.join('\\n'));\n }\n\n // The contrast contract runs at BUILD time, not only in tests: a consumer\n // editing their own palette has no test suite, and an illegible pairing that\n // ships is far more expensive than a build that stops. Chromatic roles are\n // checked against the surface planes they actually sit on, since coloured text\n // appears over the page far more often than over its own tint.\n {\n const numericOf = (hueName: string) => expandedPalette[hueName]?.numeric ?? {};\n const resolve = (val: string): string => {\n const m = /^var\\(--color-([a-z0-9-]+)-(\\d+)\\)$/.exec(val);\n return m ? (numericOf(m[1] as string)[m[2] as never] ?? val) : val;\n };\n const planeKeys = ['bg', 'bg-muted', 'bg-x-muted'] as const;\n const surfaceBg = surfaceRole\n ? {\n light: planeKeys.flatMap((k) =>\n surfaceRole.light[k] ? [resolve(surfaceRole.light[k] as string)] : [],\n ),\n dark: planeKeys.flatMap((k) =>\n surfaceRole.dark[k] ? [resolve(surfaceRole.dark[k] as string)] : [],\n ),\n }\n : undefined;\n const failures = scaleRoles.flatMap((fr) => checkContrast(fr, numericOf, surfaceBg));\n if (failures.length)\n throw new Error(\n `colour contrast contract failed (${failures.length} pairing${\n failures.length === 1 ? '' : 's'\n }):\\n ${failures.join('\\n ')}`,\n );\n }\n const patterns = ds.patterns;\n const shadows = ds.shadows;\n const typography = ds.typography;\n const UTILITIES = (ds.colors.utilities ?? ['bg', 'text', 'icon', 'border']).filter(\n (u) => u in UTILITY_PROPS,\n );\n\n const generated: Record<string, string> = {};\n\n /**\n * The two background utilities that aren't derived from the palette, so\n * neither the generated scale nor Bricks' own palette import produces them.\n *\n * They exist to undo a pattern's fill — `class=\"card bg-transparent\"` for a\n * flat, border-only card. Tailwind ships both as built-ins, so the tailwind\n * format deliberately emits neither and defers, exactly as it does for the\n * `TW_CLASH` names.\n */\n const NON_PALETTE_BG =\n `/* Undo a pattern's fill (Tailwind provides these natively in that format). */\\n` +\n `.bg-transparent { background-color: transparent; }\\n` +\n `.bg-inherit { background-color: inherit; }\\n`;\n\n // ── color.css ──────────────────────────────────────────────────────────────\n if (BRICKS) {\n generated['color.css'] =\n '/* Colours provided by Bricks (palette import generates tokens + utilities). */\\n' +\n NON_PALETTE_BG;\n } else {\n let css = `/* GENERATED from design-system.json — do not edit by hand. */\\n:root {\\n`;\n css += ` color-scheme: light;\\n`;\n css += ` /* Hue scales (numeric steps, 50 = tinted near-white … 950 = tinted near-black) */\\n`;\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const [n, hex] of Object.entries(hue.numeric))\n css += ` --color-${name}-${n}: ${hex};\\n`;\n css += `\\n /* Role tokens (the public API) */\\n`;\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.light))\n css += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n if (focusRole) {\n css += `\\n /* Focus ring — a boundary, so it takes the solid tone, not a border tint. */\\n`;\n css += ` --color-border-focus: ${focusRole.light['bg-solid']};\\n`;\n }\n if (surfaceRole) {\n css += `\\n /* Translucent surface + scrim */\\n`;\n css += ` --surface-glass: color-mix(in oklch, var(--color-bg-surface) 72%, transparent);\\n`;\n css += ` --overlay: color-mix(in oklch, var(--color-${surfaceRole.hue}-950) 45%, transparent);\\n`;\n }\n css += `}\\n\\n`;\n // Dark appearance: the automatic functional flip (solid stays mode-stable).\n {\n let fb = '';\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.dark))\n if (fr.light[t] !== val) fb += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n if (surfaceRole)\n fb += ` --overlay: color-mix(in oklch, var(--color-${surfaceRole.hue}-950) 60%, transparent);\\n`;\n if (fb) {\n css += `/* Functional role tokens (dark) */\\n`;\n css += `${DARK_SEL} {\\n color-scheme: dark;\\n${fb}}\\n\\n`;\n // The same delta again, for \"no explicit choice + a dark OS\". Opt-in,\n // because switching it on flips a site dark for dark-OS users.\n //\n // This is what makes <color-scheme-toggle>'s \"System\" position mean\n // anything: System *removes* data-theme, so with only the block above it\n // fell through to light on every machine. It also gives a no-JS page the\n // OS appearance, which the toggle alone never could.\n //\n // Yes, `fb` is emitted twice. It is a delta — only the tokens whose dark\n // value differs, and the raw hue ramps never re-point — and two identical\n // runs of text compress to almost nothing, so the cost is far below what\n // a second full colour layer would suggest.\n if (buildOpts.systemColorScheme)\n css +=\n `/* Functional role tokens (dark) — OS preference, no explicit choice */\\n` +\n `@media (prefers-color-scheme: dark) {\\n` +\n ` ${SYSTEM_DARK_SEL} {\\n color-scheme: dark;\\n${fb.replace(/^ {2}/gm, ' ')} }\\n}\\n\\n`;\n }\n }\n // Raw hue steps, then the role set. One axis means every class here is\n // emitted exactly once by construction — no precedence rule, and no reliance\n // on the minifier dropping a shadowed rule.\n css += `/* Colour utilities — ${UTILITIES.join(', ')} */\\n`;\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const n of Object.keys(hue.numeric))\n css +=\n UTILITIES.map(\n (cls) => `.${cls}-${name}-${n} { ${UTILITY_PROPS[cls]}: var(--color-${name}-${n}); }`,\n ).join('\\n') + '\\n';\n css += `\\n/* Role utilities (the public API) */\\n`;\n css += `${colorUtilityRules(roleColorUtilities(scaleRoles, UTILITIES))}\\n`;\n if (surfaceRole)\n css += `.glass { background-color: var(--surface-glass); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }\\n`;\n css += NON_PALETTE_BG;\n generated['color.css'] = css;\n }\n\n // ── shadows.css ──────────────────────────────────────────────────────────────\n {\n const entries = Object.entries(shadows ?? {});\n let sh = `/* GENERATED drop-shadow tokens + utilities — do not edit by hand. */\\n`;\n if (entries.length) {\n sh += `:root {\\n`;\n for (const [name, value] of entries) sh += ` --shadow-${name}: ${value};\\n`;\n sh += `}\\n\\n`;\n for (const [name] of entries)\n sh += `.drop-shadow-${name} { filter: drop-shadow(var(--shadow-${name})); }\\n`;\n }\n generated['shadows.css'] = sh;\n }\n\n // ── scales ───────────────────────────────────────────────────────────────────\n const typeSteps = ds.typeScale ? buildScale(ds.typeScale as ScaleConfig) : [];\n const spaceSteps = ds.spaceScale ? buildScale(ds.spaceScale as ScaleConfig) : [];\n const textMax: Record<string, string> = Object.fromEntries(\n typeSteps.map((s) => [`text-${s.name}`, s.max]),\n );\n\n const typographyFamilies = typography?.families ?? {};\n\n // The recognised key set is closed (TYPO_KEYMAP), and an unrecognised key is\n // dropped rather than emitted — so a typo, or one of the plausible-but-wrong\n // short forms (`transform` for `text-transform`, `decoration` for\n // `text-decoration`), produces a role that looks configured and renders\n // unstyled. That is invisible in the output and survives review, so say it here\n // rather than leaving it to be noticed on a live page.\n {\n const known = new Set(Object.keys(TYPO_KEYMAP));\n for (const [role, spec] of Object.entries(typography?.roles ?? {}))\n for (const key of Object.keys(spec as TypographyRole)) {\n if (known.has(key)) continue;\n const near = ALSO_MEANT[key];\n console.warn(\n `[vitops] typography.roles.${role}: unknown key \"${key}\" — ignored` +\n (near ? `. Did you mean \"${near}\"?` : `. Recognised: ${[...known].join(', ')}.`),\n );\n }\n }\n const withScaleFallback = (v: string) =>\n v.replace(/var\\(\\s*(--text-[\\w-]+)\\s*\\)/g, (m, name) =>\n textMax[name.slice(2)] ? `var(${name}, ${textMax[name.slice(2)]})` : m,\n );\n const roleDecls = (role: string, spec: TypographyRole): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [key, [prop, sfx]] of Object.entries(TYPO_KEYMAP)) {\n const identity = TYPO_IDENTITY[prop];\n if (spec[key] == null && identity == null) continue;\n const raw =\n spec[key] == null\n ? (identity as string)\n : key === 'family'\n ? (typographyFamilies[spec.family as string] ?? String(spec.family))\n : key === 'size'\n ? withScaleFallback(String(spec[key]))\n : String(spec[key]);\n out[prop] = `var(--${role}-${sfx}, ${raw})`;\n }\n return out;\n };\n\n // ── type-tokens.css ──────────────────────────────────────────────────────────\n let twTypeTokensCss = '';\n if (BRICKS) {\n generated['type-tokens.css'] =\n '/* Fonts + type/space scales provided by Bricks (Font + Variables managers). */\\n';\n } else {\n const root: Record<string, string> = {};\n for (const [name, stack] of Object.entries(ds.fonts ?? {})) root[`--font-${name}`] = stack;\n for (const s of typeSteps) root[`--text-${s.name}`] = s.value;\n for (const s of spaceSteps) root[`--space-${s.name}`] = s.value;\n const css =\n `/* GENERATED font families + fluid type/space scales — do not edit by hand.\\n` +\n ` --font-* are STACKS ONLY; no @font-face is emitted here. Load webfonts with\\n` +\n ` Astro's fonts: config and point the token at the family's cssVariable. */\\n` +\n `:root {\\n${decls(root)}\\n}\\n`;\n twTypeTokensCss = css;\n generated['type-tokens.css'] = css;\n }\n\n // ── spacing.css (gap utilities) ──────────────────────────────────────────────\n // Emitted for css AND bricks: the `--space-*` tokens come from this file in the\n // css format and from Bricks' Variables import in the bricks format, but the\n // class names are ours either way — Bricks generates utility classes only for\n // the colour palette.\n {\n const gaps = gapUtilities(spaceSteps);\n let sp = `/* GENERATED gap utilities — do not edit by hand. */\\n`;\n if (gaps.length) {\n for (const { cls, prop, value } of gaps) sp += `.${cls} { ${prop}: ${value}; }\\n`;\n for (const [bp, width] of BREAKPOINTS) {\n sp += `\\n@container (min-width: ${width}) {\\n`;\n for (const { cls, prop, value } of gaps) sp += ` .${bp}-${cls} { ${prop}: ${value}; }\\n`;\n sp += `}\\n`;\n }\n }\n generated['spacing.css'] = sp;\n }\n\n // ── tokens.css (pattern token cascade) ───────────────────────────────────────\n let twPatternTokensCss = '';\n {\n const tDefaults = patterns?.defaults ?? {};\n const tRadii = patterns?.radii ?? {};\n const tGroups = patterns?.groups ?? {};\n const tZ = patterns?.z ?? {};\n const tItems = (patterns?.items ?? {}) as Record<string, Pattern>;\n const root: Record<string, string> = {};\n for (const [prop, val] of Object.entries(tDefaults)) root[`--${prop}-default`] = val;\n if (!BRICKS) for (const [name, val] of Object.entries(tRadii)) root[`--br-${name}`] = val;\n for (const [group, props] of Object.entries(tGroups))\n for (const [prop, val] of Object.entries(props)) root[`--${prop}-${group}`] = val;\n for (const [name, n] of Object.entries(tZ)) root[`--z-tier-${name}`] = String(n);\n const aliases: Record<string, string> = {};\n for (const [name, p] of Object.entries(tItems)) {\n if (!p.group) continue;\n for (const prop of Object.keys(tGroups[p.group] ?? {}))\n aliases[`--${prop}-${name}-group`] = `var(--${prop}-${p.group})`;\n for (const [prop, val] of Object.entries(p.overrides ?? {}))\n aliases[`--${prop}-${name}-group`] = val;\n }\n let tok = `/* GENERATED pattern token cascade — do not edit by hand. */\\n:root {\\n`;\n tok += decls(root) + '\\n';\n if (Object.keys(aliases).length) tok += '\\n' + decls(aliases) + '\\n';\n tok += `}\\n`;\n twPatternTokensCss = tok;\n generated['tokens.css'] = tok;\n }\n\n // ── typography.css (.font-* roles) ───────────────────────────────────────────\n {\n const roles = (typography?.roles ?? {}) as Record<string, TypographyRole>;\n const headings = typography?.headings ?? {};\n let typo = `/* GENERATED typography roles — do not edit by hand. */\\n`;\n for (const [role, spec] of Object.entries(roles))\n typo += `.font-${role} {\\n${decls(roleDecls(role, spec))}\\n}\\n`;\n for (const [tag, role] of Object.entries(headings))\n if (roles[role]) typo += `${tag} {\\n${decls(roleDecls(role, roles[role]))}\\n}\\n`;\n generated['typography.css'] = typo;\n }\n\n // ── patterns.css (component interaction patterns) ────────────────────────────\n // `sel` is a *builder* taking the state's pseudo, not a finished selector, and\n // that indirection is load-bearing rather than stylistic: an element pattern\n // has to place the pseudo INSIDE its `:where()`, because `:where()` zeroes the\n // element but a pseudo appended outside it still counts. `:where(a, .link):hover`\n // is 0-1-0 — the same weight as `.cta-brand-primary` — so the link pattern's\n // hover colour tied with every `<a class=\"cta\">` and won on source order,\n // turning a filled CTA's text dark mid-hover. `:where(a:hover, .link:hover)` is\n // a true 0-0-0 and loses to any explicit class, which is what the base rule\n // already promised. It returns a list because an element pattern emits both\n // `:where(el, .cls).role` and `.cls-role`.\n const stateRules = (\n sel: (pseudo: string) => string[],\n role: string | null,\n states: Record<string, Record<string, unknown>>,\n colorProp: 'background-color' | 'color' = 'background-color',\n ) => {\n let out = '';\n for (const [state, spec] of Object.entries(states)) {\n const body: string[] = [];\n // `step` intensifies the pattern's colour: fills swap solid → solid-bold;\n // text swaps the bold emphasis stop → x-bold.\n if (typeof spec.step === 'number' && role) {\n const stateVar =\n colorProp === 'background-color'\n ? `var(--color-bg-${role}-${spec.step >= 1 ? 'solid-bold' : 'solid'})`\n : spec.step >= 1\n ? `var(--color-text-${role}-bold)`\n : `var(--color-text-${role})`;\n body.push(`${colorProp}: ${stateVar};`);\n }\n if (typeof spec.scale === 'number') body.push(`scale: ${spec.scale};`);\n if (typeof spec.lift === 'string') body.push(`translate: 0 calc(-1 * ${spec.lift});`);\n if (typeof spec.shadow === 'string' && shadows?.[spec.shadow])\n body.push(`filter: drop-shadow(var(--shadow-${spec.shadow}));`);\n else if (spec.shadow === true)\n body.push(`box-shadow: var(--lift-shadow, 0 8px 20px -6px rgb(0 0 0 / 0.25));`);\n if (spec.ring === true) {\n // A focus ring has to be *seen*, so it uses the solid tone rather than a\n // decorative border tint. `--color-border-focus` is the role-less\n // default, emitted once from ui-primary and contrast-checked as a\n // non-text boundary.\n const ringColor = role ? `var(--color-bg-${role}-solid)` : `var(--color-border-focus)`;\n body.push(`outline: none;`, `box-shadow: 0 0 0 3px ${ringColor};`);\n }\n if (spec.css && typeof spec.css === 'object')\n for (const [k, v] of Object.entries(spec.css as Record<string, string>))\n body.push(`${k}: ${v};`);\n if (!body.length) continue;\n const pseudo =\n state === 'hover'\n ? ':hover'\n : state === 'active'\n ? ':active'\n : state === 'focus-visible'\n ? ':focus-visible'\n : `:${state}`;\n const rule = `${sel(pseudo).join(',\\n')} {\\n ${body.join('\\n ')}\\n}\\n`;\n out += state === 'hover' ? `@media (hover: hover) {\\n${rule}}\\n` : rule;\n }\n return out;\n };\n\n let pat = `/* GENERATED component patterns — do not edit by hand. */\\n`;\n pat += `/* Interaction transitions for patterned elements (independent props compose). */\\n`;\n for (const [pname, p] of Object.entries((patterns?.items ?? {}) as Record<string, Pattern>)) {\n if (!p.base) continue;\n const states = p.states ?? {};\n // `class` defaults to the pattern key only for class-only patterns, so an\n // `element`-only entry never sprouts a surprise class.\n const cls = p.class ?? (p.element ? undefined : pname);\n // Element patterns style at zero specificity (`:where(…)`) so any explicit\n // class — a louder pattern, or a component's own BEM rule — wins without\n // !important. Class-only patterns stay unwrapped at 0-1-0, or they'd lose to\n // every utility. With both, the element and the class share one rule, which\n // is what lets `.btn` / `.link` be applied to any tag.\n //\n // `pseudo` goes inside the `:where()` so a state rule keeps that promise —\n // see the note on `stateRules`. `extra` (a role class) stays outside it,\n // since the variant is meant to carry a class's weight.\n const elementSel = (extra = '', pseudo = '') =>\n `:where(${[p.element, cls && `.${cls}`]\n .filter(Boolean)\n .map((s) => `${s}${pseudo}`)\n .join(', ')})${extra}`;\n const defaultSel = p.element ? elementSel() : `.${cls}`;\n const defaultSelFor = (pseudo: string) =>\n p.element ? [elementSel('', pseudo)] : [`.${cls}${pseudo}`];\n const defaultRole = p.default_role ?? null;\n const base = { ...p.base };\n // Explicit `fill` wins; otherwise infer, keeping the historical name-based\n // special cases so existing consumer configs don't shift behaviour.\n const fills =\n p.fill ??\n (pname === 'button' ||\n pname === 'badge' ||\n base['background-color'] != null ||\n base['background'] != null);\n const colorProp: 'background-color' | 'color' = fills ? 'background-color' : 'color';\n pat += `${defaultSel} {\\n`;\n const hasStates = Object.keys(states).length > 0;\n if (hasStates) {\n pat += ` transition-property: translate, scale, rotate, filter, box-shadow, background-color, color;\\n`;\n pat += ` transition-duration: var(--interact-duration, 200ms);\\n`;\n pat += ` transition-timing-function: var(--interact-easing, ease);\\n`;\n pat += ` translate: 0 0; scale: 1; rotate: 0deg;\\n`;\n }\n if (defaultRole && fills && base['background-color'] == null && base['background'] == null)\n base['background-color'] = `var(--color-bg-${defaultRole}-solid)`;\n const wrappedBase: Record<string, string> = {};\n for (const [prop, val] of Object.entries(base)) {\n const sfx = BASE_HOOK[prop];\n wrappedBase[prop] = sfx ? `var(--${sfx}-${pname}, ${val})` : String(val);\n }\n pat += decls(wrappedBase) + '\\n}\\n';\n pat += stateRules(defaultSelFor, defaultRole, states, colorProp);\n for (const role of p.roles ?? []) {\n // Element patterns take the role as a bare class (`<button class=\"danger\">`)\n // AND as the `<pattern>-<role>` form that class patterns use, so the same\n // variant reaches a non-element host (`<a class=\"btn btn-danger\">`). Both\n // land at 0-1-0 — the element half stays inside :where() so a role variant\n // can't outrank a plain class the way `button.danger` (0-1-1) used to.\n const variantSelsFor = (pseudo: string) =>\n p.element\n ? [elementSel(`.${role}`, pseudo), ...(cls ? [`.${cls}-${role}${pseudo}`] : [])]\n : [`.${cls}-${role}${pseudo}`];\n const variantSels = variantSelsFor('');\n // Fills sit on the role's solid and pair with the foreground computed\n // against it; text variants use the role's text token, which is the one\n // guaranteed legible over a surface in both appearances.\n const variantColorDecl = fills\n ? `background-color: var(--color-bg-${role}-solid); color: var(--color-text-on-${role})`\n : `color: var(--color-text-${role})`;\n pat += `${variantSels.join(',\\n')} { ${variantColorDecl}; }\\n`;\n pat += stateRules(variantSelsFor, role, states, colorProp);\n }\n pat += '\\n';\n }\n generated['patterns.css'] = pat;\n\n // ── animation-effects.css ────────────────────────────────────────────────────\n {\n const anim = ds.animations ?? {};\n const asStr = (v: string | number) => String(v);\n const block = (sel: string, d: Record<string, string>) => `.${sel} {\\n${decls(d)}\\n}\\n`;\n let out = `/* GENERATED animation effects + journeys — do not edit by hand. */\\n`;\n for (const [name, e] of Object.entries(anim.effects ?? {})) {\n const d: Record<string, string> = { '--_anim': e.kf };\n for (const [k, v] of Object.entries(e.css ?? {})) d[k] = asStr(v);\n for (const [k, v] of Object.entries(e.vars ?? {})) d[`--${k}`] = asStr(v);\n out += block(name, d);\n }\n const base = anim.journeys?.base ?? {};\n for (const parts of anim.journeys?.compose ?? []) {\n const d: Record<string, string> = {\n '--_anim': parts.map((p) => `${p}-journey`).join(', '),\n // A journey is entry → hold → exit (keyframes at 0%/100% hidden,\n // 25%–75% held), so it needs the long range that a one-shot entrance\n // doesn't. It starts on the same pivot as `.animate-view` — the\n // element's midpoint 15% into the viewport, which is `entry 50%` plus\n // 10vh (see the note on .animate-view in core's animation.css) — and\n // runs to the end of the exit phase, so the hold occupies the middle of\n // the crossing rather than the bottom edge of the screen.\n //\n // The END is spelled `exit 100%` rather than the equivalent bare `exit`,\n // because lightningcss misparses the shorthand: an omitted offset on the\n // END defaults to 0% there instead of the spec's 100%, so `entry exit`\n // bundled as `entry exit 0%` and every journey snapped back to its hidden\n // `from` state as the element reached the top of the viewport. Guarded by\n // animation-effects.test.ts, which asserts on the BUNDLED css.\n 'animation-range': 'entry calc(50% + 10vh) exit 100%',\n };\n for (const p of parts)\n for (const [k, v] of Object.entries(base[p] ?? {})) d[`--${k}`] = asStr(v);\n out += block(`${parts.join('-')}-journey`, d);\n }\n // Each state matches the element itself OR its direct parent, mirroring the\n // precedent animation.css already sets for the trigger driver\n // (`:is(.is-active, [data-active]) > .animate-trigger`). The parent form is\n // load-bearing, not a convenience: a `hover-reveal-*` element rests at\n // `clip-path: inset(0 100% 0 0)`, and clip-path clips HIT-TESTING as well as\n // painting — so with `:hover` alone the element has zero hittable area and\n // can never receive the hover that would reveal it. Same specificity (0,2,0)\n // as the self form, so nothing reorders.\n const STATES: [string, (s: string) => string][] = [\n ['hover', (s) => `.${s}:hover, :hover > .${s}`],\n ['focus', (s) => `.${s}:focus-visible, :focus-within > .${s}`],\n ['active', (s) => `.${s}.is-active, .${s}[data-active]`],\n ];\n out += `\\n/* State-flip variants — compose with .transition (hover-/focus-/active-<fx>). */\\n`;\n // Every keyframe family gets state variants, `layout` included: `.transition`\n // covers `height` inside `@supports (interpolate-size: allow-keywords)`, and\n // the `layout` keyframe depends on exactly the same feature — so excluding\n // layout here bought no portability, it only made `hover-size-grow` a class\n // that resolved to nothing while the docs advertised it.\n for (const [name, e] of Object.entries(anim.effects ?? {})) {\n const props: Record<string, { from?: string; to?: string }> = {};\n for (const [k, v] of Object.entries(e.vars ?? {})) {\n const m = /^(.*)-(from|to)$/.exec(k);\n if (m) (props[m[1] as string] ??= {})[m[2] as 'from' | 'to'] = asStr(v);\n }\n // The effect's own `css` block travels with the variant too — `size-grow`\n // declares `overflow: clip`, without which a collapsed (0-height) box\n // spills its content instead of hiding it.\n const rest: Record<string, string> = {};\n for (const [k, v] of Object.entries(e.css ?? {})) rest[k] = asStr(v);\n for (const [p, ft] of Object.entries(props)) {\n if (ft.from != null && ft.from !== STATE_DEFAULT[p]) rest[`--${p}-from`] = ft.from;\n if (ft.to != null && ft.to !== STATE_DEFAULT[p]) rest[`--${p}-to`] = ft.to;\n }\n const flip: Record<string, string> = Object.fromEntries(\n Object.keys(props).map((p) => [`--t-${p}`, `var(--${p}-to, ${STATE_DEFAULT[p]})`]),\n );\n if (Object.keys(rest).length)\n out += `${STATES.map(([s]) => `.${s}-${name}`).join(', ')} {\\n${decls(rest)}\\n}\\n`;\n for (const [s, sel] of STATES) out += `${sel(`${s}-${name}`)} {\\n${decls(flip)}\\n}\\n`;\n }\n generated['animation-effects.css'] = out;\n }\n\n // ── Bricks palettes ──────────────────────────────────────────────────────────\n // Named = the hue scales (numeric steps); Semantic = the functional role\n // tokens with their automatic light/dark pairing.\n const namedColors: unknown[] = [];\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const [n, hex] of Object.entries(hue.numeric)) {\n const token = `${name}-${n}`;\n namedColors.push({\n raw: `var(--color-${token})`,\n light: hex,\n id: id(`named:${token}`),\n utilityClasses: UTILITIES,\n });\n }\n const semanticColors: unknown[] = [];\n for (const fr of scaleRoles)\n for (const [t, light] of Object.entries(fr.light)) {\n const dark = fr.dark[t] as string;\n semanticColors.push({\n raw: `var(${tokenVar(fr.role, t)})`,\n light,\n darkModeEnabled: light !== dark,\n dark,\n id: id(`semantic:${fr.role}-${t}`),\n utilityClasses: UTILITIES,\n });\n }\n const bricksColorsNamed = JSON.stringify(\n { id: id('palette:named'), name: 'Named', colors: namedColors },\n null,\n 2,\n );\n const bricksColorsSemantic = JSON.stringify(\n { id: id('palette:semantic'), name: 'Semantic', colors: semanticColors },\n null,\n 2,\n );\n\n // ── Bricks Global Variables (fonts + scales) ─────────────────────────────────\n const bricksVariables = (() => {\n type BrxScale = { scale: number; scaleName: string };\n type BrxVar = { id: string; name: string; value: string; category?: string; scale?: BrxScale };\n type BrxCat = { id: string; name: string; scale: Record<string, unknown>; utilityClasses: [] };\n const scaleMeta = (scope: string, prefix: string, s: ScaleConfig, names: string[]) => {\n const px = Math.round(rem(s.base) * 16);\n const lo = s.fluid?.minRatio ?? s.ratio;\n return {\n scaleScope: scope,\n scaleType: 'tshirt',\n scaleNames: names,\n prefix,\n minFontSize: px,\n minScaleRatio: lo,\n minScaleRatioSelect: lo,\n maxFontSize: px,\n maxScaleRatio: s.ratio,\n maxScaleRatioSelect: s.ratio,\n baseline: s.baseline ?? names[Math.floor((names.length - 1) / 2)],\n };\n };\n const categories: BrxCat[] = [];\n const variables: BrxVar[] = [];\n const addScale = (\n label: string,\n scope: string,\n prefix: string,\n cfg: ScaleConfig | undefined,\n steps: ScaleStep[],\n ) => {\n if (!cfg || !steps.length) return;\n const names = steps.map((s) => s.name);\n const catId = id(`varcat:${scope}`);\n categories.push({\n id: catId,\n name: label,\n scale: scaleMeta(scope, prefix, cfg, names),\n utilityClasses: [],\n });\n for (const st of steps)\n variables.push({\n id: id(`var:${prefix}${st.name}`),\n name: `${prefix}${st.name}`,\n value: st.value,\n category: catId,\n scale: { scale: st.offset, scaleName: st.name },\n });\n };\n addScale('Typography', 'typography', 'text-', ds.typeScale as ScaleConfig, typeSteps);\n addScale('Spacing', 'spacing', 'space-', ds.spaceScale as ScaleConfig, spaceSteps);\n for (const [name, stack] of Object.entries(ds.fonts ?? {}))\n variables.push({ id: id(`var:font-${name}`), name: `font-${name}`, value: stack });\n for (const [name, val] of Object.entries(ds.patterns?.radii ?? {}))\n variables.push({ id: id(`var:br-${name}`), name: `br-${name}`, value: val });\n return JSON.stringify({ variables, categories }, null, 2);\n })();\n\n // ── tokens.json (trimmed token export for programmatic consumers) ────────────\n const numericPalette = Object.fromEntries(\n Object.entries(expandedPalette).map(([k, v]) => [k, v.numeric]),\n );\n const tokensJson = JSON.stringify(\n {\n colors: {\n palette: numericPalette,\n roles: roleMap,\n functional: Object.fromEntries(\n scaleRoles.map((fr) => [fr.role, { light: fr.light, dark: fr.dark }]),\n ),\n },\n fonts: ds.fonts ?? {},\n text: Object.fromEntries(typeSteps.map((s) => [s.name, s.value])),\n spacing: Object.fromEntries(spaceSteps.map((s) => [s.name, s.value])),\n shadows: shadows ?? {},\n radii: ds.patterns?.radii ?? {},\n },\n null,\n 2,\n );\n\n // ── design-manifest.json (live-editor manifest; css format) ──────────────────\n const designManifest = (() => {\n const reverseIndex: Record<string, string> = {};\n // A numeric step maps back to that step's `anchors` entry, NOT to the hue's\n // `seed`: the seed regenerates the whole ramp (and every step would collapse\n // to one path, so editing two steps of a hue would silently keep only one),\n // whereas `anchors.<step>` is precisely the per-step override (see schema.ts).\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const n of Object.keys(hue.numeric))\n reverseIndex[`--color-${name}-${n}`] = `colors.palette.${name}.anchors.${n}`;\n // `kind` travels with the role so the editor picks the right `roleTokens`\n // variant on a remap — it used to infer that from `role === 'surface'`, which\n // silently did the wrong thing for any other surface-kind role.\n const colorRoles = Object.entries(roleMap).map(([name, spec]) => ({\n name,\n ramp: roleHue(spec),\n kind: roleKind(spec),\n }));\n // Per-hue token sets, so a client (the live editor) can re-point a role at\n // another hue. It can't derive these itself: `text-on` is a computed contrast\n // literal, not a var() ref. One variant per role KIND, because the two kinds\n // emit different token sets — a chromatic role has no bare `bg`, a surface\n // role has no solid tints.\n //\n // Keys are token keys (`bg`, `text-on`, `border-bold`, …) — the same ones\n // `tokenVar()` turns into `--color-<target>-<role>[-<variant>]`.\n const roleTokens = Object.fromEntries(\n Object.entries(expandedPalette).map(([hueName, hue]) => {\n const chromatic = functionalRole('_', hueName, hue, 'chromatic');\n const surface = functionalRole('_', hueName, hue, 'surface');\n return [\n hueName,\n {\n chromatic: { light: chromatic.light, dark: chromatic.dark },\n surface: { light: surface.light, dark: surface.dark },\n },\n ];\n }),\n );\n const typoRoles = (typography?.roles ?? {}) as Record<string, TypographyRole>;\n const hooks: Record<string, { prop: string; key: string }> = {};\n for (const [key, [prop, sfx]] of Object.entries(TYPO_KEYMAP)) hooks[sfx] = { prop, key };\n // Index EVERY hook for every role, not just the ones the role already\n // declares. The editor builds its control set from `typography.hooks` (all\n // of TYPO_KEYMAP), so a role that omits `tracking` still gets a `--<role>-ls`\n // control; without an entry here that edit previews live and is then dropped\n // as \"skipped\" on save. The path is a valid place to write whether or not it\n // exists yet — `roles` is an open record and the patch deep-merges.\n for (const role of Object.keys(typoRoles))\n for (const [key, [, sfx]] of Object.entries(TYPO_KEYMAP))\n reverseIndex[`--${role}-${sfx}`] = `typography.roles.${role}.${key}`;\n const pDefaults = patterns?.defaults ?? {};\n const pRadii = patterns?.radii ?? {};\n const pGroups = patterns?.groups ?? {};\n const pItems = (patterns?.items ?? {}) as Record<string, Pattern>;\n for (const prop of Object.keys(pDefaults))\n reverseIndex[`--${prop}-default`] = `patterns.defaults.${prop}`;\n for (const [group, props] of Object.entries(pGroups))\n for (const prop of Object.keys(props))\n reverseIndex[`--${prop}-${group}`] = `patterns.groups.${group}.${prop}`;\n const items = Object.entries(pItems).map(([name, p]) => {\n const base = p.base ?? {};\n const wrappable = Object.keys(base)\n .filter((prop) => prop in BASE_HOOK)\n .map((prop) => ({ sfx: BASE_HOOK[prop] as string, prop }));\n for (const { sfx, prop } of wrappable)\n reverseIndex[`--${sfx}-${name}`] = `patterns.items.${name}.base.${prop}`;\n return { name, group: p.group ?? null, base, wrappable, roles: p.roles ?? [] };\n });\n // Radii last, and only where a pattern hasn't already claimed the var: a\n // `patterns.radii` key that equals a pattern name collides on `--br-<name>`\n // (e.g. radii `card` vs the `card` pattern — a live collision in the example\n // config). The pattern's BASE_HOOK is the documented override, so it wins,\n // and `validate()` surfaces the collision as a warning so it isn't silent.\n for (const name of Object.keys(pRadii))\n if (!(`--br-${name}` in reverseIndex))\n reverseIndex[`--br-${name}`] = `patterns.radii.${name}`;\n return JSON.stringify(\n {\n colors: {\n ramps: Object.keys(expandedPalette),\n steps: NUMERIC_STEPS,\n palette: numericPalette,\n roles: colorRoles,\n roleTokens,\n },\n typography: {\n roles: Object.keys(typoRoles),\n hooks,\n families: typographyFamilies,\n specs: typoRoles,\n },\n scales: {\n text: typeSteps.map((s) => ({ name: s.name, value: s.value, max: s.max })),\n space: spaceSteps.map((s) => ({ name: s.name, value: s.value, max: s.max })),\n },\n fonts: ds.fonts ?? {},\n patterns: { defaults: pDefaults, radii: pRadii, groups: pGroups, items },\n shadows: shadows ?? {},\n reverseIndex,\n },\n null,\n 2,\n );\n })();\n\n // ── Tailwind bundle ──────────────────────────────────────────────────────────\n // Only the tailwind format consumes this (see `generate`), and assembling it\n // reads every framework partial off disk — so skip the work for css/bricks.\n const tailwind =\n format !== 'tailwind'\n ? ''\n : emitTailwind({\n ds,\n expandedPalette,\n scaleRoles,\n shadows,\n typeSteps,\n spaceSteps,\n typography,\n roleDecls,\n twTypeTokensCss,\n twPatternTokensCss,\n patternsCss: pat,\n assetsDir,\n utilities: UTILITIES,\n systemColorScheme: buildOpts.systemColorScheme === true,\n });\n\n // ── DESIGN.md ────────────────────────────────────────────────────────────────\n // Same deal as the tailwind bundle: only its own format consumes it, so the\n // other three don't pay for building it.\n const designMd =\n format !== 'design'\n ? ''\n : emitDesignMd({ ds, expandedPalette, scaleRoles, typeSteps, spaceSteps, shadows });\n\n return {\n generated,\n bricksColorsNamed,\n bricksColorsSemantic,\n bricksVariables,\n tokensJson,\n designManifest,\n tailwind,\n designMd,\n twTypeTokensCss,\n twPatternTokensCss,\n patternsCss: pat,\n };\n}\n\n// ── Tailwind emitter ──────────────────────────────────────────────────────────\ninterface TwCtx {\n ds: DesignSystem;\n expandedPalette: Record<string, ExpandedHue>;\n scaleRoles: FunctionalRole[];\n shadows: Record<string, string> | undefined;\n typeSteps: ScaleStep[];\n spaceSteps: ScaleStep[];\n typography: DesignSystem['typography'];\n roleDecls: (role: string, spec: TypographyRole) => Record<string, string>;\n twTypeTokensCss: string;\n twPatternTokensCss: string;\n patternsCss: string;\n assetsDir: string;\n /**\n * The configured `colors.utilities`. Was previously hardcoded to\n * bg/text/border at the emit site, so a consumer who enabled `outline`/\n * `fill`/`stroke` got them in css/bricks but not tailwind.\n */\n utilities: string[];\n /** `BuildOptions.systemColorScheme` — see the OS-preference block below. */\n systemColorScheme: boolean;\n}\n\nfunction emitTailwind(ctx: TwCtx): string {\n const {\n ds,\n expandedPalette,\n scaleRoles,\n shadows,\n typeSteps,\n spaceSteps,\n typography,\n roleDecls,\n twTypeTokensCss,\n twPatternTokensCss,\n patternsCss,\n assetsDir,\n utilities,\n } = ctx;\n const cssDir = join(assetsDir, 'css');\n const nl = (arr: string[]) => arr.filter(Boolean).join('\\n');\n const parts: string[] = [\n `/* GENERATED for Tailwind v4 (Astro) — do not edit by hand.\\n` +\n ` Class reference: npx vitops docs classes · All topics: npx vitops docs\\n` +\n ` Fonts below are STACKS ONLY — this file loads no webfonts. Load them with\\n` +\n ` Astro's fonts: config and point the token at the family's cssVariable. */`,\n ];\n parts.push(`@import \"tailwindcss\";\\n`);\n\n const theme: string[] = [];\n theme.push(` /* Hue scales → bg-<hue>-<step> text-* border-* (numeric, 50…950) */`);\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const [n, hex] of Object.entries(hue.numeric))\n theme.push(` --color-${name}-${n}: ${hex};`);\n theme.push(`\\n /* Fonts → font-* (stacks only; no @font-face is emitted — see header) */`);\n for (const [name, stack] of Object.entries(ds.fonts ?? {}))\n theme.push(` --font-${name}: ${stack};`);\n theme.push(`\\n /* Fluid type scale → text-* */`);\n for (const s of typeSteps) theme.push(` --text-${s.name}: ${s.value};`);\n // Fluid space steps are NOT put in Tailwind's --spacing-* namespace: named\n // spacing keys shadow the size scales (e.g. `max-w-7xl` would resolve to\n // var(--spacing-7xl) ≈ 6rem and collapse layouts). They ship as --space-*\n // (matching the css format) in a plain :root below; use var(--space-<name>)\n // or the TW4 arbitrary form p-(--space-md). Numeric spacing (p-4 …) keeps\n // Tailwind's default --spacing multiplier.\n theme.push(`\\n /* Drop-shadows → shadow-* */`);\n for (const [name, value] of Object.entries(shadows ?? {}))\n theme.push(` --shadow-${name}: ${value};`);\n theme.push(`\\n /* Container breakpoints → @sm:/@md:/@lg:/@xl: */`);\n for (const [name, val] of BREAKPOINTS) theme.push(` --container-${name}: ${val};`);\n parts.push(`@theme {\\n${theme.join('\\n')}\\n}\\n`);\n\n if (spaceSteps.length)\n parts.push(\n `/* Fluid space scale — var(--space-<name>) or p-(--space-<name>) */\\n:root {\\n` +\n spaceSteps.map((s) => ` --space-${s.name}: ${s.value};`).join('\\n') +\n `\\n}\\n`,\n );\n\n // Role tokens go in a plain :root block, NOT @theme — including the emphasis\n // stops, despite those living in the --color-* namespace. The @utility set\n // below is the public API.\n //\n // This is load-bearing, not stylistic. Measured against tailwindcss@4.3.3:\n // when a token is in @theme AND an @utility of the derived name exists,\n // Tailwind merges both into one rule with the @theme declaration LAST, and it\n // does so regardless of source order. Putting `--color-<role>-<stop>` in\n // @theme would therefore silently substitute the stop for the plane on the\n // five colliding classes — including `text-<role>-muted` (step 800 → 300) and\n // `text-<role>-x-muted` (600 → 100), i.e. exactly the tokens tokens.ts's APCA\n // test guarantees are readable. Raw hue scales are safe in @theme because no\n // @utility competes for those names.\n if (scaleRoles.length) {\n let fn = '';\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.light)) fn += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n const focus = scaleRoles.find((r) => r.role === 'ui-primary') ?? scaleRoles[0];\n if (focus) fn += ` --color-border-focus: ${focus.light['bg-solid']};\\n`;\n const surface = scaleRoles.find((r) => r.role === 'surface');\n if (surface) {\n fn += ` --surface-glass: color-mix(in oklch, var(--color-bg-surface) 72%, transparent);\\n`;\n fn += ` --overlay: color-mix(in oklch, var(--color-${surface.hue}-950) 45%, transparent);\\n`;\n }\n parts.push(`/* Role tokens (the public API) */\\n:root {\\n${fn}}\\n`);\n }\n\n parts.push(\n `/* ── Framework tokens (consumed by the inlined components) ── */\\n` +\n `${twTypeTokensCss}\\n${twPatternTokensCss}`,\n );\n\n // Dark appearance: the automatic functional flip (solid stays mode-stable).\n let darkBlock = '';\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.dark))\n if (fr.light[t] !== val) darkBlock += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n {\n const surface = scaleRoles.find((r) => r.role === 'surface');\n if (surface)\n darkBlock += ` --overlay: color-mix(in oklch, var(--color-${surface.hue}-950) 60%, transparent);\\n`;\n }\n if (darkBlock) {\n parts.push(\n `/* Functional role tokens (dark) */\\n${DARK_SEL} {\\n color-scheme: dark;\\n${darkBlock}}\\n`,\n );\n // Same opt-in OS-preference block as the css/bricks path — see the comment\n // there. Emitted unlayered here for the same reason the rest of this format\n // is: Tailwind owns the layering, and role tokens must stay out of `@theme`.\n if (ctx.systemColorScheme)\n parts.push(\n `/* Functional role tokens (dark) — OS preference, no explicit choice */\\n` +\n `@media (prefers-color-scheme: dark) {\\n ${SYSTEM_DARK_SEL} {\\n` +\n ` color-scheme: dark;\\n${darkBlock.replace(/^ {2}/gm, ' ')} }\\n}\\n`,\n );\n }\n\n parts.push(\n `/* State variant for the active flip (hover/focus-visible are built in). */\\n` +\n `@custom-variant is-active (&.is-active, &[data-active]);\\n`,\n );\n\n // `typography.headings` — the bare-element → role bindings, the same rules the\n // css/bricks path emits into typography.css. This format used to emit only the\n // `@utility font-<role>` half, so a Tailwind consumer's <h1> and <body> got no\n // role styling at all: no family, no size, no text-wrap.\n //\n // Tailwind's `base` layer, deliberately. It puts these behind BOTH `@utility\n // font-<role>` (utilities layer) and the patterns (components layer), matching\n // css/bricks — where typography.css sits in vitops.utilities and the bare tag\n // selector loses to `.font-<role>` on specificity rather than on layer. Emitted\n // unlayered, an `h1` rule here would beat every Tailwind utility.\n {\n const roles = (typography?.roles ?? {}) as Record<string, TypographyRole>;\n const bindings = Object.entries(typography?.headings ?? {}).filter(([, r]) => roles[r]);\n if (bindings.length)\n parts.push(\n `/* Bare-element type roles (typography.headings) */\\n@layer base {\\n` +\n bindings\n .map(\n ([tag, role]) =>\n ` ${tag} {\\n${decls(roleDecls(role, roles[role] as TypographyRole), ' ')}\\n }`,\n )\n .join('\\n') +\n `\\n}\\n`,\n );\n }\n\n const util: string[] = [];\n if (scaleRoles.length) {\n util.push(`/* Role colour utilities (the public API) */`);\n // Same source as the css/bricks formats — the two used to diverge because\n // this path re-parsed the other's generated strings and only ever ran the\n // functional half. See roleColorUtilities().\n for (const { cls, prop, value } of roleColorUtilities(scaleRoles, utilities))\n util.push(`@utility ${cls} {\\n ${prop}: ${value};\\n}`);\n if (scaleRoles.some((r) => r.role === 'surface'))\n util.push(\n `@utility glass {\\n background-color: var(--surface-glass);\\n backdrop-filter: blur(12px);\\n -webkit-backdrop-filter: blur(12px);\\n}`,\n );\n }\n util.push(`/* Typography roles */`);\n for (const [role, spec] of Object.entries(\n (typography?.roles ?? {}) as Record<string, TypographyRole>,\n ))\n util.push(`@utility font-${role} {\\n${decls(roleDecls(role, spec))}\\n}`);\n util.push(`\\n/* Animation effects (pair with .transition or a driver) */`);\n const asStr = (v: string | number) => String(v);\n for (const [name, e] of Object.entries(ds.animations?.effects ?? {})) {\n const d: Record<string, string> = { '--_anim': e.kf };\n for (const [k, v] of Object.entries(e.css ?? {})) d[k] = asStr(v);\n for (const [k, v] of Object.entries(e.vars ?? {})) d[`--${k}`] = asStr(v);\n util.push(`@utility ${name} {\\n${decls(d)}\\n}`);\n // No `kf` filter — see the css path. `flip-size-grow` is as real as\n // `flip-fade-in`; both rest on `.transition`, which covers height behind\n // `@supports (interpolate-size: allow-keywords)`.\n const props = new Set<string>();\n for (const k of Object.keys(e.vars ?? {})) {\n const m = /^(.*)-(from|to)$/.exec(k);\n if (m) props.add(m[1] as string);\n }\n const flip = Object.fromEntries(\n [...props].map((p) => [`--t-${p}`, `var(--${p}-to, ${STATE_DEFAULT[p]})`]),\n );\n util.push(`@utility flip-${name} {\\n${decls(flip)}\\n}`);\n }\n util.push(`\\n/* Split — internal fractions (pair split with a ratio) */`);\n // The `.split` PATTERN itself is not here — it is emitted into `@layer\n // components` with the rest of the structure, so `flex-col` beats it by layer\n // exactly as it does in css/bricks. Only its modifiers are utilities.\n //\n // That placement costs `@md:split`, and nothing recovers it. Measured against\n // tailwindcss@4.3.3: `@utility` throws \"`@utility` cannot be nested\" inside\n // `@layer`, AND inside a file pulled in with `@import … layer(…)` — the layer\n // clause is itself a nesting context. A `@custom-variant` doesn't help either:\n // a variant applied to a components-layer class emits nothing, because variants\n // attach to utility candidates only. `md-flex-row` says \"become a row at md\" in\n // every format, so the loss is a bare `<bp>-split` that had no unique job.\n //\n // `order`, not `row-reverse`, so the swap applies on whichever axis the split\n // is currently on — which is the point: it decides which panel comes FIRST,\n // and that is mostly a question about the stacked state. `reading-flow` keeps\n // focus order with the visual order where supported; until that is broad,\n // only one of the two panels should hold focusable content (WCAG 2.4.3).\n util.push(\n `@utility split-reverse {\\n reading-flow: flex-visual;\\n & > :first-child { order: 1; }\\n}`,\n );\n const RATIOS: [number, number][] = [\n [1, 2],\n [2, 1],\n [1, 3],\n [3, 1],\n [1, 4],\n [4, 1],\n [2, 3],\n [3, 2],\n ];\n for (const [a, b] of RATIOS)\n util.push(\n `@utility split-${a}-${b} {\\n flex-direction: row;\\n --_split-a: ${a};\\n --_split-b: ${b};\\n}`,\n );\n // Not derivable from `@theme`: the fluid space steps are deliberately kept out\n // of Tailwind's `--spacing-*` namespace (see the note above the `:root` block),\n // so `gap-md` has to be an explicit utility here. Verified against\n // tailwindcss@4.3.3 to win over the built-in functional `gap-*` and to accept\n // variants (`@md:gap-md`), which is why no per-breakpoint classes are emitted.\n const gaps = gapUtilities(spaceSteps);\n if (gaps.length) {\n util.push(`\\n/* Gap — the fluid space scale (var(--space-<name>)) */`);\n for (const { cls, prop, value } of gaps)\n util.push(`@utility ${cls} {\\n ${prop}: ${value};\\n}`);\n }\n util.push(`\\n/* Track placement (inside .centered) */`);\n for (const track of ['measure', 'breakout', 'spotlight', 'fullbleed'])\n util.push(`@utility ${track} {\\n grid-column: ${track};\\n}`);\n\n // `layout.css` is skipped wholesale in this format and a subset re-emitted\n // above, which left these two families missing from tailwind ENTIRELY — not\n // dropped via TW_CLASH, just never re-emitted. Unlike the `<bp>-` classes they\n // have no Tailwind equivalent to fall back on, and unlike a misspelt class\n // `vitops lint` cannot flag them, because they are not anchored to the\n // consumer's config. A consumer who used them got silence and no styling.\n util.push(`\\n/* Auto-fit grid — column count is content-driven, unlike .split */`);\n util.push(\n `@utility grid-auto {\\n display: grid;\\n gap: var(--grid-gap, 1rem);\\n` +\n ` grid-template-columns: repeat(auto-fit, minmax(var(--grid-min, 13rem), 1fr));\\n` +\n // Was missing here while layout.css carried it, so in THIS format a\n // `<ul class=\"grid-auto\">` inside `.rhythm` kept the `li + li` margin: the\n // grid stretched the row to the tallest and the first cell alone looked\n // vertically offset — the exact symptom layout.css warns about.\n ` &:is(ul, ol) > li + li { margin-block-start: 0; }\\n}`,\n );\n // Applied to the SECOND element of a pair, to override the rhythm it inherited.\n util.push(`\\n/* Vertical-rhythm overrides (mirrors layout.css) */`);\n for (const pair of [\n 'h-p',\n 'p-p',\n 'p-h',\n 'h-h',\n 'p-list',\n 'list-p',\n 'li-li',\n 'text-media',\n 'media-text',\n ])\n util.push(\n `@utility m-${pair} {\\n margin-top: calc(var(--rhythm-base) * var(--rhythm-${pair}));\\n}`,\n );\n for (const [name, mult] of [\n ['0', null],\n ['xs', '0.25'],\n ['s', '0.5'],\n ['m', '1'],\n ['l', '1.5'],\n ['xl', '2'],\n ] as const)\n util.push(\n `@utility m-${name} {\\n margin-top: ${mult == null ? '0' : `calc(var(--rhythm-base) * ${mult})`};\\n}`,\n );\n parts.push(util.join('\\n') + '\\n');\n\n // Structure mirrors layout.css (kept literal for parity with the original emitter).\n parts.push(`/* ── Structure (mirrors src/css/layout.css) ── */\n:root {\n --rhythm-scale: 1;\n --rhythm-base: calc(1rlh * var(--rhythm-scale));\n --rhythm-h-p: 0.4;\n --rhythm-p-p: 0.9;\n --rhythm-p-h: 1.6;\n --rhythm-h-h: 0.6;\n --rhythm-p-list: 0.5;\n --rhythm-list-p: 0.9;\n --rhythm-li-li: 0.3;\n --rhythm-text-media: 1.2;\n --rhythm-media-text: 1.2;\n --width-measure: 65ch;\n --width-breakout: 90ch;\n --width-spotlight: 120ch;\n --gutter: clamp(1rem, 4cqi, 3rem);\n}\n\nbody {\n container-type: inline-size;\n /* Named so \\`patterns/scroll-target.css\\`'s \\`@container body (…)\\` queries\n resolve — .toc-layout/.toc-sidebar/.toc-inline. Those partials are inlined\n into this bundle verbatim, so dropping the name (as this literal did) left\n the TOC permanently in its narrow layout in the tailwind format only. */\n container-name: body;\n}\n\n/* Class-level structure rules live in \\`components\\` so track/spacing utilities\n (@layer utilities — later in the layer order) can override them; unlayered\n CSS would beat ALL layered utilities regardless of specificity (e.g.\n \\`.centered > *\\` pinning children to \\`measure\\` over \\`.spotlight\\`). */\n@layer components {\n.rhythm {\n display: flow-root;\n}\n.rhythm > * + * {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-p-p));\n}\n.rhythm > :where(h1, h2, h3, h4, h5, h6) + p {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-h-p));\n}\n.rhythm > p + :where(h1, h2, h3, h4, h5, h6) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-p-h));\n}\n.rhythm > :where(h1, h2, h3, h4, h5, h6) + :where(h1, h2, h3, h4, h5, h6) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-h-h));\n}\n.rhythm > p + :where(ul, ol) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-p-list));\n}\n.rhythm > :where(ul, ol) + p {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-list-p));\n}\n.rhythm :where(ul, ol) > li + li {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-li-li));\n}\n.rhythm > :where(p, h1, h2, h3, h4, h5, h6, ul, ol) + :where(figure, img, picture, video) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-text-media));\n}\n.rhythm > :where(figure, img, picture, video) + :where(p, h1, h2, h3, h4, h5, h6, ul, ol) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-media-text));\n}\n\n.centered {\n --_measure: min(var(--width-measure), 100% - var(--gutter) * 2);\n --_breakout: minmax(0, calc((var(--width-breakout) - var(--width-measure)) / 2));\n --_spotlight: minmax(0, calc((var(--width-spotlight) - var(--width-breakout)) / 2));\n position: relative;\n display: grid;\n grid-template-columns:\n [fullbleed-start] minmax(var(--gutter), 1fr)\n [spotlight-start] var(--_spotlight)\n [breakout-start] var(--_breakout)\n [measure-start] var(--_measure) [measure-end]\n var(--_breakout) [breakout-end]\n var(--_spotlight) [spotlight-end]\n minmax(var(--gutter), 1fr) [fullbleed-end];\n}\n.centered > * {\n grid-column: measure;\n}\n\n.region {\n padding-block: clamp(\n var(--region-space-min, 3rem),\n var(--region-space, 8vh),\n var(--region-space-max, 8rem)\n );\n}\n\n/* \\`.split\\` is a PATTERN, so it belongs here rather than in an \\`@utility\\` — that\n is what makes \\`flex-col\\` beat it by layer instead of by a source-order race\n whose winner depends on Tailwind's property-based sort of custom utilities.\n Its ratio/reversal modifiers stay utilities. Mirrors layout.css, where each\n rule's rationale is written out; in short: \\`min-inline-size: 0\\` because a flex\n item's automatic minimum is its min-content size; the ratio as a flex BASIS\n rather than a grow factor, because grow shares out only the free space and a\n child's padding is not part of it; scoped to a two-child split because a ratio\n is a pair contract and a middle child with no basis would collapse to zero;\n \\`box-sizing: border-box\\` because a basis only sizes the border box on a\n border-box item (Tailwind's preflight sets it, the other formats' reset does). */\n.split {\n display: flex;\n flex-direction: row;\n}\n.split > * {\n flex: 1;\n box-sizing: border-box;\n min-inline-size: 0;\n}\n.split > :first-child {\n flex-grow: var(--_split-a, 1);\n}\n.split > :last-child {\n flex-grow: var(--_split-b, 1);\n}\n.split > :first-child:nth-last-child(2) {\n flex-basis: ${splitBasis('--_split-a')};\n}\n.split > :nth-child(2):last-child {\n flex-basis: ${splitBasis('--_split-b')};\n}\n}\n`);\n\n // Same layering rationale as the structure block above. Guarded on existence\n // like componentPartialOrder below: `assets/**` is a gitignored build artifact\n // that `vp test` does not produce, so an unguarded read makes the tailwind\n // format untestable in a clean checkout — which is how an 87-class vocabulary\n // gap between css and tailwind went unnoticed. The token layer still emits.\n const animPath = join(cssDir, 'animation.css');\n const animEngine = existsSync(animPath) ? readFileSync(animPath, 'utf8') : '';\n if (animEngine)\n parts.push(\n `/* ── Animation engine (animation.css) ── */\\n@layer components {\\n${animEngine}\\n}`,\n );\n // Patterns live in Tailwind's `components` layer so single-purpose utilities\n // (@layer utilities — declared later in the layer order) override them, e.g.\n // `.text-on-ui-primary` beating the link pattern's element-level `a { color }`.\n // Unlayered CSS would win over ALL layered utilities regardless of specificity.\n parts.push(`/* ── Component patterns ── */\\n@layer components {\\n${patternsCss}\\n}`);\n\n // Component + structural partials: the full framework library, minus the\n // Tailwind-owned utility layer. Sourced live from the CSS partials (in index.css\n // cascade order) so this never goes stale, then run through stripForTailwind\n // (dropping the TW_CLASH names Tailwind provides itself).\n const droppedClashes = new Set<string>();\n let droppedVariantBlocks = 0;\n /**\n * Is this `@container (min-width: …)` block a PRE-EXPANDED VARIANT block —\n * i.e. only `.sm-*`/`.md-*`/`.lg-*`/`.xl-*` utility classes, which Tailwind\n * regenerates on demand as `@md:`?\n *\n * Anything else in a container query is component *behaviour*, not a variant,\n * and dropping it breaks the component. `sitenav.css` is the case that caught\n * this: its `@container (min-width: 48rem) { .sitenav--bp-md { … } }` is what\n * switches the nav to its desktop layout, and blanket-dropping every\n * container block meant the tailwind format shipped a nav stuck in mobile.\n */\n const isVariantBlock = (raw: string): boolean => {\n const open = raw.indexOf('{');\n const body = raw.slice(open + 1, raw.lastIndexOf('}'));\n const selectors: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < body.length; i++) {\n const ch = body[i];\n if (ch === '{') {\n if (depth === 0) selectors.push(body.slice(start, i));\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) start = i + 1;\n }\n }\n const names = selectors\n .flatMap((s) => s.split(','))\n .map((s) => s.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim())\n .filter(Boolean);\n return names.length > 0 && names.every((n) => /^\\.(sm|md|lg|xl)-/.test(n));\n };\n const stripForTailwind = (css: string): string => {\n const kept: string[] = [];\n let depth = 0;\n let start = 0;\n let preludeEnd = -1;\n for (let i = 0; i < css.length; i++) {\n const ch = css[i];\n if (ch === '/' && css[i + 1] === '*') {\n const end = css.indexOf('*/', i + 2);\n i = end === -1 ? css.length : end + 1;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n i += 1;\n while (i < css.length && css[i] !== ch) i += css[i] === '\\\\' ? 2 : 1;\n continue;\n }\n if (ch === '{') {\n if (depth === 0) preludeEnd = i;\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const raw = css.slice(start, i + 1).trim();\n const prelude = css\n .slice(start, preludeEnd)\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .trim();\n const clash = /^\\.([A-Za-z0-9_-]+)/.exec(prelude);\n const name = clash?.[1] as string | undefined;\n if (/^@container\\s*\\(\\s*min-width:/.test(prelude) && isVariantBlock(raw))\n droppedVariantBlocks++;\n else if (name && TW_CLASH.has(name) && !CLASH_KEEP.has(name)) droppedClashes.add(name);\n else if (raw) kept.push(raw);\n start = i + 1;\n }\n }\n }\n return kept.join('\\n\\n');\n };\n\n const partials = componentPartialOrder(cssDir);\n const componentCss = partials\n .map((rel) => {\n const css = readFileSync(join(cssDir, rel), 'utf8');\n return `/* ── ${rel} ── */\\n${stripForTailwind(css)}`;\n })\n .join('\\n\\n');\n // Same layering rationale as the patterns block above. `componentPartialOrder`\n // already returns [] when assets are absent, so this is empty in that case.\n if (componentCss)\n parts.push(\n `/* ── Component + structural partials (Tailwind-clashing utilities dropped) ── */\\n` +\n `/* Dropped ${droppedVariantBlocks} pre-expanded breakpoint block(s) — write @sm:/@md:/@lg:/@xl: instead.\\n` +\n ` Dropped ${droppedClashes.size} clashing utilit(ies) Tailwind provides itself:\\n` +\n ` ${[...droppedClashes].sort().join(' ') || '(none)'} */\\n` +\n `@layer components {\\n${componentCss}\\n}`,\n );\n\n return nl(parts) + '\\n';\n}\n\n/**\n * Partials the tailwind format does NOT inline, because it re-creates them by\n * hand: the engine (`global.css` — Tailwind's preflight covers the reset;\n * `animation.css` — read directly and wrapped in `@layer components`), and the\n * two layout partials, whose utilities are re-emitted as `@utility` and whose\n * structure is re-emitted in the `@layer components` literal.\n *\n * **Every partial mapped to `vitops.utilities` must be listed here.** Inlining a\n * utility family lands it in tailwind's `@layer components`, the exact inversion\n * the layer split exists to remove — and it fails SILENTLY, because each of those\n * classes already exists as an `@utility` that wins on layer anyway. You would get\n * ~30 dead rules and no test failure. `format-parity.test.ts` asserts the\n * implication structurally rather than spot-checking the output.\n *\n * The implication is one-way: `layout.css` is skipped while sitting in\n * `vitops.components`, because its structure is re-emitted by hand.\n */\n/**\n * Framework COMPONENTS whose class name collides with a Tailwind utility, and\n * which must therefore survive the `TW_CLASH` strip.\n *\n * The clash test matches a rule's leading `.<name>`, which is right for a\n * single-purpose utility (Tailwind ships its own) and wrong for a pattern that\n * merely shares the name. `patterns/sticky.css` opens `.sticky { … }` and was\n * being deleted from the tailwind bundle WHOLESALE — the `--_sticky-offset`\n * wiring, the z-index, and every `&.sticky--bottom`/`--inline-start` variant —\n * so a consumer writing `class=\"sticky sticky--bottom\"` got bare\n * `position: sticky` and nothing else.\n *\n * `table` is here for the same reason but was never actually hit: `table.css`'s\n * prelude is `table,\\n.table`, which doesn't start with `.`, so the regex missed\n * it by luck. Listing it makes that explicit rather than accidental.\n */\nconst CLASH_KEEP: ReadonlySet<string> = new Set(['sticky', 'table']);\n\nexport const TAILWIND_SKIP: ReadonlySet<string> = new Set([\n 'global.css',\n 'animation.css',\n 'layout.css',\n 'layout-utilities.css',\n // Everything left here after the reveal family moved to patterns/reveal.css is\n // either a TW_CLASH name (display, sr-only, text-wrap) or a pre-expanded\n // variant block, so the strip already emptied it — reading it was pure waste,\n // and leaving it out made the invariant above look violated when it wasn't.\n 'utilities.css',\n]);\n\n/**\n * The component/structural CSS partials to inline into the Tailwind bundle, in\n * index.css cascade order. Everything the aggregator imports EXCEPT `TAILWIND_SKIP`\n * and the generated token layer (Tailwind builds its own via @theme).\n */\nfunction componentPartialOrder(cssDir: string): string[] {\n const indexPath = join(cssDir, 'index.css');\n const order: string[] = [];\n const seen = new Set<string>();\n const text = existsSync(indexPath) ? readFileSync(indexPath, 'utf8') : '';\n for (const m of text.matchAll(/@import\\s+['\"]\\.\\/([^'\"]+)['\"]/g)) {\n const rel = m[1] as string;\n if (rel.startsWith('generated/')) continue;\n if (TAILWIND_SKIP.has(rel)) continue;\n if (!seen.has(rel) && existsSync(join(cssDir, rel))) {\n seen.add(rel);\n order.push(rel);\n }\n }\n // Fallback: if no index.css, inline utilities + every pattern partial.\n if (!order.length) {\n if (existsSync(join(cssDir, 'utilities.css'))) order.push('utilities.css');\n const pdir = join(cssDir, 'patterns');\n if (existsSync(pdir))\n for (const f of readdirSync(pdir).sort()) if (f.endsWith('.css')) order.push(`patterns/${f}`);\n }\n return order;\n}\n\n// ── CSS bundling (css + bricks formats) ───────────────────────────────────────\n\n/** The bundle's cascade layers, in precedence order (last wins). */\nexport const CSS_LAYERS = ['vitops.base', 'vitops.components', 'vitops.utilities'] as const;\n\n/**\n * Which layer each `index.css` chunk belongs to. Anything unmapped defaults to\n * `vitops.components` — the safe default, since an unrecognised partial is far\n * more likely to be a component than a utility family.\n *\n * The split is by what the file *emits*, not what it's named:\n * • base — the UA reset and the pure `:root` token blocks.\n * • components — the animation engine, structural layout, and every pattern.\n * • utilities — the single-purpose classes that must be able to override a\n * pattern (`bg-*`, `drop-shadow-*`, `font-*`, effects, …).\n *\n * `color.css` and `shadows.css` each mix a `:root` block with utility classes\n * and go to `utilities` whole. That is safe because custom-property resolution\n * is NOT source-order dependent — a `:root` block declared after a rule that\n * reads it still resolves.\n *\n * `layout.css` is genuinely mixed (structural `.rhythm`/`.centered` AND\n * `.m-*`/`.flex`/`.split-*` utilities) and stays in `components` whole, so its\n * utility half still can't override a pattern. Splitting it is a separate\n * change; see the 0.9.0 changelog.\n */\nexport const CHUNK_LAYER: Record<string, (typeof CSS_LAYERS)[number]> = {\n 'global.css': 'vitops.base',\n 'generated/type-tokens.css': 'vitops.base',\n 'generated/tokens.css': 'vitops.base',\n 'generated/color.css': 'vitops.utilities',\n 'generated/shadows.css': 'vitops.utilities',\n 'generated/typography.css': 'vitops.utilities',\n 'generated/animation-effects.css': 'vitops.utilities',\n 'generated/spacing.css': 'vitops.utilities',\n 'layout-utilities.css': 'vitops.utilities',\n 'utilities.css': 'vitops.utilities',\n};\n\n/**\n * A `.split` child's flex basis. The ratio is a BASIS rather than a grow factor\n * because grow shares out only the FREE space, which a child's padding is not\n * part of — so a padded column came out wider than its sibling by exactly its\n * horizontal padding. Must stay character-identical to layout.css; the parity\n * suite matches this expression against both.\n */\nexport const splitBasis = (v: '--_split-a' | '--_split-b'): string =>\n `calc(var(${v}, 1) / (var(--_split-a, 1) + var(--_split-b, 1)) * 100%)`;\n\n/** The layer a partial's rules are wrapped in; unmapped partials are components. */\nexport const layerForPartial = (rel: string): (typeof CSS_LAYERS)[number] =>\n CHUNK_LAYER[rel] ?? 'vitops.components';\n\n/**\n * Assemble the full stylesheet by resolving index.css's @import order against the\n * static partials (from assets) and the freshly generated token partials (in\n * memory), then minify with lightningcss. No @import survives, so no disk\n * resolution / shared `generated/` dir is needed.\n *\n * Each chunk is wrapped in a cascade layer. This is what lets a single-purpose\n * utility override a component pattern — `class=\"card bg-danger-muted\"` — which\n * previously depended on source order and so silently did nothing here while\n * working in the tailwind format, where Tailwind's own layers already ordered\n * them correctly.\n *\n * Consequence worth knowing: unlayered CSS beats ALL layered CSS regardless of\n * specificity, so a consumer's own stylesheet now wins over the framework by\n * default. That is deliberate — it is the override story every layered\n * framework ships — but it means an unlayered *reset* will beat framework\n * component rules it used to lose to. Such a reset belongs in a layer declared\n * before `vitops.base` (see the `<style>` block in this repo's index.html).\n */\nfunction bundleCss(\n generated: Record<string, string>,\n assetsDir: string,\n minify: boolean,\n): { code: string; map: string | undefined } {\n const cssDir = join(assetsDir, 'css');\n const indexPath = join(cssDir, 'index.css');\n const index = readFileSync(indexPath, 'utf8');\n const chunks: string[] = [];\n for (const line of index.split('\\n')) {\n const m = /@import\\s+['\"]\\.\\/([^'\"]+)['\"]/.exec(line);\n if (!m) continue;\n const rel = m[1] as string;\n const body = rel.startsWith('generated/')\n ? (generated[rel.slice('generated/'.length)] ?? '')\n : readFileSync(join(cssDir, rel), 'utf8');\n if (!body.trim()) continue;\n chunks.push(`@layer ${layerForPartial(rel)} {\\n${body}\\n}`);\n }\n // `/*!` rather than `/*`: lightningcss strips ordinary comments when\n // minifying, and both the css and bricks bundles are minified — so a plain\n // banner would never reach the file anyone actually opens. Whoever opens this\n // is looking for a class name; point them at the live reference.\n const banner =\n `/*! GENERATED by @getvitops/generator — do not edit by hand.\\n` +\n ` Class reference: npx vitops docs classes · All topics: npx vitops docs */\\n`;\n // Declare the order up front so it is explicit rather than an artifact of\n // which chunk happened to appear first.\n const merged = banner + `@layer ${CSS_LAYERS.join(', ')};\\n` + chunks.join('\\n');\n const res = transform({\n filename: 'styles.css',\n code: Buffer.from(merged),\n minify,\n sourceMap: minify,\n });\n return {\n code: res.code.toString(),\n map: res.map ? res.map.toString() : undefined,\n };\n}\n\n// ── public generate() ─────────────────────────────────────────────────────────\n/**\n * Read `input` as whichever config kind it is, and return the design system to\n * build from plus the site config if that is what it was.\n *\n * The design system is validated here rather than in `resolveInput` so the error\n * can name where it came from: a theme inside a site config reports its `themes`\n * path, which is the difference between \"your config is wrong\" and \"your config\n * is wrong *here*\" when the file is a few hundred lines of company facts.\n */\nfunction loadInput(\n input: string | DesignSystem | SiteConfig,\n opts: { theme?: string; siteEnv?: string },\n): { ds: DesignSystem; site?: SiteConfig } {\n const raw = typeof input === 'string' ? JSON.parse(readFileSync(input, 'utf8')) : input;\n const resolved = resolveInput(raw, opts);\n const result = validate(resolved.designSystem);\n if (!result.ok) {\n const where =\n resolved.theme != null\n ? `design system at designSystem.themes.${resolved.theme}`\n : 'design-system.json';\n const lines = result.errors\n .slice(0, 12)\n .map((e) => ` • ${e.path.join('.') || '(root)'}: ${e.message}`)\n .join('\\n');\n throw new Error(`Invalid ${where}:\\n${lines}`);\n }\n for (const w of result.warnings) console.warn(`[vitops] ${w}`);\n return { ds: result.data, ...(resolved.site ? { site: resolved.site } : {}) };\n}\n\nexport async function generate(options: GenerateOptions): Promise<GenerateResult> {\n const format: Format = options.format ?? 'bricks';\n const outDir = options.outDir ?? 'dist';\n const assetsDir = options.assetsDir ?? DEFAULT_ASSETS;\n const { ds, site: embedded } = loadInput(options.input, {\n ...(options.theme != null ? { theme: options.theme } : {}),\n ...(options.siteEnv != null ? { siteEnv: options.siteEnv } : {}),\n });\n // Loaded before `build` because `designSystem.defaultColorScheme` decides what\n // the colour layer emits. (It is read again below for legal documents;\n // resolving twice would validate twice and double any warning.)\n //\n // An explicit `site` wins over one embedded in `input` — it is the more\n // specific statement, and the two are the same file in every case but the one\n // where a consumer deliberately split them.\n const site = options.site != null ? loadSiteConfigFile(options.site, options.siteEnv) : embedded;\n const built = build(ds, format, assetsDir, {\n systemColorScheme:\n options.systemColorScheme ?? site?.designSystem?.defaultColorScheme === 'system',\n });\n mkdirSync(outDir, { recursive: true });\n const written: string[] = [];\n const put = (rel: string, content: string) => {\n const p = join(outDir, rel);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, content);\n written.push(p);\n };\n\n if (format === 'design') {\n // Deliberately the only output: DESIGN.md conventionally lives at the repo\n // root next to AGENTS.md, not in a build directory, so this format is meant\n // to be run with `--out .` — writing a stylesheet alongside it would be\n // surprising. Compose it when you want both: `--format css,design`.\n put('DESIGN.md', built.designMd);\n } else if (format === 'tailwind') {\n put('tailwind.css', built.tailwind);\n put('tokens.json', built.tokensJson);\n } else if (format === 'css') {\n const { code } = bundleCss(built.generated, assetsDir, true);\n put('styles.css', code);\n put('tokens.json', built.tokensJson);\n put('design-manifest.json', built.designManifest);\n } else {\n // bricks: bundled minified CSS + Bricks import JSON + copied JS/PHP/docs.\n const { code, map } = bundleCss(built.generated, assetsDir, true);\n put('styles.min.css', map ? code + `\\n/*# sourceMappingURL=styles.min.css.map */` : code);\n if (map) put('styles.min.css.map', map);\n put('bricks-colors-named.json', built.bricksColorsNamed);\n put('bricks-colors-semantic.json', built.bricksColorsSemantic);\n put('bricks-variables.json', built.bricksVariables);\n put('tokens.json', built.tokensJson);\n // Framework-static JS bundles → outDir root (theme enqueues them).\n const jsDir = join(assetsDir, 'js');\n if (existsSync(jsDir)) {\n cpSync(jsDir, outDir, { recursive: true });\n for (const f of readdirSync(jsDir)) written.push(join(outDir, f));\n }\n // Bricks PHP elements + loader → outDir/bricks.\n const bricksSrc = join(assetsDir, 'bricks');\n if (existsSync(bricksSrc)) {\n cpSync(bricksSrc, join(outDir, 'bricks'), { recursive: true });\n written.push(join(outDir, 'bricks'));\n }\n // OKF docs bundle (generated per-config) → outDir/docs.\n const docs = generateDocs(ds, assetsDir);\n for (const [rel, content] of Object.entries(docs)) put(join('docs', rel), content);\n }\n\n // Legal documents → outDir/legal, as HTML fragments.\n //\n // Opt-in via `site`, and emitted for every format that emits files at all —\n // passing a site config and silently getting nothing back would be the\n // surprising behaviour. `design` is excluded because it emits DESIGN.md and\n // deliberately nothing else.\n //\n // HTML rather than markdown because this is the fragment a WordPress theme,\n // a Bricks shortcode or a plain page can include with no build step of its own.\n if (site != null && format !== 'design') {\n const legal = generateLegal(site, { output: 'html' });\n for (const [name, content] of Object.entries(legal)) put(join('legal', name), content);\n\n // Icon sprite → outDir/icons.svg.\n //\n // Opt-in via `icons.sprite`, because building it needs the @iconify-json/*\n // collections and most consumers render icons through their framework's own\n // integration instead. This is the path for the ones that can't: Bricks,\n // EmDash renderers, any plain HTML — `<use href=\"…/icons.svg#id\">`, no JS.\n const icons = site.icons as\n | { sprite?: boolean; ui?: string; brand?: string; weight?: string; semantic?: string[] }\n | undefined;\n if (icons?.sprite) {\n const { ui, brand, weight, semantic, sprite: _sprite, ...sets } = icons;\n const include = generateIconInclude({\n ...(ui ? { ui } : {}),\n ...(brand ? { brand } : {}),\n ...(weight ? { weight } : {}),\n ...(semantic ? { semantic } : {}),\n ...sets,\n });\n // Semantic names get a set-independent alias (`icon-menu`) alongside the\n // qualified id, so markup written against a sprite survives a set swap —\n // the same guarantee `resolveIcon` gives Astro consumers.\n const aliases: Record<string, string> = {};\n for (const name of semantic ?? []) {\n try {\n aliases[`icon-${name}`] = resolveIcon(name, ui ?? 'fa7-solid', weight ? { weight } : {});\n } catch {\n // Already reported by generateIconInclude, which throws on the same input.\n }\n }\n const built = await buildIconSprite({ include, aliases });\n put('icons.svg', built.svg);\n if (built.missing.length)\n console.warn(\n `[vitops] icons.sprite: ${built.missing.length} icon(s) were not found and are ` +\n `absent from the sprite: ${built.missing.join(', ')}.`,\n );\n }\n }\n\n return { format, outDir, written };\n}\n\nfunction loadSiteConfigFile(input: string | SiteConfig, siteEnv?: string): SiteConfig {\n const raw = typeof input === 'string' ? JSON.parse(readFileSync(input, 'utf8')) : input;\n // resolveSiteConfig validates and throws with one issue per line.\n return resolveSiteConfig(raw, siteEnv);\n}\n","/**\n * @getvitops/generator — public API.\n *\n * Turn a `design-system.json` into platform outputs (Bricks, standalone CSS,\n * Tailwind v4). The `zod/mini` schema is the single source of truth: types,\n * validation, and the published JSON Schema all derive from it.\n */\nexport { generate, roleColorUtilities } from './generate.ts';\nexport type {\n GenerateOptions,\n GenerateResult,\n Format,\n StylesheetFormat,\n ColorUtility,\n} from './generate.ts';\n\n// Exposed so `vitops lint` can ask what the generator emits instead of\n// re-deriving the vocabulary and drifting from it.\nexport { expandPalette, functionalRole } from './tokens.ts';\nexport type { ExpandedHue, FunctionalRole } from './tokens.ts';\n\nexport { generateDocs } from './docs.ts';\n/**\n * SVG sprite emitter. `spriteId` is the id grammar `<use href=\"…#id\">` targets;\n * @getvitops/astro's Icon.astro mirrors it, so treat it as a shared contract.\n */\nexport { buildIconSprite, loadIconSvg, spriteId } from './icons-sprite.ts';\nexport type { IconSpriteOptions, IconSpriteResult } from './icons-sprite.ts';\nexport { NUMERIC_STEPS } from './tokens.ts';\nexport {\n TW_CLASH,\n BASE_HOOK,\n DARK_SEL,\n REQUIRED_ROLES,\n ROLE_TOKEN_KEYS,\n roleHue,\n roleKind,\n} from './shared.ts';\nexport type { RoleSpec } from './shared.ts';\nexport { tokenVar, tokenClass, CONTRAST } from './tokens.ts';\nexport type { RoleKind } from './tokens.ts';\n\nexport { DesignSystemSchema, jsonSchema, SCHEMA_URL, validate } from './schema.ts';\nexport type { DesignSystem, ValidationResult } from './schema.ts';\nexport {\n SiteConfigSchema,\n SiteFontSchema,\n siteJsonSchema,\n SITE_SCHEMA_URL,\n validateSite,\n resolveSiteConfig,\n resolvePrivacyContact,\n resolveTheme,\n // Every entry point that takes a config goes through these, so a consumer who\n // keeps their tokens inside the larger site config points the same option at\n // that file rather than maintaining a second one.\n isSiteConfig,\n resolveInput,\n stripNulls,\n deepMerge,\n JURISDICTIONS,\n} from './site.ts';\nexport type {\n ContactObject,\n Jurisdiction,\n PostalAddress,\n ResolvedInput,\n SiteConfig,\n SiteFont,\n SiteIndexNow,\n SiteIndexing,\n SiteSearchConsole,\n SiteValidationResult,\n} from './site.ts';\n\n// Legal documents. A sibling of `generateDocs`, not a `generate()` format:\n// `generate()` is keyed to a DesignSystem, and these render from a SiteConfig.\nexport {\n generateLegal,\n enabledDocs,\n renderMarkdown,\n renderNodes,\n derivePolicyVars,\n detectProcessorKeys,\n resolveProcessors,\n KNOWN_PROCESSORS,\n parseMarkdown,\n toContentNodes,\n toHtmlFragment,\n toPortableText,\n DOC_ORDER,\n DOC_SLUGS,\n TEMPLATES,\n} from './legal/index.ts';\nexport type {\n GenerateLegalOptions,\n LegalDoc,\n LegalOutput,\n PolicyVars,\n Processor,\n KnownProcessorKey,\n Block,\n Span,\n DocSet,\n} from './legal/index.ts';\n\nimport { SCHEMA_URL, type DesignSystem } from './schema.ts';\n\n/**\n * A minimal but complete starter design system, used by `vitops init`. It\n * validates against the schema and generates real output in every format, so a\n * new project can `vitops generate` immediately and then tune from here.\n */\nexport function defaultConfig(): DesignSystem {\n return {\n $schema: SCHEMA_URL,\n colors: {\n // Each hue is generated as an 11-step OKLCH scale from its seed.\n palette: {\n brand: { seed: '#2e9b73' },\n ink: { seed: '#3f4a5c' },\n sky: { seed: '#2f7bc0' },\n sun: { seed: '#d08a1f' },\n rose: { seed: '#c74a42' },\n },\n // role → hue. Tokens (--color-<target>-<role>-<variant>) derive from the\n // hue's scale; dark mode flips automatically. `kind: \"surface\"` marks the\n // page/panel colours, which get a bare `bg-<role>`; the bare-string form\n // means chromatic, so a signal colour says tint-or-solid rather than\n // leaving \"how loud?\" to a guess.\n roles: {\n neutral: { hue: 'ink', kind: 'surface' },\n surface: { hue: 'ink', kind: 'surface' },\n 'ui-primary': 'brand',\n 'brand-primary': 'brand',\n info: 'sky',\n success: 'brand',\n warning: 'sun',\n danger: 'rose',\n },\n utilities: ['bg', 'text', 'icon', 'border'],\n },\n shadows: {\n sm: '0 1px 2px rgb(0 0 0 / 0.08)',\n md: '0 4px 6px rgb(0 0 0 / 0.12)',\n lg: '0 10px 15px rgb(0 0 0 / 0.18)',\n },\n fonts: {\n display: 'system-ui, -apple-system, \"Segoe UI\", sans-serif',\n sans: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n mono: 'ui-monospace, \"SF Mono\", Menlo, monospace',\n },\n typeScale: {\n base: '1rem',\n names: ['2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl'],\n baseStep: 4,\n baseline: 'm',\n ratio: 1.2,\n fluid: { minVw: '22.5rem', maxVw: '80rem', minRatio: 1.12 },\n },\n spaceScale: {\n base: '1rem',\n names: ['2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl'],\n baseStep: 4,\n baseline: 'm',\n ratio: 1.25,\n fluid: { minVw: '22.5rem', maxVw: '80rem', minRatio: 1.2 },\n },\n patterns: {\n defaults: {\n ds: 'none',\n b: '1px solid var(--color-border-surface-muted)',\n br: '0.375rem',\n p: '1rem',\n fs: '1rem',\n },\n // No `card` key here: a radii key named after a pattern collides on `--br-<name>`,\n // shadowing that pattern's override hook and leaving its `-group` alias unreachable\n // (validate() warns about exactly this). `card` is in the `panel` group, which already\n // carries the same 0.5rem, so dropping it is value-preserving.\n radii: { pill: '999px', circle: '50%' },\n groups: {\n control: {\n ds: 'var(--ds-default)',\n b: 'var(--b-default)',\n br: 'var(--br-default)',\n p: '0.5em 1em',\n fs: 'var(--fs-default)',\n },\n panel: {\n ds: 'var(--shadow-md)',\n b: 'var(--b-default)',\n br: '0.5rem',\n p: '1rem',\n fs: 'var(--fs-default)',\n },\n },\n z: { raised: 1, sticky: 100, overlay: 200, top: 1000 },\n items: {\n // Affordance tier: bare <button> and .btn share one zero-specificity rule,\n // so any explicit class (including .cta) overrides it.\n btn: {\n group: 'control',\n element: 'button',\n class: 'btn',\n fill: false,\n // Geometry resolves through the group alias layer (`--<prop>-btn-group`),\n // so the mapping to the `control` group lives in CSS and stays editable;\n // `overrides` restate only what this tier does differently.\n overrides: { b: '1px solid transparent', fs: 'inherit' },\n base: {\n display: 'inline-flex',\n 'align-items': 'center',\n 'justify-content': 'center',\n gap: '0.4em',\n padding: 'var(--p-btn-group)',\n 'border-radius': 'var(--br-btn-group)',\n border: 'var(--b-btn-group)',\n 'box-shadow': 'var(--ds-btn-group)',\n background: 'transparent',\n color: 'inherit',\n 'font-family': 'inherit',\n 'font-size': 'var(--fs-btn-group)',\n 'font-weight': 'inherit',\n 'text-decoration': 'none',\n cursor: 'pointer',\n },\n states: {\n hover: { step: 1, css: { 'background-color': 'var(--color-bg-surface-muted)' } },\n 'focus-visible': { ring: true },\n },\n roles: [],\n },\n // Persuasion tier: opt-in, works on any element (<a>, <button>, <summary>).\n cta: {\n group: 'control',\n class: 'cta',\n fill: true,\n // `ui-primary`, not `brand-primary`: a CTA is a prominent *interface*\n // affordance, and its prominence already comes from fill/weight/padding.\n // Keeping it on the ui role means the whole interaction family (btn,\n // link, cta) shares one hue lineage — otherwise focus rings change\n // colour depending on which tier you tabbed onto. Brand stays reachable\n // as an explicit `.cta-brand-primary` variant.\n default_role: 'ui-primary',\n overrides: { p: '0.75em 1.5em', b: 'none', ds: 'var(--shadow-sm)', fs: 'inherit' },\n base: {\n display: 'inline-flex',\n 'align-items': 'center',\n 'justify-content': 'center',\n gap: '0.5em',\n padding: 'var(--p-cta-group)',\n 'border-radius': 'var(--br-cta-group)',\n border: 'var(--b-cta-group)',\n 'font-family': 'inherit',\n 'font-size': 'var(--fs-cta-group)',\n 'font-weight': '600',\n 'text-decoration': 'none',\n cursor: 'pointer',\n color: 'var(--color-text-on-ui-primary)',\n 'box-shadow': 'var(--ds-cta-group)',\n },\n states: {\n hover: { step: 1, lift: '1px' },\n active: { scale: 0.97 },\n 'focus-visible': { ring: true },\n },\n roles: [],\n },\n card: {\n group: 'panel',\n class: 'card',\n base: {\n 'border-radius': 'var(--br-card-group)',\n padding: '1.5rem',\n background: 'var(--color-bg-surface)',\n border: 'var(--b-card-group)',\n 'box-shadow': 'var(--ds-card-group)',\n },\n states: {},\n roles: [],\n },\n },\n },\n typography: {\n families: {\n display: 'var(--font-display)',\n sans: 'var(--font-sans)',\n code: 'var(--font-mono, ui-monospace, monospace)',\n },\n // `text-wrap` is stated on every role because omitting it is NOT \"inherit\":\n // it is emitted at its identity (`wrap`) so role classes fully reset one\n // another, which would cancel the `pretty` a role inherits from body.\n roles: {\n display: {\n family: 'display',\n size: 'var(--text-3xl)',\n weight: 700,\n 'line-height': '1.05',\n tracking: '-0.03em',\n 'text-wrap': 'balance',\n },\n heading: {\n family: 'display',\n size: 'var(--text-xl)',\n weight: 600,\n 'line-height': '1.3',\n 'text-wrap': 'balance',\n },\n body: {\n family: 'sans',\n size: 'var(--text-m)',\n weight: 400,\n 'line-height': '1.55',\n 'text-wrap': 'pretty',\n },\n },\n // `body` binds base page typography to the body role, so prose inherits it\n // and the role's tokens stay the single place it's edited.\n headings: { body: 'body', h1: 'display', h2: 'heading', h3: 'heading' },\n },\n animations: {\n effects: {\n 'fade-in': { kf: 'composite', vars: { 'opacity-from': 0 } },\n 'slide-up': {\n kf: 'composite',\n vars: { 'translate-y-from': 'var(--slide-distance, 2rem)' },\n },\n },\n journeys: {\n // Each part must declare the `from` endpoint its keyframe reads — an\n // empty `slide` leaves slide-journey animating translate 0 → 0, i.e. a\n // journey that silently doesn't slide. Same var as the `slide-up`\n // effect above, so `--slide-distance` tunes both.\n base: {\n fade: { 'opacity-from': 0 },\n slide: { 'translate-y-from': 'var(--slide-distance, 2rem)' },\n },\n compose: [['fade'], ['slide'], ['fade', 'slide']],\n },\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["providersSection"],"sources":["../src/shared.ts","../src/schema.ts","../src/config.ts","../src/tokens.ts","../src/docs.ts","../src/design-md.ts","../src/legal/providers.ts","../src/legal/derive.ts","../src/legal/render.ts","../src/legal/templates/shared.ts","../src/legal/templates/cookies.ca.ts","../src/legal/templates/privacy.ca.ts","../src/legal/templates/terms.ca.ts","../src/legal/templates/index.ts","../src/legal/index.ts","../src/icons-sprite.ts","../src/generate.ts","../src/index.ts"],"sourcesContent":["/**\n * Data shared between the generator (`generate.ts`) and the docs bundle\n * (`docs.ts`). Lives in its own module because `generate.ts` imports `docs.ts` —\n * importing back the other way would be a cycle.\n */\n\n/**\n * Selector the dark functional-token flip hangs off.\n *\n * `data-brx-theme` is Bricks' own attribute — Bricks sets it, so it's what the\n * WordPress target needs. Nothing sets it anywhere else, which meant the dark\n * flip was unreachable outside Bricks: the shipped `<color-scheme-toggle>` web\n * component writes `documentElement.dataset.theme` (i.e. `data-theme`), so\n * clicking \"Dark\" changed an attribute no rule matched. Matching both makes the\n * component work on every target without changing what Bricks already does.\n *\n * This covers the EXPLICIT choice. The OS preference is a second, opt-in block —\n * see `SYSTEM_DARK_SEL` — because turning it on flips a site dark for dark-OS\n * users, which is the site's decision rather than the design system's.\n *\n * Shared so the docs quote the selector the generator actually emits.\n */\nexport const DARK_SEL = ':root[data-brx-theme=\"dark\"], :root[data-theme=\"dark\"]';\n\n/**\n * Selector for the OS-preference dark block, emitted inside\n * `@media (prefers-color-scheme: dark)` when a site opts in.\n *\n * Derived from `DARK_SEL`'s attributes rather than written out a third time, and\n * inverted: this must apply when NO explicit choice has been made. That is\n * exactly what `<color-scheme-toggle>`'s \"System\" position produces — it removes\n * `data-theme` entirely — so with this block present System resolves to the OS\n * instead of silently falling through to light, and needs no JS to do it.\n *\n * The `:not()`s are what keep an explicit *light* choice winning over a dark OS.\n */\nexport const SYSTEM_DARK_SEL = `:root${DARK_SEL.split(', ')\n .map((s) => s.replace(/^:root\\[([\\w-]+)=\"dark\"\\]$/, '[$1=\"light\"]'))\n .map((attr) => `:not(${attr})`)\n .join('')}`;\n\n/**\n * Roles the shipped CSS partials reference with NO fallback, so a config that\n * omits one leaves those rules resolving to nothing — an invalid declaration,\n * not a graceful degrade.\n *\n * `colors.roles` is an open record: any name works and generates a full token\n * set, utilities and dark flip. But the framework's own component CSS is\n * written against these six, so \"roles are arbitrary\" is only half true — they\n * are *extensible*, over a required core. `validate()` warns when one is\n * missing; `required-roles.test.ts` re-derives this list from the partials so\n * it cannot drift as components are added.\n *\n * Kept as a constant rather than scanned at call time because `validate()` is\n * a pure function — the CLI, the Vite plugin and `toJSONSchema` all import it,\n * and none of them should touch the filesystem to answer \"is this config ok?\".\n */\nexport const REQUIRED_ROLES: readonly string[] = [\n 'brand-primary',\n 'danger',\n 'neutral',\n 'surface',\n 'ui-primary',\n 'warning',\n];\n\n/**\n * Every token key a role can resolve to, across both role kinds. Shared so the\n * required-roles drift test greps for exactly what the generator emits.\n *\n * These are *keys*, not var names: the role sits in the middle of the property\n * (`--color-bg-danger-muted`), so compose them with `tokenVar()` from `tokens.ts`\n * rather than concatenating by hand.\n */\nexport const ROLE_TOKEN_KEYS: readonly string[] = [\n // backgrounds — surface roles get the bare token and the full range,\n // chromatic roles get tints plus the solid family.\n 'bg',\n 'bg-muted',\n 'bg-x-muted',\n 'bg-bold',\n 'bg-x-bold',\n 'bg-solid',\n 'bg-solid-bold',\n 'bg-solid-x-bold',\n // foregrounds\n 'text',\n 'text-bold',\n 'text-muted',\n 'text-x-muted',\n 'text-xx-muted',\n 'text-on',\n 'text-on-bold',\n // non-text tiers\n 'icon',\n 'icon-muted',\n 'border',\n 'border-muted',\n 'border-bold',\n];\n\n/** How a role is authored in `colors.roles`: a bare hue, or a hue plus its kind. */\n// `kind` admits an explicit `undefined` because the repo runs\n// `exactOptionalPropertyTypes` and the zod-inferred config type spells optionals\n// that way — without it every call site would need a cast.\nexport type RoleSpec = string | { hue: string; kind?: 'surface' | 'chromatic' | undefined };\n\n/** The palette hue a role points at, through either authoring form. */\nexport const roleHue = (spec: RoleSpec): string => (typeof spec === 'string' ? spec : spec.hue);\n\n/**\n * A role's kind. The bare-string shorthand means `chromatic`, because signal\n * colours are the common case and surfaces are the two or three you name once.\n */\nexport const roleKind = (spec: RoleSpec): 'surface' | 'chromatic' =>\n typeof spec === 'string' ? 'chromatic' : (spec.kind ?? 'chromatic');\n\n/**\n * Pattern base geometry props → per-pattern override-hook shorthand. Each hook\n * wraps the authored value (`padding: var(--p-btn, 0.4em 0.8em)`) so a\n * consumer restyles one pattern by setting one variable. The hook is named after\n * the pattern's key, not its class.\n */\nexport const BASE_HOOK: Record<string, string> = {\n padding: 'p',\n 'border-radius': 'br',\n border: 'b',\n 'box-shadow': 'ds',\n 'font-size': 'fs',\n // Both spellings map to `bg`, because patterns author either (`card` uses the\n // shorthand, `status` the longhand). A pattern setting both would map the\n // same var twice — a config error, not something to design around.\n background: 'bg',\n 'background-color': 'bg',\n};\n\n/**\n * Framework utility classes whose names collide with Tailwind's own defaults.\n * The `tailwind` format strips any rule targeting these — Tailwind provides\n * them, so consumers use Tailwind's utilities for these names instead.\n */\nexport const TW_CLASH: ReadonlySet<string> = new Set<string>([\n 'block',\n 'inline',\n 'inline-block',\n 'flow-root',\n 'flex',\n 'inline-flex',\n 'grid',\n 'inline-grid',\n 'table',\n 'inline-table',\n 'table-caption',\n 'table-cell',\n 'table-row',\n 'contents',\n 'hidden',\n 'list-item',\n 'static',\n 'fixed',\n 'absolute',\n 'relative',\n 'sticky',\n 'isolate',\n 'visible',\n 'invisible',\n 'collapse',\n 'sr-only',\n 'not-sr-only',\n 'flex-row',\n 'flex-row-reverse',\n 'flex-col',\n 'flex-col-reverse',\n 'flex-wrap',\n 'flex-nowrap',\n 'items-start',\n 'items-end',\n 'items-center',\n 'items-baseline',\n 'items-stretch',\n 'justify-start',\n 'justify-end',\n 'justify-center',\n 'justify-between',\n 'justify-around',\n 'justify-evenly',\n 'content-start',\n 'content-end',\n 'content-center',\n 'content-between',\n 'content-around',\n 'content-evenly',\n 'text-left',\n 'text-center',\n 'text-right',\n 'text-justify',\n 'text-start',\n 'text-end',\n 'text-wrap',\n 'text-nowrap',\n 'text-balance',\n 'text-pretty',\n]);\n","/**\n * Canonical `design-system.json` schema — the single source of truth.\n *\n * Authored with `zod/mini` (tree-shakeable Zod v4). Everything else derives from it:\n * • the `DesignSystem` TS type (`z.infer`), used throughout the generator,\n * • the published JSON Schema (`toJSONSchema`), emitted to `schema.json` for `$schema` refs,\n * • runtime validation (`validate`) for the CLI and to gate `generate`,\n * • the generated `authoring.md` reference doc (walks `jsonSchema`'s descriptions).\n */\nimport * as z from 'zod/mini';\nimport { REQUIRED_ROLES, type RoleSpec, roleHue } from './shared.ts';\n\n/**\n * Attach a JSON-Schema `description`. zod/mini has no `.describe()` method; the\n * mini-API equivalent is `.check(z.describe(…))`, and `.check()` clones — so a\n * shared sub-schema (`Scale`, `CssDecls`, …) can carry a different description\n * per use-site without mutating the original.\n */\nexport const desc = <T extends { check(...checks: never[]): T }>(schema: T, text: string): T =>\n schema.check(z.describe(text) as never);\n\nconst CssDecls = desc(\n z.record(z.string(), z.string()),\n 'A CSS declaration block: property → value. Values stay strings (they can be hex, var(), clamp(), keywords, …); the generator, not the schema, interprets them.',\n);\nconst Scalar = z.union([z.string(), z.number()]);\nconst VarMap = z.record(z.string(), Scalar);\n\n// ── colors ──────────────────────────────────────────────────────────────────\nconst SeededRamp = desc(\n z.strictObject({\n seed: desc(\n z.string(),\n 'Seed colour (hex or oklch()). An 11-step numeric scale (50…950, tinted near-white → tinted near-black) is generated in OKLCH from it; the seed is preserved at its natural step.',\n ),\n anchors: z.optional(\n desc(\n z.record(z.string(), z.string()),\n 'Step → colour overrides (hex or oklch()) pinned VERBATIM at those steps. Every other step takes its lightness from the shared ladder, with chroma and hue interpolated between the anchors — so an anchor is reproduced exactly and is the only step allowed off the ladder. An explicit anchor overrides the seed at that step; two anchors that resolve to the same step are an error.',\n ),\n ),\n }),\n 'Seeded hue: the 11-step scale is GENERATED in OKLCH from `seed` (anchors pin specific steps).',\n);\nconst FixedRamp = desc(\n z.strictObject({\n tones: desc(\n z.union([z.array(z.string()), z.record(z.string(), z.string())]),\n 'Fixed brand kit: authored tones placed verbatim at their nearest steps plus tinted off-white/off-black endpoints; no interpolation. Either an ordered light → dark array or a step → colour map.',\n ),\n }),\n 'Fixed hue: authored brand tones used verbatim; no generation.',\n);\nconst Ramp = desc(\n z.union([SeededRamp, FixedRamp]),\n 'A palette hue, authored one of two ways: `{ seed, anchors? }` generates an 11-step numeric OKLCH scale (50…950) from the seed, or `{ tones }` supplies a fixed brand kit used verbatim.',\n);\n\n/**\n * A role points at a hue, and optionally declares its kind. The bare-string form\n * is the shorthand for a chromatic role — signal colours are the common case,\n * and the two or three surfaces are worth naming explicitly.\n */\nconst RoleSpecSchema = z.union([\n desc(z.string(), 'A palette hue name. Shorthand for `{ hue, kind: \"chromatic\" }`.'),\n z.strictObject({\n hue: desc(z.string(), 'The palette hue this role resolves to.'),\n kind: z.optional(\n desc(\n z.enum(['surface', 'chromatic']),\n '`surface` — a page/panel colour: gets a bare `bg-<role>` plus the full emphasis range and text scale. `chromatic` (default) — a signal colour: tints and solids only, no bare `bg-<role>`.',\n ),\n ),\n }),\n]);\n\nconst UtilityName = z.enum(['bg', 'text', 'icon', 'border', 'outline', 'fill', 'stroke']);\n\nconst Colors = desc(\n z.strictObject({\n palette: desc(\n z.record(z.string(), Ramp),\n 'Palette hues by name. Each becomes an 11-step numeric OKLCH scale (`--color-<hue>-50…950`). Every ramp shares one fixed lightness ladder, so a step means the same lightness in every hue; only chroma and hue vary. Beyond the outermost authored colour the chroma decays towards a small endpoint value (0.008 light / 0.015 dark) so the near-white and near-black ends keep a whisper of the hue — but that is a **ceiling**, not a target, so a low-chroma seed stays low and **a chroma-0 seed gives a true neutral** rather than a tinted one. The ladder is also enforced: if pinned colours leave a ramp non-monotonic (some step darker than the one below it), the build fails rather than shipping a scale whose hover states run backwards.',\n ),\n roles: desc(\n z.record(z.string(), RoleSpecSchema),\n `Maps semantic role names onto palette hues. Role names are ARBITRARY — add a key and the generator emits that role's token set (\\`--color-<target>-<role>[-<variant>]\\` for target bg/text/icon/border), its dark-mode flip and its utility classes.\\n\\nA value is either a hue name (\\`\"danger\": \"rust\"\\`) or \\`{ \"hue\": …, \"kind\": \"surface\" | \"chromatic\" }\\`. **The kind decides the shape of the token set.** \\`chromatic\\` (the default, and what the bare-string form means) is a signal colour: its backgrounds split into tints (\\`bg-<role>-x-muted\\`/\\`-muted\\`) and solids (\\`bg-<role>-solid[-bold|-x-bold]\\`), with deliberately **no bare \\`bg-<role>\\`** — \"how loud?\" is a question the author answers. \\`surface\\` is a page/panel colour: it has a bare \\`bg-<role>\\` plus the full emphasis range and text scale.\\n\\nDark mode flips automatically; there is no per-appearance scheme grammar. The solid family and its computed \\`text-on-<role>\\` foreground stay mode-stable so a filled button keeps its identity. Six roles are a required core, because the shipped framework CSS references them with no fallback: ${REQUIRED_ROLES.join(', ')}. Conventional additions are ui-secondary/accent, brand-secondary, info and success.`,\n ),\n utilities: z.optional(\n desc(\n z.array(UtilityName),\n 'Which colour utility-class families to emit (`bg-*`, `text-*`, `icon-*`, `border-*`, `outline-*`, `fill-*`, `stroke-*`). Defaults to bg, text, icon, border. `icon` is a separate non-text tier (a glyph may run more vivid than text); `outline`/`fill`/`stroke` have no tokens of their own and alias the border and icon tiers.',\n ),\n ),\n }),\n 'The colour system (the only required section): `palette` hues become generated OKLCH scales; `roles` map semantic roles onto those hues, from which all role tokens and dark mode derive.',\n);\n\n// ── fluid modular scale (type + space) ──────────────────────────────────────\nconst Scale = z.strictObject({\n base: desc(z.string(), 'Anchor size (a CSS length, e.g. \"1rem\") — the value at `baseStep`.'),\n ratio: desc(z.number(), 'Modular ratio between adjacent steps at large viewports.'),\n steps: desc(\n z.optional(z.number()),\n 'Token count when `names` is absent (steps are then named 1..steps).',\n ),\n names: desc(\n z.optional(z.array(z.string())),\n 'Step names, smallest → largest (e.g. [\"xs\",\"sm\",\"md\",…]); each becomes a token suffix.',\n ),\n baseStep: desc(z.optional(z.number()), '1-based index of the step whose value is `base`.'),\n baseline: desc(\n z.optional(z.string()),\n 'Named step used as the fluid pivot / GUI scale centre (defaults to `baseStep`).',\n ),\n fluid: desc(\n z.optional(\n z.strictObject({\n minVw: desc(z.string(), 'Viewport width (CSS length) where fluid scaling bottoms out.'),\n maxVw: desc(z.string(), 'Viewport width (CSS length) where fluid scaling tops out.'),\n minRatio: desc(z.number(), 'Modular ratio at/below `minVw` (usually < `ratio`).'),\n }),\n ),\n 'Makes the scale fluid: each step compiles to a clamp() that interpolates from `minRatio` at `minVw` to `ratio` at `maxVw`.',\n ),\n});\n\n// ── patterns ────────────────────────────────────────────────────────────────\nconst Pattern = desc(\n z.strictObject({\n group: desc(\n z.optional(z.string()),\n 'Token-cascade group this pattern belongs to (e.g. tag / control / panel); base declarations resolve through `--<prop>-<group>` before `--<prop>-default`.',\n ),\n overrides: z.optional(\n desc(CssDecls, 'Per-pattern token overrides, emitted as `--<prop>-<name>-group` values.'),\n ),\n element: desc(\n z.optional(z.string()),\n 'Style at element level via zero-specificity `:where(<element>)` (instead of, or alongside, a class).',\n ),\n class: desc(\n z.optional(z.string()),\n \"Class name to emit (defaults to the pattern's key when no `element` is set). Combined with `element`, the pattern emits one zero-specificity `:where(<element>, .<class>)` rule so the class works on any tag and any explicit class overrides it.\",\n ),\n fill: desc(\n z.optional(z.boolean()),\n 'Whether this pattern is colour-filled (states/roles drive `background-color` + `on-solid` text) or text-coloured (they drive `color`). Defaults to true when `base` declares a background.',\n ),\n default_role: desc(\n z.optional(z.string()),\n 'Semantic colour role applied to the bare/default variant.',\n ),\n base: z.optional(\n desc(\n CssDecls,\n 'Base CSS declarations. Geometry properties (padding, border-radius, border, box-shadow, font-size) are wrapped in per-pattern override hooks (`--p-<name>`, `--br-<name>`, `--b-<name>`, `--ds-<name>`, `--fs-<name>`) so consumers can restyle one pattern by setting one variable.',\n ),\n ),\n states: desc(\n z.optional(z.record(z.string(), z.record(z.string(), z.unknown()))),\n 'Interaction states (hover / active / focus-visible), each a map of shortcuts: `step` (intensify the fill or text by n rungs — `bg-<role>-solid` → `-solid-bold`, `text-<role>` → `-bold`), `scale` (transform scale), `lift` (translateY + shadow), `shadow` (a shadow name → drop-shadow(var(--shadow-<name>)), or true → lift shadow), `ring` (focus ring), or raw `css` declarations. Hover rules are wrapped in `@media (hover: hover)`.',\n ),\n roles: desc(\n z.optional(z.array(z.string())),\n 'Semantic colour role variants to emit as `<pattern>-<role>` classes (fills use the role solid / on-solid tokens).',\n ),\n }),\n 'One component pattern (button, link, badge, card, …): base declarations + interaction states + semantic role variants, resolved through the pattern token cascade.',\n);\n\nconst Patterns = desc(\n z.strictObject({\n defaults: z.optional(\n desc(CssDecls, 'Cascade-wide fallback tokens, emitted as `--<prop>-default`.'),\n ),\n radii: z.optional(\n desc(CssDecls, 'Shape primitives, emitted as `--br-<name>` (referenced by pattern bases).'),\n ),\n groups: desc(\n z.optional(z.record(z.string(), CssDecls)),\n 'Group-level tokens, emitted as `--<prop>-<group>`; patterns opt in via their `group` key.',\n ),\n z: desc(z.optional(z.record(z.string(), z.number())), 'Z-index tiers → `--z-tier-<name>`.'),\n items: desc(\n z.optional(z.record(z.string(), Pattern)),\n 'The component patterns to emit, keyed by name.',\n ),\n }),\n 'Component patterns and their token cascade: `defaults` → `groups` → per-pattern `overrides`, plus shape (`radii`) and z-index primitives.',\n);\n\n// ── typography ──────────────────────────────────────────────────────────────\nconst TypographyRole = desc(\n z.record(z.string(), Scalar),\n 'A bag of CSS-ish keys, each mapped to a declaration plus a `--<role>-<sfx>` override hook. The recognised set is **closed**: `family`, `size`, `weight`, `style`, `line-height`, `tracking` (→ `letter-spacing`), `text-transform`, `text-decoration`, `text-wrap`, `color`. Note the last four are spelled with their full CSS property names — `transform` and `decoration` are NOT accepted. Anything unrecognised is **ignored**, not passed through, so the generator warns rather than emitting it: a silently-dropped `transform: uppercase` is how title-case navigation reaches production. Note also that `style`, `text-transform`, `text-decoration` and `text-wrap` are emitted on **every** role at their identity value (`normal`/`none`/`none`/`wrap`) whether declared or not, so applying one role class over another fully resets it — which means **omitting `text-wrap` is not \"inherit\"**: it emits `text-wrap: wrap` and cancels the `pretty` the role would otherwise inherit from a `pretty` ancestor such as a `body`-mapped role. Declare it on every role — `balance` for heading-like roles, `pretty` for copy, `wrap` for short single-line labels.',\n);\nconst Typography = desc(\n z.strictObject({\n families: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Role-facing family aliases → CSS font values, usually referencing the top-level `fonts` tokens (e.g. \"var(--font-display)\").',\n ),\n roles: desc(\n z.optional(z.record(z.string(), TypographyRole)),\n 'Semantic type roles (display, title, heading, body, quote, caption, eyebrow, code, lead, footnote, tag, …), each emitted as a `font-<role>` class.',\n ),\n headings: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Maps bare elements to type roles so unclassed markup picks up role styling — `{ \"h1\": \"display\", \"h2\": \"heading\" }`. The key is used verbatim as a selector, so it is not limited to h1…h6: **map `\"body\"` to your prose role** to bind base page typography to the role rather than hand-writing it. That binding is what makes the role editable — a stylesheet that re-states `font-family`/`line-height` as literals on `body` shadows `--<role>-ff`/`--<role>-lh`, and the live theme editor then appears to do nothing.',\n ),\n }),\n 'Typography: family aliases, semantic type roles (→ `font-<role>` classes), and the bare-element → role mapping.',\n);\n\n// ── animations ──────────────────────────────────────────────────────────────\nconst AnimEffect = desc(\n z.strictObject({\n kf: desc(\n z.string(),\n 'Keyframe family driving the effect: composite (transform/opacity), paint, or layout.',\n ),\n css: z.optional(desc(VarMap, 'Extra literal declarations merged into the effect class as-is.')),\n vars: z.optional(\n desc(\n VarMap,\n 'Effect endpoint variables (`--<key>: <value>`, e.g. opacity-from, translate-y-to) that override the keyframe defaults.',\n ),\n ),\n }),\n 'A named animation effect class — a pure value layer (`--_anim` + `--<prop>-from/-to`) over the static keyframe engine.',\n);\nconst Animations = desc(\n z.strictObject({\n effects: desc(\n z.optional(z.record(z.string(), AnimEffect)),\n 'Effect classes to emit (`.fade-in`, `.reveal-left`, …), keyed by class name.',\n ),\n journeys: desc(\n z.optional(\n z.strictObject({\n base: desc(\n z.optional(z.record(z.string(), VarMap)),\n 'Named journey building blocks: part name → var map.',\n ),\n compose: desc(\n z.optional(z.array(z.array(z.string()))),\n 'Combinations of base parts, each emitted as a `.<parts>-journey` class.',\n ),\n }),\n ),\n 'Multi-part journey classes composed from `base` building blocks.',\n ),\n }),\n 'Animation effect + journey classes (pure value layers). The animation engine itself — keyframes, drivers, floats, utilities — is static framework CSS, not configured here.',\n);\n\n// ── the design system ───────────────────────────────────────────────────────\nexport const DesignSystemSchema = z.strictObject({\n $schema: desc(\n z.optional(z.string()),\n 'URL of the published JSON Schema (stamped by `vitops init`) so editors provide autocomplete + validation.',\n ),\n meta: desc(\n z.optional(\n z.strictObject({\n name: desc(\n z.optional(z.string()),\n 'Brand/system name. Used as the `name` field and `<h1>` of the `design` format\\'s `DESIGN.md`. Defaults to \"Design System\".',\n ),\n description: desc(\n z.optional(z.string()),\n \"One or two sentences on the brand personality and the feeling the UI should evoke — what an agent needs when no token answers the question. Becomes the DESIGN.md `description` field and opens its Overview section; if omitted, a generic description of the system's mechanics is used instead.\",\n ),\n }),\n ),\n 'Brand identity for agent-facing output. Consumed only by the `design` format (`DESIGN.md`); it emits no CSS and no tokens.',\n ),\n colors: Colors,\n shadows: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Named shadows → `--shadow-<name>` tokens and `.drop-shadow-<name>` utilities. Values are shadow parameter lists (offset/blur/colour). Each token feeds two consumers with different grammars — `box-shadow` (pattern geometry, via the `--ds-*` group aliases) and `filter: drop-shadow(…)` (the utilities and the `shadow:` state shortcut) — so values must stay in the intersection: **one layer, no spread radius, no `inset`**. `drop-shadow()` rejects all three, and rejecting them invalidates the whole filter, so the shadow vanishes rather than degrading.',\n ),\n fonts: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Raw font stacks by name, emitted as `--font-<name>` tokens (referenced by `typography.families`). **Stacks only — vitops does not load webfonts.** A value here is a `font-family` list and nothing more: it emits no `@font-face`, no preload, and no metrics-matched fallback. If a family needs loading, declare it in Astro\\'s `fonts:` config (`astro.config`, or the site config\\'s `fonts` array) and point the token at the family\\'s `cssVariable` — `\"display\": \"var(--font-league-spartan), sans-serif\"`. Installing a `@fontsource*` package and importing its CSS also works but gives up subsetting, preload and `size-adjust`/`ascent-override` fallbacks, so it regresses CLS.',\n ),\n typeScale: desc(\n z.optional(Scale),\n 'Fluid modular TYPE scale → `--text-<name>` tokens, consumed by typography roles and text-size utilities.',\n ),\n spaceScale: desc(\n z.optional(Scale),\n 'Fluid modular SPACE scale → `--space-<name>` tokens, consumed by spacing/gap utilities and vertical rhythm.',\n ),\n patterns: z.optional(Patterns),\n typography: z.optional(Typography),\n animations: z.optional(Animations),\n});\n\nexport type DesignSystem = z.infer<typeof DesignSystemSchema>;\n\n// A deep-partial view used for theme deltas: an `extends` patch supplies only\n// what it overrides, so every field is optional — including one level down\n// through `colors` into palette / roles / utilities. Reuses the same leaf\n// schemas, so there's no second source of truth. Completeness is enforced after\n// merge (validate the resolved theme against `DesignSystemSchema`).\n//\n// Note this is NOT a per-appearance grammar. Light/dark is derived inside a\n// single design system by re-pointing which ramp step each token reads; the old\n// `schemes` layer this comment used to describe was removed with that redesign.\nconst ColorsPatch = z.strictObject({\n palette: z.optional(z.record(z.string(), Ramp)),\n roles: z.optional(z.record(z.string(), RoleSpecSchema)),\n utilities: z.optional(z.array(UtilityName)),\n});\nexport const DesignSystemPatchSchema = z.extend(z.partial(DesignSystemSchema), {\n colors: z.optional(ColorsPatch),\n});\nexport type DesignSystemPatch = z.infer<typeof DesignSystemPatchSchema>;\n\n/**\n * Stable URL of the published JSON Schema. Resolves once `@getvitops/generator` is on\n * npm (unpkg serves the packaged `schema.json`); `vitops init` stamps this into a\n * scaffolded config's `$schema` so editors light up autocomplete + validation.\n */\nexport const SCHEMA_URL = 'https://unpkg.com/@getvitops/generator/schema.json';\n\n/** The published JSON Schema (draft-2020-12), derived from the zod schema. */\nexport const jsonSchema = {\n $id: SCHEMA_URL,\n ...z.toJSONSchema(DesignSystemSchema, { target: 'draft-2020-12' }),\n};\n\n/** Split a CSS value on top-level commas, ignoring commas nested in `rgba(…)` etc. */\nconst splitLayers = (value: string): string[] => {\n const out: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < value.length; i++) {\n const c = value[i];\n if (c === '(') depth++;\n else if (c === ')') depth--;\n else if (c === ',' && depth === 0) {\n out.push(value.slice(start, i));\n start = i + 1;\n }\n }\n out.push(value.slice(start));\n return out.map((s) => s.trim()).filter(Boolean);\n};\n\nconst LENGTH = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(px|rem|em|ch|ex|vh|vw|vmin|vmax|cm|mm|in|pt|pc|q)?$/i;\n\n/**\n * Why a shadow can be *valid CSS* and still render nothing: a `--shadow-<name>`\n * token is consumed both as a `box-shadow` (pattern geometry) and inside\n * `filter: drop-shadow(…)` (the `.drop-shadow-<name>` utilities, the `shadow:`\n * state shortcut). `drop-shadow()` accepts a *single* layer of at most three\n * lengths and no `inset` — a spread radius, a second comma-separated layer or an\n * inset keyword makes the function invalid, which drops the entire `filter`\n * declaration. `box-shadow` accepts all three happily, so the value looks fine\n * everywhere it is authored and only the utility silently goes blank.\n */\nconst dropShadowIssue = (value: string): string | undefined => {\n const layers = splitLayers(value);\n if (layers.length > 1) return `${layers.length} comma-separated layers`;\n const layer = layers[0] ?? '';\n if (/(^|\\s)inset(\\s|$)/i.test(layer)) return 'an `inset` keyword';\n // Drop function calls (`rgb(0 0 0 / .5)`, `color-mix(…)`) so their numbers\n // aren't miscounted as lengths, then count what's left.\n const lengths = layer\n .replaceAll(/[\\w-]*\\([^()]*\\)/g, ' ')\n .split(/\\s+/)\n .filter((t) => LENGTH.test(t));\n if (lengths.length > 3) return `a spread radius (${lengths.length} lengths)`;\n return undefined;\n};\n\nexport type ValidationResult =\n | { ok: true; data: DesignSystem; errors: []; warnings: string[] }\n | { ok: false; data: undefined; errors: z.core.$ZodIssue[]; warnings: string[] };\n\nconst RAMP_KEYS = new Set(['seed', 'anchors', 'tones']);\n\n/**\n * Replace the bare \"Invalid input\" a failed union produces with the reason.\n *\n * `Ramp` is `SeededRamp | FixedRamp`, and both branches are closed — so `{ seed,\n * tones }` or a stray key fails *both* and zod reports only that the union didn't\n * match. That message sends you reading the schema rather than looking at the two\n * keys in front of you, and the config that produced it is one whose `tones` were\n * being silently discarded at generate time.\n */\nconst explainRamp =\n (input: unknown) =>\n (issue: z.core.$ZodIssue): z.core.$ZodIssue => {\n // A closed object reports the offending keys on the issue but renders them as\n // a bare \"Invalid input\", which names the parent and not the typo.\n if (issue.code === 'unrecognized_keys') {\n const keys = (issue as { keys?: string[] }).keys ?? [];\n if (keys.length)\n return {\n ...issue,\n message: `unknown key${keys.length > 1 ? 's' : ''} ${keys.map((k) => `\"${k}\"`).join(', ')} — not part of the schema, so ignored at generate time.`,\n };\n }\n if (issue.path.length !== 3 || issue.path[0] !== 'colors' || issue.path[1] !== 'palette')\n return issue;\n const hue = (input as { colors?: { palette?: Record<string, unknown> } })?.colors?.palette?.[\n String(issue.path[2])\n ];\n if (hue == null || typeof hue !== 'object') return issue;\n const keys = Object.keys(hue);\n const unknown = keys.filter((k) => !RAMP_KEYS.has(k));\n const message =\n 'seed' in hue && 'tones' in hue\n ? 'a hue is either seeded (`seed`, with optional `anchors`) or fixed (`tones`) — not both. ' +\n 'Drop one: with both present the `tones` are ignored at generate time.'\n : unknown.length\n ? `unknown key${unknown.length > 1 ? 's' : ''} ${unknown.map((k) => `\"${k}\"`).join(', ')}. ` +\n 'A hue takes `seed` + optional `anchors`, or `tones`.'\n : keys.length === 0\n ? 'a hue needs `seed` (+ optional `anchors`) or `tones`.'\n : null;\n return message ? { ...issue, message } : issue;\n };\n\n/**\n * Validate an unknown value against the design-system schema.\n *\n * `warnings` are configurations that parse and generate, but produce output that\n * won't behave as authored — currently only the token-namespace collisions the\n * flat `--<prop>-<name>` grammar makes possible.\n */\nexport function validate(input: unknown): ValidationResult {\n const result = z.safeParse(DesignSystemSchema, input);\n if (!result.success)\n return {\n ok: false,\n data: undefined,\n errors: result.error.issues.map(explainRamp(input)),\n warnings: [],\n };\n // Every role must point at a palette hue that exists.\n const { palette, roles } = result.data.colors;\n for (const [role, spec] of Object.entries(roles)) {\n const hue = roleHue(spec as RoleSpec);\n if (palette[hue] == null) {\n return {\n ok: false,\n data: undefined,\n errors: [\n {\n code: 'custom',\n path: ['colors', 'roles', role],\n message: `role \"${role}\" references unknown palette hue \"${hue}\"`,\n } as z.core.$ZodIssue,\n ],\n warnings: [],\n };\n }\n }\n const warnings: string[] = [];\n // Role names are arbitrary — but the shipped component CSS is written against\n // a core set, and references them with no fallback. Omitting one doesn't fail\n // validation (the tokens for the roles you DO define are all emitted fine); it\n // silently strips colour from whichever components depended on it, which is\n // far harder to diagnose than a warning here.\n const missing = REQUIRED_ROLES.filter((r) => roles[r] == null);\n if (missing.length)\n warnings.push(\n `colors.roles is missing ${missing.map((r) => `\"${r}\"`).join(', ')} — ` +\n `the framework's own component CSS references ${missing.length === 1 ? 'it' : 'them'} ` +\n `with no fallback, so those components will render uncoloured. ` +\n `Add any role you like, but keep these defined.`,\n );\n // A radius named after a pattern collides on `--br-<name>`: the radius token and\n // the pattern's own override hook are the same var, so whichever the generator\n // emits last silently wins. Same class of clash as a pattern keyed like its\n // group (see the `tag`/`label` note in AGENTS.md). The pattern hook takes it.\n const radii = Object.keys(result.data.patterns?.radii ?? {});\n const items = new Set(Object.keys(result.data.patterns?.items ?? {}));\n for (const name of radii)\n if (items.has(name))\n warnings.push(\n `patterns.radii.${name} collides with the \"${name}\" pattern on --br-${name}; ` +\n `the pattern's override hook wins — rename the radius`,\n );\n for (const [name, value] of Object.entries(result.data.shadows ?? {})) {\n const issue = dropShadowIssue(value);\n if (issue)\n warnings.push(\n `shadows.${name} carries ${issue}, which \\`filter: drop-shadow()\\` rejects — ` +\n `\\`.drop-shadow-${name}\\` will render no shadow at all (the token still works ` +\n `as a \\`box-shadow\\`). Use one layer of at most three lengths.`,\n );\n }\n return { ok: true, data: result.data, errors: [], warnings };\n}\n","/**\n * The top-level configuration schema — the umbrella around a\n * `design-system.json`-compliant `designSystem`.\n *\n * **Three sections, one document.** A config is `{ designSystem, organization,\n * site }`:\n *\n * - `designSystem` — the token set (named themes + which theme/appearance).\n * - `organization` — the company: who it is, where it is, how to reach it, what\n * it sells. Facts that stay true if the site is rebuilt from scratch.\n * - `site` — this published site: locales, domains, environments, SEO,\n * analytics, legal, icons, deployment. Facts about *a* presentation of the\n * organization.\n *\n * The split is not cosmetic. The flat predecessor (`SiteConfig`) held the company\n * and the deployment as peers, so no single noun described it — and the\n * multi-site case was inexpressible. With three sections, several sites can share\n * one `organization` and override only `site`.\n *\n * Authored with `zod/mini` (same instance the design-system schema uses), so the\n * two compose: `DesignSystemSchema` is embedded as `designSystem.themes.<theme>` and the\n * whole thing serialises to one JSON Schema via `z.toJSONSchema`. Everything a\n * generator needs derives from here: the `Config` type (`z.infer`), the\n * published JSON Schema (`configJsonSchema`), and runtime validation (`validateConfig`).\n *\n * Pure: no YAML/env/fs. `resolveConfig` takes an already-parsed object; a\n * thin loader (reading YAML, injecting `SITE_ENV`) lives outside this module.\n */\nimport * as z from 'zod/mini';\nimport { desc, DesignSystemPatchSchema, type DesignSystem } from './schema.ts';\n\n// ── Primitives ────────────────────────────────────────────────────────────────\n\nconst LocalizableSchema = desc(\n z.union([z.string(), z.record(z.string(), z.string())]),\n 'A string, or a per-locale map of strings (`{ en: \"…\", fr: \"…\" }`).',\n);\n\nconst ImageRefSchema = z.union([\n z.string(),\n z.object({\n src: z.string(),\n alt: z.string(),\n width: z.optional(z.number()),\n height: z.optional(z.number()),\n }),\n]);\n\n// Attribute bags on generated HTML — constrained to serialisable scalars so the\n// exported JSON Schema still offers validation (vs. an opaque `unknown`).\nconst AttrValue = z.union([z.string(), z.number(), z.boolean()]);\nconst AttrsSchema = z.optional(z.record(z.string(), AttrValue));\n\nconst IsoDate = z.string().check(z.regex(/^\\d{4}-\\d{2}-\\d{2}$/)); // YYYY-MM-DD\nconst Iso4217 = z.string().check(z.regex(/^[A-Z]{3}$/)); // currency code\nconst DayOfWeek = z.enum([\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday',\n 'Sunday',\n]);\n\n// ── Design system ───────────────────────────────────────────────────────────────\n// Each `themes` entry is a full `DesignSystem` plus a localised `displayName` and\n// an optional `extends` (another entry's key). Entries are lenient (all top-level\n// fields optional) so an extending entry can be a partial patch; the resolved\n// theme is validated against the full `DesignSystemSchema` by `resolveTheme`.\n\nconst DesignSystemEntry = z.extend(DesignSystemPatchSchema, {\n displayName: desc(\n z.optional(LocalizableSchema),\n 'Human-readable theme name (localisable). The label a theme picker would show — nothing reads it yet, because nothing builds more than one theme (see `themes`).',\n ),\n extends: desc(\n z.optional(z.string()),\n 'Another `themes` key to inherit from; this entry then only supplies what it overrides.',\n ),\n});\n\n/**\n * The design system as a whole: the named themes plus the facts that describe the\n * system rather than any one theme.\n *\n * `themes` is nested rather than being the block itself because the block used to\n * BE the map — every key was a theme name, so there was nowhere to put\n * system-wide metadata without it colliding with a theme of that name.\n *\n * Note the two axes here are independent, and deliberately so. `defaultTheme`\n * picks a *theme* (an authored design system); `defaultColorScheme` picks an\n * *appearance* (light/dark), which every theme already has because the flip is\n * derived from one ramp rather than authored. \"Theme `elegant`, appearance\n * follows the OS\" has to be sayable, and a single union could not express it.\n */\nconst DesignSystemBlock = desc(\n z.strictObject({\n themes: desc(\n z.record(z.string(), DesignSystemEntry),\n 'Named themes. `default` is the base; others may `extends` another and supply a partial patch. Light/dark is NOT a theme — the functional tokens flip per appearance within each one, so `default` already has both. Only the default theme is built today; multi-theme output and a picker are not wired yet.',\n ),\n defaultTheme: desc(\n z.optional(z.string()),\n 'Which `themes` entry to use (convention: \"default\"). Validated against the map; selecting a non-default theme is not wired yet.',\n ),\n defaultColorScheme: desc(\n z.optional(z.enum(['light', 'dark', 'system'])),\n 'Initial appearance. `\"system\"` follows the OS via `prefers-color-scheme` and is what makes `<color-scheme-toggle>`\\'s \"System\" position resolve to anything — it removes the theme attribute, so without this the page falls through to light. It also gives a no-JS page the OS appearance. Defaults to `\"light\"`, because switching an existing site to `\"system\"` visibly flips it dark for dark-OS visitors.',\n ),\n }),\n 'The design system: named themes plus the system-wide facts (which theme, which appearance). A bare design system, or a bare theme map, is accepted as shorthand for `{ themes: … }`.',\n);\n\n// ── Locales ─────────────────────────────────────────────────────────────────────\n\nconst LocaleSchema = z.object({\n name: desc(z.string(), 'Display name of the locale (e.g. \"English\").'),\n tagline: desc(z.optional(z.string()), 'Site tagline in this locale.'),\n basePath: desc(z.optional(z.string()), 'URL prefix for this locale (e.g. \"/fr\").'),\n});\n\n// ── Domains ─────────────────────────────────────────────────────────────────────\n\nconst HttpRedirect = z.union([z.literal(301), z.literal(302), z.literal(307), z.literal(308)]);\n\nconst DomainAliasSchema = z.object({\n domain: z.string(),\n redirectType: HttpRedirect,\n redirectTo: z.string(),\n environment: z.optional(z.string()),\n});\n\n// ── Contact / address (schema.org-aligned) ──────────────────────────────────────\n\nconst PostalAddressSchema = desc(\n z.object({\n streetAddress: z.string(),\n addressLocality: desc(z.string(), 'City.'),\n addressRegion: desc(z.optional(z.string()), 'State / province.'),\n postalCode: z.optional(z.string()),\n addressCountry: desc(z.string(), 'Country (ISO 3166-1 alpha-2 preferred).'),\n }),\n 'schema.org `PostalAddress` field names, so JSON-LD generation is lossless.',\n);\n\nconst ContactObjectSchema = z.object({\n name: z.optional(z.string()),\n email: z.optional(z.email()),\n phone: z.optional(z.string()),\n address: z.optional(PostalAddressSchema),\n});\n\n// contact is either a string (location key reference) or an inline object\nconst ContactConfigSchema = z.union([z.string(), ContactObjectSchema]);\n\nexport type PostalAddress = z.infer<typeof PostalAddressSchema>;\nexport type ContactObject = z.infer<typeof ContactObjectSchema>;\n\n// ── Locations (schema.org LocalBusiness) ────────────────────────────────────────\n\nconst GeoSchema = z.object({\n latitude: z.number().check(z.gte(-90), z.lte(90)),\n longitude: z.number().check(z.gte(-180), z.lte(180)),\n});\n\n/** schema.org `OpeningHoursSpecification` — per-day open/close (24h `HH:MM`). */\nconst OpeningHoursSchema = z.object({\n dayOfWeek: z.array(DayOfWeek),\n opens: z.string().check(z.regex(/^\\d{2}:\\d{2}$/)),\n closes: z.string().check(z.regex(/^\\d{2}:\\d{2}$/)),\n});\n\n// Common schema.org LocalBusiness subtypes (extend as needed).\nconst LocalBusinessType = z.enum([\n 'LocalBusiness',\n 'Store',\n 'Restaurant',\n 'CafeOrCoffeeShop',\n 'ProfessionalService',\n 'MedicalBusiness',\n 'HealthAndBeautyBusiness',\n 'HomeAndConstructionBusiness',\n 'AutomotiveBusiness',\n 'FinancialService',\n 'LegalService',\n 'RealEstateAgent',\n 'Organization',\n]);\n\nconst LocationSchema = z.object({\n slug: z.optional(LocalizableSchema),\n name: LocalizableSchema,\n email: z.optional(z.email()),\n phone: z.optional(z.string()),\n address: z.optional(PostalAddressSchema),\n geo: z.optional(GeoSchema),\n hours: z.optional(z.array(OpeningHoursSchema)),\n type: z.optional(LocalBusinessType),\n description: z.optional(LocalizableSchema),\n areaServed: z.optional(z.array(z.string())),\n priceRange: z.optional(z.string()),\n paymentAccepted: z.optional(z.array(z.string())),\n currenciesAccepted: z.optional(Iso4217),\n knowsLanguage: z.optional(z.array(z.string())),\n});\n\n// ── Organization (schema.org Organization) ──────────────────────────────────────\n\nconst OrganizationSchema = z.object({\n name: desc(\n z.optional(LocalizableSchema),\n 'Trading name, as a reader would recognise it (e.g. \"Acme\"). Localisable.',\n ),\n legalName: desc(\n z.optional(z.string()),\n 'Registered legal name (e.g. \"Acme Widgets Inc.\"). The generated legal documents prefer this over `name` — a policy is a statement by the legal entity.',\n ),\n foundingDate: desc(z.optional(IsoDate), 'Date the organization was founded (YYYY-MM-DD).'),\n logo: desc(z.optional(ImageRefSchema), 'Organization logo → JSON-LD `logo`.'),\n email: desc(\n z.optional(z.email()),\n 'General contact address. Also the last fallback for privacy requests — see `contact`.',\n ),\n phone: desc(z.optional(z.string()), 'General contact telephone number.'),\n address: desc(\n z.optional(PostalAddressSchema),\n 'Registered/mailing address. Its `addressRegion` and `addressCountry` are what the governing-law clause of the generated terms of service defaults to.',\n ),\n taxID: desc(z.optional(z.string()), 'Tax identification number.'),\n vatID: desc(z.optional(z.string()), 'VAT identification number.'),\n sameAs: desc(z.optional(z.array(z.url())), 'Profile URLs → JSON-LD `sameAs` (mirrors `links`).'),\n});\n\n// ── DNS ──────────────────────────────────────────────────────────────────────\n\nconst DnsRecordType = z.enum(['A', 'AAAA', 'CNAME', 'TXT', 'MX', 'NS', 'SRV', 'CAA', 'PTR', 'SOA']);\n\nconst DnsRecordSchema = z.object({\n type: DnsRecordType,\n name: z.optional(z.string()),\n value: z.string(),\n ttl: z.optional(z.number().check(z.int(), z.positive())),\n proxied: z.optional(z.boolean()),\n});\n\nconst DnsDomainSchema = z.object({\n provider: z.optional(z.string()),\n nameservers: z.optional(z.array(z.string())),\n records: z.optional(z.array(DnsRecordSchema)),\n});\n\n// ── Environments ──────────────────────────────────────────────────────────────\n\nconst RobotsSchema = z.string(); // e.g. \"index,follow\" / \"noindex,nofollow\"\n\nconst EnvironmentSchema = z.object({\n url: desc(z.url(), 'Public origin of this environment.'),\n api: desc(z.optional(z.url()), 'API origin, when different from `url`.'),\n analytics: desc(z.optional(z.boolean()), 'Whether analytics fire in this environment.'),\n robots: desc(z.optional(RobotsSchema), 'Robots policy (e.g. \"noindex,nofollow\" for dev).'),\n variant: desc(z.optional(z.string()), 'Active `abTesting.variants` key for this environment.'),\n});\n\n// ── A/B testing ─────────────────────────────────────────────────────────────────\n\nconst AbVariantSchema = z.object({\n environment: z.string(),\n description: z.optional(z.string()),\n // Deliberate escape hatch: overrides are deep-merged into the raw config\n // before validation, so their shape is the config's own.\n overrides: z.optional(z.record(z.string(), z.unknown())),\n});\n\n// ── Fonts (Astro Fonts API projection) ──────────────────────────────────────────\n// Font *loading* — a serialisable projection of Astro's `fonts:[…]` config. A\n// loader maps `provider` (string) → `fontProviders.<name>()`. Distinct from the\n// design-system font *tokens* (`designSystem.themes.<theme>.fonts` / typography.families),\n// which reference the same `cssVariable`.\n\nconst FontProvider = z.enum([\n 'google',\n 'fontsource',\n 'adobe',\n 'bunny',\n 'fontshare',\n 'googleicons',\n 'npm',\n 'local',\n]);\nconst FontStyle = z.enum(['normal', 'italic']);\nconst FontDisplay = z.enum(['auto', 'block', 'swap', 'fallback', 'optional']);\nconst FontWeight = z.union([z.number(), z.string()]); // discrete, or a variable range like \"100 900\"\n\n/** A local-font face (`provider: 'local'`). */\nconst FontVariantSchema = z.object({\n src: z.array(z.string()),\n weight: z.optional(FontWeight),\n style: z.optional(FontStyle),\n unicodeRange: z.optional(z.array(z.string())),\n display: z.optional(FontDisplay),\n});\n\nexport const SiteFontSchema = z.object({\n name: z.string(),\n provider: FontProvider,\n cssVariable: z.string().check(z.regex(/^--/)),\n weights: z.optional(z.array(FontWeight)),\n styles: z.optional(z.array(FontStyle)),\n subsets: z.optional(z.array(z.string())),\n fallbacks: z.optional(z.array(z.string())),\n optimizedFallbacks: z.optional(z.boolean()),\n display: z.optional(FontDisplay),\n formats: z.optional(z.array(z.string())),\n unicodeRange: z.optional(z.array(z.string())),\n variants: z.optional(z.array(FontVariantSchema)), // local provider\n preload: desc(\n z.optional(\n z.union([\n z.boolean(),\n z.array(z.object({ weight: FontWeight, style: z.optional(FontStyle) })),\n ]),\n ),\n 'Emit `<Font preload />` for this family (true, or a list of weight/style faces).',\n ),\n});\n\n// ── Templates (nav / form / nodes) ──────────────────────────────────────────────\n\nconst PresentSchema = z.optional(z.record(z.string(), z.unknown()));\n\nconst NavItemSchema: z.ZodMiniType = z.object({\n label: z.optional(LocalizableSchema),\n image: z.optional(ImageRefSchema),\n href: z.optional(z.string()),\n icon: z.optional(z.string()),\n attrs: AttrsSchema,\n itemAttrs: AttrsSchema,\n submenu: z.optional(\n z.object({\n present: PresentSchema,\n get items() {\n return z.optional(z.array(NavItemSchema));\n },\n }),\n ),\n});\n\nconst FormFieldType = z.enum([\n 'text',\n 'email',\n 'tel',\n 'url',\n 'number',\n 'password',\n 'textarea',\n 'select',\n 'checkbox',\n 'radio',\n 'date',\n 'file',\n 'hidden',\n]);\n\nconst FormFieldSchema = z.object({\n name: z.string(),\n type: FormFieldType,\n label: z.optional(LocalizableSchema),\n required: z.optional(z.boolean()),\n validation: z.optional(z.string()), // regex source or named rule\n options: z.optional(\n z.union([z.string(), z.array(z.object({ label: z.string(), value: z.string() }))]),\n ),\n attrs: AttrsSchema,\n});\n\nconst ContentNodeSchema: z.ZodMiniType = z.object({\n tag: z.string(),\n attrs: AttrsSchema,\n text: z.optional(z.string()),\n get children() {\n return z.optional(z.array(ContentNodeSchema));\n },\n});\n\nconst TemplateSchema = z.union([\n z.object({\n type: z.literal('nav'),\n tags: z.optional(z.array(z.string())),\n present: PresentSchema,\n items: z.optional(z.array(NavItemSchema)),\n }),\n z.object({\n type: z.literal('form'),\n tags: z.optional(z.array(z.string())),\n present: PresentSchema,\n action: z.optional(z.string()),\n method: z.optional(z.enum(['get', 'post'])),\n fields: z.optional(z.array(FormFieldSchema)),\n submit: z.optional(z.record(z.string(), AttrValue)),\n honeypot: z.optional(z.boolean()),\n }),\n z.object({\n type: z.literal('nodes'),\n tags: z.optional(z.array(z.string())),\n nodes: z.optional(z.array(ContentNodeSchema)),\n }),\n]);\n\n// ── Galleries / testimonials ────────────────────────────────────────────────────\n\nconst GalleryImageSchema = z.object({\n src: z.string(),\n alt: LocalizableSchema,\n caption: z.optional(LocalizableSchema),\n});\n\nconst GallerySchema = z.object({\n title: z.optional(LocalizableSchema),\n tags: z.optional(z.array(z.string())),\n images: z.array(GalleryImageSchema),\n});\n\nconst TestimonialItemSchema = z.object({\n quote: LocalizableSchema,\n name: z.string(),\n role: z.optional(z.string()),\n rating: z.optional(z.number().check(z.gte(0), z.lte(5))),\n date: z.optional(IsoDate),\n});\n\nconst TestimonialGroupSchema = z.object({\n title: z.optional(LocalizableSchema),\n items: z.array(TestimonialItemSchema),\n});\n\n// ── Services (schema.org Offer) ─────────────────────────────────────────────────\n\nconst OfferSchema = z.object({\n name: z.optional(LocalizableSchema),\n price: z.optional(z.union([z.string(), z.number()])),\n priceCurrency: z.optional(Iso4217),\n availability: z.optional(z.string()),\n url: z.optional(z.url()),\n validFrom: z.optional(IsoDate),\n priceValidUntil: z.optional(IsoDate),\n});\n\nconst ServiceSchema = z.object({\n name: LocalizableSchema,\n description: z.optional(LocalizableSchema),\n slug: z.optional(LocalizableSchema),\n offers: z.optional(z.array(OfferSchema)),\n});\n\n// ── SEO / social ─────────────────────────────────────────────────────────────\n\nconst OpenGraphSchema = z.object({\n type: z.optional(z.string()),\n siteName: z.optional(z.string()),\n title: z.optional(LocalizableSchema),\n description: z.optional(LocalizableSchema),\n image: z.optional(ImageRefSchema),\n locale: z.optional(z.string()),\n});\n\nconst TwitterSchema = z.object({\n card: z.optional(z.enum(['summary', 'summary_large_image', 'app', 'player'])),\n site: z.optional(z.string()),\n creator: z.optional(z.string()),\n title: z.optional(LocalizableSchema),\n description: z.optional(LocalizableSchema),\n image: z.optional(ImageRefSchema),\n});\n\n// ── Indexing ────────────────────────────────────────────────────────────────────\n\n/**\n * What `vitops notify` needs to tell search engines a deploy happened.\n *\n * Scoped by what search engines actually accept, which is narrower than it looks:\n * Google exposes **no** \"request indexing\" API (the Search Console button is not in\n * its API, and URL Inspection is read-only), and it removed the sitemap ping\n * endpoint in 2023. So the sanctioned set is: an accurate sitemap, a Search Console\n * sitemap resubmit, an IndexNow ping — which Google does *not* honour but Bing,\n * Yandex, Naver, Seznam and Yep do — and a read-only inspection pass to find out\n * what Google actually did.\n *\n * Facts only, the same rule the legal block follows: this records what the site has\n * (a key, a property, which pages matter), never what to say about it.\n */\nconst IndexNowSchema = z.object({\n key: desc(\n z.string().check(z.regex(/^[a-zA-Z0-9-]{8,128}$/)),\n 'IndexNow key (8–128 chars, hex is conventional). NOT a secret — it is served publicly at `keyLocation` so the engine can verify you own the host. Generate one with `vitops notify --new-key`.',\n ),\n keyLocation: desc(\n z.optional(z.url()),\n 'Absolute URL of the key file. Defaults to `<canonical>/<key>.txt`; set it only when the file lives elsewhere.',\n ),\n endpoint: desc(\n z.optional(z.url()),\n 'IndexNow endpoint (default `https://api.indexnow.org/indexnow`). Any participating engine shares submissions with the rest, so one is normally enough.',\n ),\n});\n\nconst SearchConsoleSchema = z.object({\n siteUrl: desc(\n z.string(),\n 'The property exactly as Search Console identifies it — `sc-domain:acme.ca` for a domain property, or the URL-prefix form `https://acme.ca/`. A mismatch here is a 403, not a \"not found\".',\n ),\n resubmitSitemap: desc(\n z.optional(z.boolean()),\n 'Re-submit the sitemap through the Search Console API on each notify (default true when `searchConsole` is set). This is the automated equivalent of the manual resubmit in the UI.',\n ),\n});\n\nconst IndexingSchema = z.object({\n sitemapUrl: desc(\n z.optional(z.url()),\n 'The sitemap to submit and to diff for changed URLs. Defaults to `<canonical>/sitemap-index.xml`.',\n ),\n indexNow: desc(\n z.optional(IndexNowSchema),\n 'IndexNow submission (Bing, Yandex, Naver, Seznam, Yep — not Google). Omit to skip the channel.',\n ),\n searchConsole: desc(\n z.optional(SearchConsoleSchema),\n 'Google Search Console property. Needs a service-account credential in `VITOPS_GSC_SERVICE_ACCOUNT` or `GOOGLE_APPLICATION_CREDENTIALS` at run time — never put the key in this file.',\n ),\n priorityUrls: desc(\n z.optional(z.array(z.url())),\n 'The pages whose indexing actually matters. `vitops notify --check` inspects these and exits non-zero if Google has not indexed one. Kept explicit because URL Inspection is quota-bound (2000/day), so checking every page is neither affordable nor informative.',\n ),\n});\n\n// ── Legal ───────────────────────────────────────────────────────────────────────\n\n/**\n * Which template set the generated legal documents are written against. This is\n * a closed enum rather than a free string because an unrecognised value would\n * otherwise silently fall back to the wrong body of law; `validateConfig` rejects\n * anything without a registered template. Add a member here and a matching entry\n * in `legal/templates/index.ts` — the two are checked against each other.\n */\nexport const JURISDICTIONS = ['ca'] as const;\nconst JurisdictionSchema = z.enum(JURISDICTIONS);\nexport type Jurisdiction = (typeof JURISDICTIONS)[number];\n\n/**\n * A third party that receives personal information. The generator derives the\n * ones it can see (analytics IDs, Turnstile, the deploy platform); this is for\n * the rest, which no other part of the config implies.\n *\n * Deliberately facts, not prose: the config records *what is true*, the template\n * owns *how it is said*. That keeps a policy correct when the wording changes.\n */\nconst ProcessorSchema = z.object({\n name: desc(z.string(), 'The provider, as a reader would recognise it (e.g. \"Stripe\").'),\n purpose: desc(\n z.string(),\n 'Why they receive it, as a noun phrase that reads after \"for\" (e.g. \"payment processing\").',\n ),\n country: desc(\n z.optional(z.string()),\n 'Where they process it, as it should read in a sentence (e.g. \"the United States\"). Feeds the cross-border-transfer disclosure.',\n ),\n privacyUrl: z.optional(z.url()),\n});\n\n// ── The `site` section ──────────────────────────────────────────────────────────\n// This published site: where it lives, what it says, how it is built. Everything\n// here is a fact about a *presentation* of the organization — swap the site and\n// these change while `organization` does not.\n\nconst SiteSectionSchema = z.object({\n defaultLocale: desc(\n z.string(),\n 'The locale used when none is specified; must be a `locales` key.',\n ),\n locales: desc(\n z.record(z.string(), LocaleSchema),\n 'Locales the site is published in, keyed by BCP 47 tag (e.g. \"en\", \"fr\").',\n ),\n domains: desc(\n z.optional(\n z.object({\n canonical: desc(z.url(), 'The canonical origin used for absolute URLs and SEO.'),\n aliases: desc(\n z.optional(z.array(DomainAliasSchema)),\n 'Alias domains and how they redirect to the canonical one.',\n ),\n }),\n ),\n 'Canonical domain + redirecting aliases.',\n ),\n dns: desc(\n z.optional(z.record(z.string(), DnsDomainSchema)),\n 'Desired DNS state per domain (provider, nameservers, records) — declarative reference, not applied automatically.',\n ),\n cloudflare: desc(\n z.optional(z.record(z.string(), z.unknown())),\n 'Deliberate escape hatch for provider-specific Cloudflare settings — out of scope to model here.',\n ),\n environments: desc(\n z.record(z.string(), EnvironmentSchema),\n 'Deploy environments (production, dev, …): URL, API origin, analytics toggle, robots policy, active A/B variant.',\n ),\n abTesting: desc(\n z.optional(\n z.object({\n enabled: z.boolean(),\n cookieName: z.optional(z.string()),\n cookieMaxAge: desc(z.optional(z.number().check(z.int(), z.positive())), 'Seconds.'),\n splitRatio: desc(\n z.optional(z.number().check(z.gte(0), z.lte(1))),\n 'Fraction of traffic sent to the variant (0–1).',\n ),\n variants: desc(\n z.optional(z.record(z.string(), AbVariantSchema)),\n 'Named variants; each targets an environment and may deep-merge config `overrides`.',\n ),\n }),\n ),\n 'A/B testing: cookie-based split plus named variants whose `overrides` patch the config per environment.',\n ),\n fonts: desc(\n z.optional(z.array(SiteFontSchema)),\n 'Font LOADING (a serialisable projection of the Astro Fonts API: provider, weights, subsets, preload). Font TOKENS live in `designSystem.themes.<theme>.fonts` and reference the same `cssVariable`.',\n ),\n\n tags: desc(\n z.optional(z.record(z.string(), z.unknown())),\n 'Free-form content-tag taxonomy (site-specific; not interpreted by the generator).',\n ),\n postTypes: desc(\n z.optional(z.record(z.string(), z.unknown())),\n 'Free-form content-type definitions (site-specific; not interpreted by the generator).',\n ),\n galleries: desc(\n z.optional(z.record(z.string(), GallerySchema)),\n 'Named image galleries (title, tags, images with localisable alt/caption).',\n ),\n testimonials: desc(\n z.optional(z.record(z.string(), TestimonialGroupSchema)),\n 'Named testimonial groups (quote, name, role, rating, date).',\n ),\n templates: desc(\n z.optional(z.record(z.string(), TemplateSchema)),\n 'Named content templates rendered at SSR time: `nav` (menu trees), `form` (field lists + submit), or `nodes` (raw element trees).',\n ),\n navigation: desc(\n z.optional(\n z.object({\n activeTemplate: desc(\n z.optional(\n z.object({\n default: desc(z.optional(z.string()), 'A `templates` key.'),\n breakpoints: desc(\n z.optional(z.record(z.string(), z.string())),\n 'Breakpoint name → `templates` key overrides.',\n ),\n }),\n ),\n 'Which nav template is active, optionally per breakpoint.',\n ),\n }),\n ),\n 'Site navigation settings (which nav template renders where).',\n ),\n seo: desc(\n z.optional(\n z.object({\n titleTemplate: desc(z.optional(z.string()), 'Page-title pattern (e.g. \"%s · Acme\").'),\n descriptionTemplate: z.optional(z.string()),\n robots: desc(z.optional(RobotsSchema), 'e.g. \"index,follow\" / \"noindex,nofollow\".'),\n googleSiteVerification: z.optional(z.string()),\n bingSiteVerification: z.optional(z.string()),\n openGraph: z.optional(OpenGraphSchema),\n twitter: z.optional(TwitterSchema),\n indexing: desc(\n z.optional(IndexingSchema),\n 'How `vitops notify` tells search engines about a deploy: which sitemap, IndexNow key, Search Console property, and which pages to verify afterwards.',\n ),\n }),\n ),\n 'SEO defaults: title/description templates, robots policy, verification tokens, Open Graph + Twitter cards, and post-deploy indexing notification.',\n ),\n analytics: desc(\n z.optional(\n z.object({\n googleAnalyticsId: z.optional(z.string()),\n plausibleDomain: z.optional(z.string()),\n googleTagManagerId: z.optional(z.string()),\n clarityId: desc(z.optional(z.string()), 'Microsoft Clarity project ID.'),\n matomo: desc(\n z.optional(\n z.object({\n url: desc(z.string(), 'Instance base URL (self-hosted, or `*.matomo.cloud`).'),\n siteId: desc(z.string(), 'Site ID within that instance.'),\n cookies: desc(\n z.optional(z.boolean()),\n 'Default false — Matomo runs cookieless (`disableCookies`), which is what lets the cookie notice state positively that it sets none.',\n ),\n }),\n ),\n 'Matomo instance.',\n ),\n }),\n ),\n 'Analytics provider IDs (gated per environment via `environments.<env>.analytics`). Which provider is set is also what the generated privacy policy and cookie notice disclose — see `legal`.',\n ),\n notifications: desc(\n z.optional(z.object({ email: z.optional(z.email()) })),\n 'Where site notifications (e.g. form submissions) are sent.',\n ),\n tracking: desc(\n z.optional(\n z.object({\n enabled: z.optional(z.boolean()),\n platforms: z.optional(z.array(z.string())),\n }),\n ),\n 'Marketing/conversion tracking toggles per platform.',\n ),\n security: desc(\n z.optional(\n z.object({\n turnstile: z.optional(\n z.object({\n siteKey: desc(z.optional(z.string()), 'Cloudflare Turnstile site key (public).'),\n }),\n ),\n }),\n ),\n 'Security integrations (bot protection).',\n ),\n legal: desc(\n z.optional(\n z.object({\n jurisdiction: desc(\n z.optional(JurisdictionSchema),\n 'Which legal template set the generated documents use. Default `ca`.',\n ),\n privacyPolicy: z.optional(\n z.object({\n enabled: z.boolean(),\n url: z.optional(z.url()),\n lastUpdated: z.optional(IsoDate),\n privacyOfficer: desc(\n z.optional(ContactConfigSchema),\n 'Who privacy requests go to. Falls back to `contact`, then `primaryLocation`.',\n ),\n retention: desc(\n z.optional(z.string()),\n 'How long personal information is kept, in prose (e.g. \"24 months after last contact\").',\n ),\n processors: desc(\n z.optional(z.array(ProcessorSchema)),\n 'Third parties that receive personal information and cannot be inferred from the rest of the config (payment processors, CRMs, mail senders). Known providers implied by `analytics`, `security` and `deployment` are added automatically — list only the rest.',\n ),\n }),\n ),\n termsOfService: z.optional(\n z.object({\n enabled: z.boolean(),\n url: z.optional(z.url()),\n lastUpdated: z.optional(z.nullable(IsoDate)),\n governingLaw: desc(\n z.optional(z.string()),\n 'Governing-law clause, in prose (e.g. \"the Province of Ontario\"). Defaults from the contact address.',\n ),\n }),\n ),\n cookieConsent: z.optional(\n z.object({\n enabled: z.boolean(),\n type: desc(z.optional(z.enum(['opt-in', 'opt-out'])), 'Consent model.'),\n position: z.optional(z.enum(['top', 'bottom', 'center'])),\n categories: z.optional(z.array(z.string())),\n }),\n ),\n }),\n ),\n 'Legal pages: which documents exist, where they live, and the facts the generated prose asserts.',\n ),\n icons: desc(\n z.optional(\n // LOOSE on purpose. The per-set keys below are the sets `iconMap` knows\n // semantically, but the value shape is \"any iconify collection name → a\n // list of icons\", which is open-ended by definition. A closed object\n // silently DROPPED unlisted collections (`icons: { ph: [...] }` vanished\n // in validateConfig with no error) while `generateIconInclude`'s parameter\n // type advertised `[prefix: string]` — so the config validated, the icons\n // never bundled, and the failure only showed as missing glyphs in prod.\n z.looseObject({\n ui: desc(z.optional(z.string()), 'Icon set used for UI chrome (e.g. \"lucide\", \"ph\").'),\n brand: desc(z.optional(z.string()), 'Icon set used for brand marks.'),\n weight: desc(\n z.optional(z.string()),\n 'Weight for suffix-weighted sets like Phosphor (\"regular\" | \"bold\" | \"duotone\" | \"fill\" | \"light\" | \"thin\"). Ignored by sets that split weights across collections, e.g. Font Awesome.',\n ),\n sprite: desc(\n z.optional(z.boolean()),\n 'Emit an SVG sprite (icons.svg) alongside the stylesheet, for consumers that cannot run an icon integration (Bricks/WordPress, EmDash renderers).',\n ),\n semantic: desc(z.optional(z.array(z.string())), 'Named semantic icons to include.'),\n 'fa7-solid': z.optional(z.array(z.string())),\n 'fa7-regular': z.optional(z.array(z.string())),\n 'fa7-light': z.optional(z.array(z.string())),\n 'fa7-thin': z.optional(z.array(z.string())),\n 'fa7-brands': z.optional(z.array(z.string())),\n 'simple-icons': z.optional(z.array(z.string())),\n 'material-symbols': z.optional(z.array(z.string())),\n lucide: z.optional(z.array(z.string())),\n ph: z.optional(z.array(z.string())),\n }),\n ),\n 'Icon sets and the specific icons to bundle from each (keys are iconify collection names).',\n ),\n favicon: desc(\n z.optional(\n z.object({\n source: desc(z.string(), 'Source image (SVG/PNG) the favicon set is generated from.'),\n lowResSource: desc(\n z.optional(z.string()),\n 'Alternate source for small raster sizes (16/32px) when the main source scales down poorly.',\n ),\n name: desc(z.optional(z.string()), 'App name for the generated web manifest / PWA.'),\n themeColor: desc(\n z.optional(z.string()),\n 'PWA theme color (also `<meta name=\"theme-color\">`).',\n ),\n backgroundColor: desc(z.optional(z.string()), 'PWA background color.'),\n }),\n ),\n 'Favicon/PWA asset generation (consumed by `@getvitops/utils` favicon tooling).',\n ),\n deployment: desc(\n z.optional(\n z.object({\n platform: z.optional(z.string()),\n buildCommand: z.optional(z.string()),\n deployCommand: z.optional(z.string()),\n outputDirectory: z.optional(z.string()),\n type: z.optional(z.string()),\n }),\n ),\n 'How the site is built and deployed (platform, commands, output directory) — informational for tooling.',\n ),\n});\n\n// ── The `organization` section ──────────────────────────────────────────────────\n// The company itself. `OrganizationSchema` above is the schema.org core; the\n// section adds the things that describe the same entity rather than the site —\n// where it operates, how to reach it, what it sells, where it can be found.\n// Defined here rather than beside `OrganizationSchema` because it references\n// `ServiceSchema`, which is declared further down.\n\nconst OrganizationSectionSchema = z.extend(OrganizationSchema, {\n contact: desc(\n z.optional(ContactConfigSchema),\n 'Primary contact: either a `locations` key (string reference) or an inline name/email/phone/address object.',\n ),\n primaryLocation: desc(\n z.optional(z.string()),\n 'The main `locations` key (for JSON-LD and defaults).',\n ),\n locations: desc(\n z.optional(z.record(z.string(), LocationSchema)),\n 'Physical locations (schema.org LocalBusiness): address, geo, opening hours, service area.',\n ),\n services: desc(\n z.optional(z.record(z.string(), ServiceSchema)),\n 'Services offered (schema.org Service/Offer): name, description, slug, price offers.',\n ),\n links: desc(\n z.optional(\n z.object({\n googleMaps: z.optional(z.url()),\n instagram: z.optional(z.url()),\n facebook: z.optional(z.url()),\n x: z.optional(z.url()),\n linkedin: z.optional(z.url()),\n youtube: z.optional(z.url()),\n github: z.optional(z.url()),\n }),\n ),\n 'Public profile URLs (also feed JSON-LD `sameAs` via `organization.sameAs`).',\n ),\n});\n\n// ── Top-level schema ────────────────────────────────────────────────────────────\n\nexport const ConfigSchema = z.object({\n designSystem: DesignSystemBlock,\n organization: desc(\n z.optional(OrganizationSectionSchema),\n 'The company: schema.org Organization details for JSON-LD (name, legalName, logo, tax IDs, sameAs), plus its contact, physical locations, services and public profiles. These stay true across sites — several sites can share one `organization` and differ only in `site`.',\n ),\n site: desc(\n SiteSectionSchema,\n 'This published site: locales, domains, environments, content templates, SEO, analytics, legal documents, icons, favicon and deployment. Facts about a *presentation* of the organization rather than the organization itself.',\n ),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n/** The `organization` section — the company, independent of any one site. */\nexport type OrganizationConfig = z.infer<typeof OrganizationSectionSchema>;\n/** The `site` section — one published presentation of the organization. */\nexport type SiteSection = z.infer<typeof SiteSectionSchema>;\n/** One `fonts[]` entry — a serialisable projection of an Astro Fonts API family. */\nexport type SiteFont = z.infer<typeof SiteFontSchema>;\n/** The `seo.indexing` block — what `vitops notify` reads. */\nexport type SiteIndexing = z.infer<typeof IndexingSchema>;\n/** IndexNow submission settings. The `key` is public by design. */\nexport type SiteIndexNow = z.infer<typeof IndexNowSchema>;\n/** Google Search Console property settings. The credential is never in the config. */\nexport type SiteSearchConsole = z.infer<typeof SearchConsoleSchema>;\n\n// ── JSON Schema + validation ────────────────────────────────────────────────────\n\nexport const CONFIG_SCHEMA_URL = 'https://unpkg.com/@getvitops/generator/config.schema.json';\n\n/** The published JSON Schema (draft-2020-12), derived from the zod schema. */\nexport const configJsonSchema = {\n $id: CONFIG_SCHEMA_URL,\n ...z.toJSONSchema(ConfigSchema, { target: 'draft-2020-12' }),\n};\n\nexport type ConfigValidationResult =\n | { ok: true; data: Config; errors: [] }\n | { ok: false; data: undefined; errors: z.core.$ZodIssue[] };\n\ntype Issue = z.core.$ZodIssue;\nconst issue = (path: (string | number)[], message: string): Issue =>\n ({ code: 'custom', path, message }) as Issue;\n\n// ── Migration from the flat `SiteConfig` ────────────────────────────────────────\n\n/**\n * Where each key of the old flat config now lives.\n *\n * This exists so the restructure fails with a sentence a reader can act on. Zod\n * reports a flat config as a dozen separate `unrecognized_keys` issues plus a\n * missing required `site` — an accurate description of the document that teaches\n * nobody where anything went. Checked first, and it short-circuits: once we know\n * the document is the old shape, every other error is downstream noise.\n */\nconst MOVED_KEYS: Record<string, 'site' | 'organization'> = {\n defaultLocale: 'site',\n locales: 'site',\n domains: 'site',\n dns: 'site',\n cloudflare: 'site',\n environments: 'site',\n abTesting: 'site',\n fonts: 'site',\n tags: 'site',\n postTypes: 'site',\n galleries: 'site',\n testimonials: 'site',\n templates: 'site',\n navigation: 'site',\n seo: 'site',\n analytics: 'site',\n notifications: 'site',\n tracking: 'site',\n security: 'site',\n legal: 'site',\n icons: 'site',\n favicon: 'site',\n deployment: 'site',\n contact: 'organization',\n primaryLocation: 'organization',\n locations: 'organization',\n services: 'organization',\n links: 'organization',\n};\n\n/**\n * Detect the pre-3.0 flat shape and name the moves.\n *\n * Keyed on a moved key sitting at the ROOT, not on the absence of `site` — a\n * config that simply forgot `site` should get the ordinary \"required\" error, and\n * a partially-migrated one (some keys moved, some not) is exactly the case worth\n * catching loudly.\n */\nfunction migrationIssues(raw: unknown): Issue[] {\n if (typeof raw !== 'object' || raw == null || Array.isArray(raw)) return [];\n const found = Object.keys(raw).filter((k) => k in MOVED_KEYS);\n if (found.length === 0) return [];\n const moves = found.map((k) => ` ${k} → ${MOVED_KEYS[k]}.${k}`).join('\\n');\n return [\n issue(\n [],\n 'this is the pre-3.0 flat site config. The top level is now three sections — ' +\n '`designSystem`, `organization`, `site` — and these keys moved:\\n' +\n `${moves}\\n` +\n '`designSystem` and the fields already under `organization` stay where they are.',\n ),\n ];\n}\n\n/**\n * Validate a raw (already parsed) config: shape via zod, then the cross-field\n * integrity that JSON Schema can't express (referential keys, extends acyclicity).\n * These live only here — the published JSON Schema enforces shape, not integrity.\n */\nexport function validateConfig(input: unknown): ConfigValidationResult {\n const migration = migrationIssues(input);\n if (migration.length) return { ok: false, data: undefined, errors: migration };\n\n const parsed = z.safeParse(ConfigSchema, input);\n if (!parsed.success) return { ok: false, data: undefined, errors: parsed.error.issues };\n const cfg = parsed.data;\n const site = cfg.site;\n const org = cfg.organization;\n const errors: Issue[] = [];\n const has = (m: Record<string, unknown> | undefined, k: string) => !!m && k in m;\n\n if (!has(site.locales, site.defaultLocale))\n errors.push(\n issue(['site', 'defaultLocale'], `defaultLocale \"${site.defaultLocale}\" is not in locales`),\n );\n\n const themes = cfg.designSystem?.themes ?? {};\n const defaultTheme = cfg.designSystem?.defaultTheme;\n\n if (!has(themes, 'default') && defaultTheme == null)\n errors.push(issue(['designSystem', 'themes'], 'themes must include a \"default\" entry'));\n\n if (defaultTheme != null && !has(themes, defaultTheme))\n errors.push(\n issue(\n ['designSystem', 'defaultTheme'],\n `defaultTheme \"${defaultTheme}\" is not in designSystem.themes`,\n ),\n );\n\n for (const [key, entry] of Object.entries(themes)) {\n if (entry.extends != null && !has(themes, entry.extends))\n errors.push(\n issue(\n ['designSystem', 'themes', key, 'extends'],\n `extends \"${entry.extends}\" is not a themes key`,\n ),\n );\n }\n // extends acyclicity + each resolved theme is a complete DesignSystem\n for (const key of Object.keys(themes)) {\n try {\n resolveTheme(themes as Record<string, DesignSystemEntryT>, key);\n } catch (e) {\n errors.push(issue(['designSystem', 'themes', key], (e as Error).message));\n }\n }\n\n if (org?.primaryLocation != null && !has(org.locations, org.primaryLocation))\n errors.push(\n issue(\n ['organization', 'primaryLocation'],\n `primaryLocation \"${org.primaryLocation}\" is not in organization.locations`,\n ),\n );\n if (typeof org?.contact === 'string' && !has(org.locations, org.contact))\n errors.push(\n issue(\n ['organization', 'contact'],\n `contact \"${org.contact}\" is not an organization.locations key`,\n ),\n );\n\n for (const [name, v] of Object.entries(site.abTesting?.variants ?? {}))\n if (!has(site.environments, v.environment))\n errors.push(\n issue(\n ['site', 'abTesting', 'variants', name, 'environment'],\n `environment \"${v.environment}\" is not in site.environments`,\n ),\n );\n for (const [i, a] of (site.domains?.aliases ?? []).entries())\n if (a.environment != null && !has(site.environments, a.environment))\n errors.push(\n issue(\n ['site', 'domains', 'aliases', i, 'environment'],\n `environment \"${a.environment}\" is not in site.environments`,\n ),\n );\n\n const templates = site.templates;\n const at = site.navigation?.activeTemplate;\n if (at?.default != null && !has(templates, at.default))\n errors.push(\n issue(\n ['site', 'navigation', 'activeTemplate', 'default'],\n `template \"${at.default}\" is not in site.templates`,\n ),\n );\n for (const [bp, tpl] of Object.entries(at?.breakpoints ?? {}))\n if (!has(templates, tpl))\n errors.push(\n issue(\n ['site', 'navigation', 'activeTemplate', 'breakpoints', bp],\n `template \"${tpl}\" is not in site.templates`,\n ),\n );\n\n // Legal. An enabled document is a promise to publish a specific, correct\n // sentence — so the inputs those sentences interpolate are required here\n // rather than allowed to render as a blank. `jurisdiction` needs no check:\n // the enum rejects an unregistered value at parse time.\n const privacy = site.legal?.privacyPolicy;\n if (typeof privacy?.privacyOfficer === 'string' && !has(org?.locations, privacy.privacyOfficer))\n errors.push(\n issue(\n ['site', 'legal', 'privacyPolicy', 'privacyOfficer'],\n `privacyOfficer \"${privacy.privacyOfficer}\" is not an organization.locations key`,\n ),\n );\n if (privacy?.enabled) {\n if (resolvePrivacyContact(cfg) == null)\n errors.push(\n issue(\n ['site', 'legal', 'privacyPolicy'],\n 'privacyPolicy.enabled requires a contact for privacy requests — set site.legal.privacyPolicy.privacyOfficer, organization.contact, or organization.email/address',\n ),\n );\n if (site.domains?.canonical == null)\n errors.push(\n issue(\n ['site', 'legal', 'privacyPolicy'],\n 'privacyPolicy.enabled requires site.domains.canonical — the policy states where information is held',\n ),\n );\n }\n\n // Indexing. Both defaults (the sitemap URL and the IndexNow key location) are\n // built from `domains.canonical`, so without it the block is unresolvable —\n // and the failure would otherwise surface at deploy time, as a submission\n // against `undefined/sitemap-index.xml`, rather than here.\n const indexing = site.seo?.indexing;\n if (indexing != null && site.domains?.canonical == null) {\n if (indexing.sitemapUrl == null)\n errors.push(\n issue(\n ['site', 'seo', 'indexing', 'sitemapUrl'],\n 'site.seo.indexing needs site.domains.canonical to derive the sitemap URL — set one, or state sitemapUrl explicitly',\n ),\n );\n if (indexing.indexNow != null && indexing.indexNow.keyLocation == null)\n errors.push(\n issue(\n ['site', 'seo', 'indexing', 'indexNow', 'keyLocation'],\n 'site.seo.indexing.indexNow needs site.domains.canonical to derive the key location — set one, or state keyLocation explicitly',\n ),\n );\n }\n\n if (errors.length) return { ok: false, data: undefined, errors };\n return { ok: true, data: cfg, errors: [] };\n}\n\n/**\n * Resolve who privacy requests go to: the explicit privacy officer, else the\n * organization's contact, else its primary location, else the organization itself.\n *\n * Exported because `validateConfig` and the legal-document derivation must agree\n * on it exactly — a config that validates must be one the policy can render, and\n * two copies of this precedence would drift into a policy with a blank address.\n *\n * Note every candidate but the first now lives in `organization`, and the first\n * (`site.legal.privacyPolicy.privacyOfficer`) still dereferences against\n * `organization.locations` — the officer is a person at the company, named by the\n * site because a company may publish more than one policy.\n */\nexport function resolvePrivacyContact(cfg: Config): ContactObject | undefined {\n const org = cfg.organization;\n // A location's `name` is Localizable and a contact's is a plain string; the\n // name is not used in the rendered address, so drop it rather than pick a locale.\n const deref = (c: string | ContactObject | undefined): ContactObject | undefined => {\n if (c == null) return undefined;\n if (typeof c !== 'string') return c;\n const loc = org?.locations?.[c];\n return loc && { email: loc.email, phone: loc.phone, address: loc.address };\n };\n const candidates = [\n deref(cfg.site.legal?.privacyPolicy?.privacyOfficer),\n deref(org?.contact),\n deref(org?.primaryLocation),\n org && { email: org.email, phone: org.phone, address: org.address },\n ];\n // A contact with no reachable channel is not a contact — skip to the next.\n return candidates.find((c) => c != null && (c.email != null || c.address != null));\n}\n\n// ── Theme resolution (extends) ──────────────────────────────────────────────────\n\ntype DesignSystemEntryT = Partial<DesignSystem> & { displayName?: unknown; extends?: string };\n\n/**\n * Resolve a design-system theme by following its `extends` chain and deep-merging\n * base → child (child wins; arrays replace wholesale, correct for token overrides).\n * Throws on unknown keys or an `extends` cycle. The result is a plain\n * `DesignSystem` (validate it against `DesignSystemSchema` for completeness).\n */\nexport function resolveTheme(\n designSystem: Record<string, DesignSystemEntryT>,\n key: string,\n): DesignSystem {\n const chain: DesignSystemEntryT[] = [];\n const seen = new Set<string>();\n let cur: string | undefined = key;\n while (cur != null) {\n if (seen.has(cur)) throw new Error(`extends cycle in designSystem at \"${cur}\"`);\n seen.add(cur);\n const entry: DesignSystemEntryT | undefined = designSystem[cur];\n if (entry == null) throw new Error(`designSystem theme \"${cur}\" not found`);\n chain.unshift(entry);\n cur = entry.extends;\n }\n const out: Record<string, unknown> = {};\n for (const entry of chain) {\n const { extends: _e, displayName: _d, ...ds } = entry;\n deepMerge(out, ds as Record<string, unknown>);\n }\n return out as DesignSystem;\n}\n\n/**\n * Normalise the two `designSystem` shorthands to the canonical\n * `{ themes: { … } }` shape.\n *\n * Both are keyed off what CANNOT be a theme name in the other reading:\n * - `colors` → a bare `DesignSystem` was written inline.\n * - `themes` → already canonical.\n * - neither → the legacy bare theme map, from before the block gained\n * system-wide fields. Every config authored against the old schema takes this\n * branch, which is what keeps the change forgiving at runtime even though the\n * published JSON Schema moved.\n */\nfunction normaliseDesignSystem(raw: Record<string, unknown>): void {\n const ds = raw.designSystem as Record<string, unknown> | undefined;\n if (ds == null || typeof ds !== 'object') return;\n if ('themes' in ds) return;\n raw.designSystem = 'colors' in ds ? { themes: { default: ds } } : { themes: ds };\n}\n\n/**\n * Resolve a raw (already-parsed) config into a validated `Config`:\n * 1. strip YAML nulls,\n * 2. normalise the `designSystem` shorthands to `{ themes: … }`,\n * 3. apply the active A/B variant's `overrides` (by `siteEnv`),\n * 4. validate (shape + cross-field).\n * Pure — no YAML/env access. A loader supplies `siteEnv`.\n *\n * Steps 2 and 3 are in this order deliberately. Normalising first means an\n * `abTesting` override always addresses the canonical shape\n * (`designSystem.themes.<name>`), whatever shorthand the base config used. With\n * the merge first, an override's key path depended on how the base happened to be\n * written — so the same patch hit a different place in two configs that were\n * otherwise equivalent.\n *\n * The A/B lookup reads `site.environments` / `site.abTesting`, and the overrides\n * still deep-merge at the **root** — a variant patches whichever section it names,\n * which is what lets one target `designSystem` and another `site.seo`.\n */\nexport function resolveConfig(input: unknown, siteEnv = 'production'): Config {\n const raw = stripNulls(input) as Record<string, unknown>;\n\n normaliseDesignSystem(raw);\n\n const site = raw.site as Record<string, unknown> | undefined;\n const envConfig = (site?.environments as Record<string, { variant?: string }> | undefined)?.[\n siteEnv\n ];\n if (envConfig?.variant) {\n const overrides = (\n site?.abTesting as { variants?: Record<string, { overrides?: Record<string, unknown> }> }\n )?.variants?.[envConfig.variant]?.overrides;\n if (overrides) {\n // An override may itself use a shorthand; normalise it to the same shape or\n // deepMerge would nest a bare map under the canonical one.\n normaliseDesignSystem(overrides);\n deepMerge(raw, overrides);\n }\n }\n\n const result = validateConfig(raw);\n if (!result.ok) {\n const msg = result.errors\n .map((e) => ` ${e.path.join('.') || '<root>'}: ${e.message}`)\n .join('\\n');\n throw new Error(`Invalid config:\\n${msg}`);\n }\n return result.data;\n}\n\n// ── Accepting either config kind ────────────────────────────────────────────────\n\n/**\n * Is this raw config a full `Config` rather than a bare `design-system.json`?\n *\n * The discriminator is **total**, not a heuristic, and both halves are load-\n * bearing: `ConfigSchema` cannot validate without a `designSystem` (it is a\n * required key), and `DesignSystemSchema` is strict, so a `designSystem` key in a\n * design system is an `unrecognized_keys` error. No document can be read as both,\n * and no document that is neither reaches here without failing validation anyway.\n *\n * The restructure did not weaken this: `designSystem` stayed at the root\n * precisely so the discriminator kept working unchanged.\n *\n * Deliberately shape-based rather than filename-based: consumers name this file\n * whatever suits them (`company.json`, `site.json`, `vitops.config.json`), and a\n * rule keyed to a name would silently stop working the moment someone renamed it.\n */\nexport function isConfig(raw: unknown): boolean {\n return typeof raw === 'object' && raw != null && !Array.isArray(raw) && 'designSystem' in raw;\n}\n\n/** What a config file turned out to hold. */\nexport interface ResolvedInput {\n /** The design system to build from — a resolved theme, if the input was a full `Config`. */\n designSystem: DesignSystem;\n /** The whole config, when that is what the input was. */\n config?: Config;\n /** Which `themes` key was selected. Absent for a bare `design-system.json`. */\n theme?: string;\n}\n\n/**\n * Resolve a raw config of either kind into the design system to build from.\n *\n * Every entry point that used to take a `design-system.json` goes through this,\n * so a consumer who keeps their tokens inside the larger config points the\n * same option at that file instead of maintaining a second one. The config\n * is handed back too, because the parts of generation that depend on site-level\n * facts (`designSystem.defaultColorScheme`, the legal documents, the icon\n * sprite) would otherwise need the same path declared a second time.\n *\n * The returned `designSystem` is **not** validated here — the caller does that,\n * so it can say which file and which theme the errors belong to. Validation of\n * the config itself has already happened (`resolveConfig` throws).\n */\nexport function resolveInput(\n raw: unknown,\n opts: { theme?: string; siteEnv?: string } = {},\n): ResolvedInput {\n if (!isConfig(raw)) {\n if (opts.theme != null)\n throw new Error(\n `theme \"${opts.theme}\" was requested, but this is a design-system.json — it holds one ` +\n 'design system and no `themes` map. Point at a full config to select a theme.',\n );\n return { designSystem: raw as DesignSystem };\n }\n const config = resolveConfig(raw, opts.siteEnv);\n const themes = (config.designSystem?.themes ?? {}) as Record<string, DesignSystemEntryT>;\n const theme = opts.theme ?? config.designSystem?.defaultTheme ?? 'default';\n if (!(theme in themes))\n throw new Error(\n `designSystem.themes has no \"${theme}\" entry (found: ${Object.keys(themes).join(', ') || 'none'})`,\n );\n return { designSystem: resolveTheme(themes, theme), config, theme };\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────────\n\n/** Strip nulls (YAML `~`/`null`) → undefined so optional fields validate. */\nexport function stripNulls(obj: unknown): unknown {\n if (obj === null) return undefined;\n if (Array.isArray(obj)) return obj.map(stripNulls);\n if (obj && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const stripped = stripNulls(value);\n if (stripped !== undefined) result[key] = stripped;\n }\n return result;\n }\n return obj;\n}\n\n/** Deep-merge `source` into `target` (in place). Arrays replace wholesale. */\nexport function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>) {\n for (const key of Object.keys(source)) {\n const s = source[key];\n const t = target[key];\n if (\n s &&\n typeof s === 'object' &&\n !Array.isArray(s) &&\n t &&\n typeof t === 'object' &&\n !Array.isArray(t)\n ) {\n deepMerge(t as Record<string, unknown>, s as Record<string, unknown>);\n } else {\n target[key] = s;\n }\n }\n}\n","/**\n * Palette expansion + semantic colour tokens.\n *\n * A palette hue is authored one of two ways:\n * • `{ seed, anchors? }` — an 11-step numeric scale (50…950) generated in\n * OKLCH via @getvitops/utils/color. Lightness comes from the shared\n * `LIGHTNESS_LADDER`; the seed (and any anchors) are reproduced verbatim at\n * their steps.\n * • `{ tones }` — a fixed brand kit: authored tones placed verbatim at their\n * nearest steps + tinted endpoints; nothing else is invented (strict kits).\n *\n * **The grammar.** Every role gets tokens named `--color-<target>-<role>[-<variant>]`,\n * where target ∈ bg | text | icon | border. Putting the target *inside* the name is\n * the point: `--color-bg-danger-muted` and `--color-text-danger-muted` are distinct\n * tokens, so the two axes that used to collide over one `<family>-<role>-<modifier>\n * ` namespace cannot any more. The utility class is the token name minus `--color-`.\n *\n * Variants are ordinal — xx-muted < x-muted < muted < (bare) < bold < x-bold —\n * and the tables are **sparse**: a target only emits the cells that are actually\n * viable. `bold` means \"more emphatic than the role's default in the current\n * appearance\", not \"darker\"; the appearance decides polarity.\n *\n * Roles come in two kinds (declared in `colors.roles`):\n * • `surface` — a page/panel colour. Has a bare `bg-<role>` plus the full\n * emphasis range and the complete text scale.\n * • `chromatic` (default) — a signal colour. Backgrounds split into *tints*\n * (`bg-<role>-x-muted` / `-muted`) and *solids* (`bg-<role>-solid[-bold|-x-bold]`);\n * there is deliberately **no bare `bg-<role>`**, because \"how loud?\" is a\n * question the author has to answer.\n *\n * Dark mode re-points which step each token reads; the solid family and the\n * `text-on-<role>` foreground computed against it stay mode-stable, so a filled\n * button keeps its identity across appearances.\n */\nimport {\n LIGHTNESS_LADDER,\n contrastLc,\n generateOklchPalette,\n hexToOklch,\n oklchStringToHex,\n pickOn,\n tintedEndpoints,\n} from '@getvitops/utils/color';\n\nexport const NUMERIC_STEPS = [\n '50',\n '100',\n '200',\n '300',\n '400',\n '500',\n '600',\n '700',\n '800',\n '900',\n '950',\n] as const;\ntype NumStep = (typeof NUMERIC_STEPS)[number];\n\n/**\n * Lightness of each numeric step. Re-exported from the engine's ladder rather\n * than restated — there used to be three copies of this curve (here, the engine,\n * and the linter) and they were free to drift.\n */\nconst STEP_L = Object.fromEntries(\n NUMERIC_STEPS.map((s) => [s, LIGHTNESS_LADDER[Number(s) as keyof typeof LIGHTNESS_LADDER]]),\n) as Record<NumStep, number>;\n\nexport interface ExpandedHue {\n /** Numeric steps (sparse for fixed-tone kits). */\n numeric: Partial<Record<NumStep, string>>;\n /** True when only authored tones + endpoints exist (no interpolation). */\n sparse?: boolean;\n /**\n * Steps the author pinned, and how far each sits from the ladder's lightness.\n * A pinned colour is reproduced exactly, so a large value here is legal — but\n * it means this hue reads heavier or lighter than its siblings at that step,\n * which the generator surfaces as a warning.\n */\n deviations?: Partial<Record<NumStep, number>>;\n}\n\ninterface SeedInput {\n seed: string;\n anchors?: Record<string, string>;\n}\ninterface TonesInput {\n tones: string[] | Record<string, string>;\n}\n\nconst isHex = (v: string) => v.startsWith('#');\nconst toOklchStr = (v: string) => {\n if (!isHex(v)) return v; // already oklch(...)\n const { l, c, h } = hexToOklch(v);\n return `oklch(${(l * 100).toFixed(2)}% ${c.toFixed(4)} ${h.toFixed(2)})`;\n};\nconst nearestStep = (l: number): NumStep =>\n NUMERIC_STEPS.reduce((best, s) =>\n Math.abs(l - STEP_L[s]) < Math.abs(l - STEP_L[best]) ? s : best,\n );\n\n/**\n * Claim `step` for `value`, refusing to overwrite a step another colour already\n * took.\n *\n * Silently dropping one of two colliding tones is the worst outcome: the palette\n * still builds, and the tone the author cared about is simply gone. The record\n * form (`tones: { \"600\": \"#…\", \"700\": \"#…\" }`) is the escape hatch, so the error\n * points at it.\n */\nfunction claim(\n into: Record<string, string>,\n step: string,\n value: string,\n hueLabel: string,\n what: string,\n): void {\n const taken = into[step];\n if (taken != null && taken !== value) {\n throw new Error(\n `palette hue \"${hueLabel}\": ${what} ${value} and ${taken} both map to step ${step}. ` +\n `Key them explicitly, e.g. { \"${step}\": \"${taken}\", \"${Number(step) + 100}\": \"${value}\" }.`,\n );\n }\n into[step] = value;\n}\n\nfunction expandSeeded(input: SeedInput, hueLabel: string): ExpandedHue {\n // The seed and any author anchors pin verbatim at their natural (or explicit)\n // steps; the engine fills every other step from the shared lightness ladder,\n // fading chroma toward the tinted ends. No implicit 50/950 anchors any more —\n // the ladder already defines the endpoints, and pinning them would override it.\n // Author anchors are placed FIRST and may collide only with each other. The\n // seed goes in afterwards, and only where an anchor hasn't already claimed the\n // step: an explicit anchor is the author overriding that step, which is exactly\n // what the live editor writes when you recolour a swatch. Treating that as a\n // collision would break the editor's save path.\n const anchors: Record<string, string> = {};\n for (const [key, value] of Object.entries(input.anchors ?? {})) {\n const step = (NUMERIC_STEPS as readonly string[]).includes(key)\n ? key\n : nearestStep(hexToOklch(value).l);\n claim(anchors, step, toOklchStr(value), hueLabel, 'anchors');\n }\n const seedStep = nearestStep(hexToOklch(input.seed).l);\n anchors[seedStep] ??= toOklchStr(input.seed);\n const scale = generateOklchPalette(anchors) as Record<string, string>;\n const numeric: Partial<Record<NumStep, string>> = {};\n for (const s of NUMERIC_STEPS) if (scale[s] != null) numeric[s] = oklchStringToHex(scale[s]);\n return { numeric, deviations: deviationsFor(anchors) };\n}\n\nfunction expandTones(input: TonesInput, hueLabel: string): ExpandedHue {\n // Strict kit: authored tones verbatim at their nearest step; add tinted\n // endpoints (the one allowed exception); interpolate nothing else.\n const entries: Array<[string | null, string]> = Array.isArray(input.tones)\n ? input.tones.map((hex) => [null, hex])\n : Object.entries(input.tones).map(([k, hex]) => [k, hex]);\n\n const placed: Record<string, string> = {};\n for (const [key, hex] of entries) {\n const step =\n key != null && (NUMERIC_STEPS as readonly string[]).includes(key)\n ? key\n : nearestStep(hexToOklch(hex).l);\n claim(placed, step, hex, hueLabel, 'tones');\n }\n\n const numeric: Partial<Record<NumStep, string>> = {};\n for (const [step, hex] of Object.entries(placed)) numeric[step as NumStep] = hex;\n\n const firstTone = entries[0]?.[1] ?? '#808080';\n const ends = tintedEndpoints(hexToOklch(firstTone).h);\n numeric['50'] ??= ends.light;\n numeric['950'] ??= ends.dark;\n\n return { numeric, sparse: true, deviations: deviationsFor(placed) };\n}\n\n/** How far each pinned colour sits from its step's ladder lightness. */\nfunction deviationsFor(pinned: Record<string, string>): Partial<Record<NumStep, number>> {\n const out: Partial<Record<NumStep, number>> = {};\n for (const [step, value] of Object.entries(pinned)) {\n const l = isHex(value) ? hexToOklch(value).l : hexToOklch(oklchStringToHex(value)).l;\n out[step as NumStep] = l - STEP_L[step as NumStep];\n }\n return out;\n}\n\n/** Snap to the nearest AVAILABLE numeric step (sparse kits). */\nfunction snap(numeric: Partial<Record<NumStep, string>>, want: NumStep): NumStep {\n if (numeric[want] != null) return want;\n const have = NUMERIC_STEPS.filter((s) => numeric[s] != null);\n return have.reduce((best, s) =>\n Math.abs(STEP_L[s] - STEP_L[want]) < Math.abs(STEP_L[best] - STEP_L[want]) ? s : best,\n );\n}\n\n/** Expand every palette hue into its numeric scale. */\nexport function expandPalette(raw: Record<string, unknown>): Record<string, ExpandedHue> {\n const out: Record<string, ExpandedHue> = {};\n for (const [name, entry] of Object.entries(raw)) {\n const e = entry as Partial<SeedInput & TonesInput>;\n if (typeof e?.seed === 'string') out[name] = expandSeeded(e as SeedInput, name);\n else if (e?.tones != null) out[name] = expandTones(e as TonesInput, name);\n else throw new Error(`palette hue \"${name}\" must have a \"seed\" or \"tones\"`);\n }\n return out;\n}\n\n/**\n * Warn about pinned colours that sit noticeably off the ladder. Not an error:\n * the author asked for that exact colour and gets it. But at ~0.03 L the hue\n * starts reading visibly heavier or lighter than its siblings at that step, and\n * that is the class of drift the fixed ladder exists to prevent.\n */\nexport const LADDER_TOLERANCE = 0.03;\n\nexport function ladderWarnings(palette: Record<string, ExpandedHue>): string[] {\n const warnings: string[] = [];\n for (const [hue, expanded] of Object.entries(palette)) {\n for (const [step, deviation] of Object.entries(expanded.deviations ?? {})) {\n if (Math.abs(deviation as number) <= LADDER_TOLERANCE) continue;\n const dir = (deviation as number) > 0 ? 'lighter' : 'darker';\n warnings.push(\n `colors.palette.${hue}: the colour pinned at step ${step} is ${Math.abs(\n deviation as number,\n ).toFixed(3)} ${dir} than the shared lightness ladder — this hue will read ` +\n `${dir} than others at ${step}. Legal, but move it to a neighbouring step if that wasn't intended.`,\n );\n }\n }\n return warnings;\n}\n\n/**\n * Gamut mapping nudges lightness by a hair, so an exact `<` comparison would\n * report rounding as an inversion. Well below any deviation a person could see.\n */\nconst MONOTONIC_EPSILON = 1e-3;\n\n/**\n * Ramps whose lightness does not fall monotonically from 50 to 950.\n *\n * A ramp built from the ladder alone cannot invert — only pinned colours (a seed,\n * an `anchor`, a `tones` entry) can, because they are the one thing allowed off\n * it. `ladderWarnings` will not catch it: it compares each pinned step against\n * *its own* ladder rung, never against its neighbours, so it reports the wrong\n * defect (\"reads darker than others at 600\") while the real problem is that 600\n * is darker than 700. And since `LADDER_TOLERANCE` is 0.03 — the same size as the\n * ladder's own 50→100 gap — two anchors can each sit within tolerance and still\n * invert, with no warning at all.\n *\n * This is an error rather than a warning because the rest of the system assumes\n * the order: `snap` picks the nearest step by ladder lightness, the mode-stable\n * solid family hard-codes 600/700/800 as increasingly dark, and both dark tables\n * re-point steps on the same assumption. An inverted ramp therefore runs hover\n * states backwards — the failure the fixed ladder was introduced to eliminate.\n */\nexport function monotonicityErrors(palette: Record<string, ExpandedHue>): string[] {\n const errors: string[] = [];\n for (const [hue, expanded] of Object.entries(palette)) {\n const numeric = expanded.numeric ?? {};\n // Present steps only — a sparse `tones` kit is legal, and comparing against\n // absent steps would invent inversions that aren't there.\n const steps = NUMERIC_STEPS.filter((s) => numeric[s] != null);\n for (let i = 1; i < steps.length; i++) {\n const [prev, step] = [steps[i - 1] as NumStep, steps[i] as NumStep];\n // The final hex, not the nominal ladder value: a pinned colour is emitted\n // verbatim, and it is precisely the pinned steps that can invert.\n const lPrev = hexToOklch(numeric[prev] as string).l;\n const lStep = hexToOklch(numeric[step] as string).l;\n if (lStep < lPrev + MONOTONIC_EPSILON) continue;\n // Point at the colour the author actually wrote. Only a pinned step can be\n // off the ladder, so naming its correct home is the actionable half — the\n // unpinned neighbour is already exactly where it belongs, and telling\n // someone to move that one sends them the wrong way.\n const pinned = expanded.deviations ?? {};\n const culprits = ([prev, step] as NumStep[]).filter((s) => pinned[s] != null);\n const fix = culprits.length\n ? culprits\n .map((s) => {\n const l = hexToOklch(numeric[s] as string).l;\n return `${numeric[s]} (pinned at ${s}) sits at L ${l.toFixed(3)}, nearest step ${nearestStep(l)}`;\n })\n .join('; ')\n : `no step here is pinned, so this is a bug in the generator rather than in your config`;\n errors.push(\n `colors.palette.${hue}: step ${step} (${numeric[step]}, L ${lStep.toFixed(3)}) is LIGHTER ` +\n `than step ${prev} (${numeric[prev]}, L ${lPrev.toFixed(3)}). A ramp must darken from 50 ` +\n `to 950 — inverted, a hover from \\`bg-<role>-solid\\` to \\`-solid-bold\\` gets lighter, and ` +\n `the dark-mode tables re-point steps assuming the order. ${fix}.`,\n );\n }\n }\n return errors;\n}\n\n// ── the token tables ─────────────────────────────────────────────────────────\n\n/** Which shape of token set a role gets. */\nexport type RoleKind = 'surface' | 'chromatic';\n\n/** Token key → numeric step. Keys are `<target>[-<variant>]`; see `tokenVar`. */\ntype Table = Record<string, NumStep>;\n\n/**\n * Surface roles: a bare `bg` (cards, panels, inputs), `bg-muted` for the page\n * behind them, `bg-x-muted` for wells, and `bg-bold`/`-x-bold` for the inverse\n * surface a tooltip sits on. Elevation is expressed by *which* token you reach\n * for — page `bg-muted`, card `bg` — rather than by a raised/sunken pair. That\n * is what lets a future `data-surfaces` axis flatten it without touching markup.\n */\nconst SURFACE_LIGHT: Table = {\n bg: '50',\n 'bg-muted': '100',\n 'bg-x-muted': '200',\n 'bg-bold': '800',\n 'bg-x-bold': '950',\n text: '900',\n 'text-bold': '950',\n 'text-muted': '700',\n 'text-x-muted': '500',\n 'text-xx-muted': '400',\n 'text-on-bold': '50',\n icon: '600',\n 'icon-muted': '500',\n 'border-muted': '200',\n border: '300',\n 'border-bold': '600',\n};\nconst SURFACE_DARK: Table = {\n bg: '900',\n 'bg-muted': '950',\n 'bg-x-muted': '950',\n 'bg-bold': '200',\n 'bg-x-bold': '50',\n text: '100',\n 'text-bold': '50',\n // 300 and 400, not v3.1's 400 and 500: those were tuned against WCAG and come\n // up short of APCA's secondary-text and non-text bars over a dark surface.\n 'text-muted': '300',\n 'text-x-muted': '500',\n 'text-xx-muted': '600',\n 'text-on-bold': '950',\n icon: '400',\n 'icon-muted': '500',\n 'border-muted': '800',\n border: '700',\n 'border-bold': '400',\n};\n\n/**\n * Chromatic roles: tints for alert/badge backgrounds, solids for fills. No bare\n * `bg` — see the module docblock. No `text-muted` either: a de-emphasised\n * coloured text could not hold its contrast target off a white surface, so the\n * way to soften coloured text is weight/size, not another colour.\n */\nconst CHROMATIC_LIGHT: Table = {\n 'bg-x-muted': '50',\n 'bg-muted': '100',\n text: '700',\n 'text-bold': '900',\n icon: '600',\n border: '200',\n 'border-bold': '300',\n};\nconst CHROMATIC_DARK: Table = {\n 'bg-x-muted': '950',\n 'bg-muted': '900',\n text: '300',\n 'text-bold': '200',\n icon: '400',\n border: '800',\n 'border-bold': '700',\n};\n\n/**\n * The solid family — mode-stable, so a filled button keeps its identity when the\n * appearance flips. Fixed steps rather than the old scan-and-clamp: with a shared\n * lightness ladder every hue's 600 already sits at the same lightness, so there\n * is nothing left to search for. `text-on-<role>` is computed against `bg-solid`.\n */\nconst SOLID: Table = { 'bg-solid': '600', 'bg-solid-bold': '700', 'bg-solid-x-bold': '800' };\n\n/**\n * Map a token key to its CSS custom property for a given role.\n *\n * `on` is the one irregular case: the foreground for a filled surface reads\n * `--color-text-on-<role>`, with the role *after* `on`, because it names what it\n * sits on rather than what it is.\n *\n * The utility class name is this minus the `--color-` prefix, which is why the\n * emitter and the linter can both derive their vocabulary from one function.\n */\nexport function tokenVar(role: string, key: string): string {\n const dash = key.indexOf('-');\n const target = dash === -1 ? key : key.slice(0, dash);\n const variant = dash === -1 ? '' : key.slice(dash + 1);\n if (variant === 'on') return `--color-${target}-on-${role}`;\n if (variant.startsWith('on-')) return `--color-${target}-on-${role}-${variant.slice(3)}`;\n return variant ? `--color-${target}-${role}-${variant}` : `--color-${target}-${role}`;\n}\n\n/** The class name a token key produces for a role (`bg-danger-solid`, …). */\nexport const tokenClass = (role: string, key: string): string =>\n tokenVar(role, key).slice('--color-'.length);\n\nexport interface FunctionalRole {\n role: string;\n hue: string;\n kind: RoleKind;\n /** token key → CSS value, per appearance. */\n light: Record<string, string>;\n dark: Record<string, string>;\n}\n\n/** Resolve the token set for one role over its hue. */\nexport function functionalRole(\n role: string,\n hueName: string,\n hue: ExpandedHue,\n kind: RoleKind = 'chromatic',\n): FunctionalRole {\n const numeric = hue.numeric;\n const v = (n: NumStep) => `var(--color-${hueName}-${snap(numeric, n)})`;\n const hex = (n: NumStep) => numeric[snap(numeric, n)] as string;\n\n const map = (table: Table): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [token, step] of Object.entries(table)) out[token] = v(step);\n return out;\n };\n\n // Solids and the foreground computed against them are identical in both\n // appearances — that mode-stability is the whole point of the family.\n const solids = map(SOLID);\n const onSolid = pickOn(hex(SOLID['bg-solid'] as NumStep));\n\n const light = {\n ...map(kind === 'surface' ? SURFACE_LIGHT : CHROMATIC_LIGHT),\n ...solids,\n 'text-on': onSolid,\n };\n const dark = {\n ...map(kind === 'surface' ? SURFACE_DARK : CHROMATIC_DARK),\n ...solids,\n 'text-on': onSolid,\n };\n return { role, hue: hueName, kind, light, dark };\n}\n\n// ── the contrast contract ────────────────────────────────────────────────────\n\n/**\n * APCA targets. `TEXT` is the body-text bar; `SECONDARY` covers text on a\n * non-primary surface and de-emphasised text. `NON_TEXT` is the icon/boundary\n * tier — the APCA analogue of WCAG's 3:1, where a glyph may run more vivid than\n * text because shape carries meaning alongside contrast.\n */\nexport const CONTRAST = { TEXT: 75, SECONDARY: 60, NON_TEXT: 45 } as const;\n\n/**\n * Text tokens deliberately exempt from the contract. Placeholders and disabled\n * text are required to look unavailable; holding them to the body-text bar would\n * defeat the affordance. Nothing else may be exempt.\n */\nconst EXEMPT_TEXT = new Set(['text-x-muted', 'text-xx-muted']);\n\n/**\n * Verify a role's contrast targets. Returns human-readable failures.\n *\n * Chromatic roles are checked against the surface planes they actually sit on\n * (`surfaceBg`) as well as their own tints — coloured text almost never appears\n * over its own solid, it appears over the page. Checking only within the role\n * would have missed the pairing that matters most.\n */\nexport function checkContrast(\n fr: FunctionalRole,\n numericOf: (hueName: string) => Partial<Record<NumStep, string>>,\n surfaceBg?: { light: string[]; dark: string[] },\n): string[] {\n const failures: string[] = [];\n const resolve = (val: string): string => {\n const m = /^var\\(--color-([a-z0-9-]+)-(\\d+)\\)$/.exec(val);\n if (!m) return val;\n return numericOf(m[1] as string)[m[2] as NumStep] ?? val;\n };\n const fail = (appearance: string, msg: string) =>\n failures.push(`${fr.role}/${appearance}: ${msg}`);\n\n for (const [appearance, tokens] of [\n ['light', fr.light],\n ['dark', fr.dark],\n ] as const) {\n // Backgrounds this role's own foregrounds have to work on. For a surface\n // role that's its own planes; for a chromatic role it's the page surface\n // plus its own tints.\n const ownBg = Object.keys(tokens)\n .filter((k) => k === 'bg' || k.startsWith('bg-'))\n .filter((k) => !k.startsWith('bg-solid'))\n .filter((k) => !k.startsWith('bg-bold') && !k.startsWith('bg-x-bold'));\n const planes: Array<[string, string]> =\n fr.kind === 'surface'\n ? ownBg.map((k) => [k, resolve(tokens[k] as string)])\n : [\n ...(surfaceBg?.[appearance] ?? []).map(\n (h, i) => [`surface#${i}`, h] as [string, string],\n ),\n ...ownBg.map((k) => [k, resolve(tokens[k] as string)] as [string, string]),\n ];\n\n for (const [planeName, bg] of planes) {\n // `bg` is the role's primary surface and holds the full body-text bar;\n // every other plane holds the secondary bar.\n const textMin = planeName === 'bg' ? CONTRAST.TEXT : CONTRAST.SECONDARY;\n for (const key of ['text', 'text-bold', 'text-muted']) {\n if (tokens[key] == null || EXEMPT_TEXT.has(key)) continue;\n const min = key === 'text-muted' ? CONTRAST.SECONDARY : textMin;\n const lc = contrastLc(resolve(tokens[key] as string), bg);\n if (lc < min) fail(appearance, `${key} Lc ${lc.toFixed(1)} < ${min} on ${planeName} ${bg}`);\n }\n // Icons carry meaning, so they hold the non-text bar everywhere. Borders\n // do not: a chromatic `border-<role>` is *decorative* — the tinted edge of\n // an alert, where the colour reinforces a message the text already makes.\n // Only a surface role's `border-bold` is the \"this boundary is the only\n // thing separating two regions\" token, so only that one is guaranteed.\n const nonText = fr.kind === 'surface' ? ['icon', 'border-bold'] : ['icon'];\n for (const key of nonText) {\n if (tokens[key] == null) continue;\n const lc = contrastLc(resolve(tokens[key] as string), bg);\n if (lc < CONTRAST.NON_TEXT)\n fail(\n appearance,\n `${key} Lc ${lc.toFixed(1)} < ${CONTRAST.NON_TEXT} on ${planeName} ${bg}`,\n );\n }\n }\n\n // The filled-surface pairing: text-on against the solid it names.\n const solid = resolve(tokens['bg-solid'] as string);\n const onLc = contrastLc(tokens['text-on'] as string, solid);\n if (onLc < CONTRAST.SECONDARY)\n fail(appearance, `text-on Lc ${onLc.toFixed(1)} < ${CONTRAST.SECONDARY} on bg-solid`);\n\n // The inverse surface, where it exists.\n if (tokens['bg-bold'] != null && tokens['text-on-bold'] != null) {\n const lc = contrastLc(resolve(tokens['text-on-bold'] as string), resolve(tokens['bg-bold']));\n if (lc < CONTRAST.TEXT)\n fail(appearance, `text-on-bold Lc ${lc.toFixed(1)} < ${CONTRAST.TEXT} on bg-bold`);\n }\n }\n return failures;\n}\n","/**\n * OKF documentation bundle generator (ported from the repo's `generate-docs.ts`).\n *\n * Pure: `generateDocs(ds, assetsDir)` returns a `{ relPath: markdown }` map for the\n * Open Knowledge Format tree (top index, css/, bricks/), reading the Bricks element\n * PHP from `<assetsDir>/bricks/elements`. No filesystem writes — the caller decides\n * where the bundle lands (e.g. `<outDir>/docs`).\n */\nimport { readFileSync, readdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { jsonSchema, SCHEMA_URL, type DesignSystem } from './schema.ts';\nimport { configJsonSchema, CONFIG_SCHEMA_URL } from './config.ts';\nimport { BASE_HOOK, DARK_SEL, REQUIRED_ROLES, SYSTEM_DARK_SEL, TW_CLASH } from './shared.ts';\nimport { expandPalette } from './tokens.ts';\n\nconst DS_PATH = 'design-system.json';\n/** The `resource` a config-reference doc points at. Consumers rename it freely. */\nconst CONFIG_PATH = 'site.json';\n\n// Curated element display order (by $name, sans the vitops- prefix). Unlisted\n// elements fall to the end alphabetically so new ones still appear.\nconst ORDER = [\n 'split',\n 'centered',\n 'carousel',\n 'color-scheme-toggle',\n 'wc-copy',\n 'dismissable',\n 'entries',\n 'image-compare',\n 'sitenav',\n 'wc-multifield',\n 'split-link',\n 'split-panel',\n];\n\n// ── PHP array-literal parser ─────────────────────────────────────────────────\ntype Json = string | number | boolean | null | Json[] | { [k: string]: Json };\n\ninterface Tok {\n t: 'str' | 'num' | 'id' | 'punc' | 'arrow';\n v: string;\n}\n\nfunction tokenize(src: string): Tok[] {\n const toks: Tok[] = [];\n let i = 0;\n const n = src.length;\n while (i < n) {\n const c = src[i] as string;\n if (c === ' ' || c === '\\t' || c === '\\n' || c === '\\r') {\n i++;\n continue;\n }\n if (c === '/' && src[i + 1] === '/') {\n while (i < n && src[i] !== '\\n') i++;\n continue;\n }\n if (c === '#') {\n while (i < n && src[i] !== '\\n') i++;\n continue;\n }\n if (c === '/' && src[i + 1] === '*') {\n i += 2;\n while (i < n && !(src[i] === '*' && src[i + 1] === '/')) i++;\n i += 2;\n continue;\n }\n if (c === \"'\" || c === '\"') {\n const quote = c;\n i++;\n let s = '';\n while (i < n && src[i] !== quote) {\n if (src[i] === '\\\\' && i + 1 < n) {\n const next = src[i + 1];\n s += next === 'n' ? '\\n' : next === 't' ? '\\t' : next;\n i += 2;\n } else {\n s += src[i++];\n }\n }\n i++;\n toks.push({ t: 'str', v: s });\n continue;\n }\n if (c === '=' && src[i + 1] === '>') {\n toks.push({ t: 'arrow', v: '=>' });\n i += 2;\n continue;\n }\n if ('[](){},'.includes(c)) {\n toks.push({ t: 'punc', v: c });\n i++;\n continue;\n }\n if (\n (c >= '0' && c <= '9') ||\n (c === '-' && (src[i + 1] as string) >= '0' && (src[i + 1] as string) <= '9')\n ) {\n let s = c;\n i++;\n while (i < n && (src[i] as string) >= '0' && (src[i] as string) <= '9') s += src[i++];\n toks.push({ t: 'num', v: s });\n continue;\n }\n if (/[A-Za-z_\\\\]/.test(c)) {\n let s = c;\n i++;\n while (i < n && /[A-Za-z0-9_\\\\]/.test(src[i] as string)) s += src[i++];\n toks.push({ t: 'id', v: s });\n continue;\n }\n i++;\n }\n return toks;\n}\n\nclass Parser {\n p = 0;\n toks: Tok[];\n constructor(toks: Tok[]) {\n this.toks = toks;\n }\n peek(): Tok | undefined {\n return this.toks[this.p];\n }\n next(): Tok | undefined {\n return this.toks[this.p++];\n }\n parseValue(): Json {\n const t = this.peek();\n if (!t) return null;\n if (t.t === 'str') {\n this.next();\n return t.v;\n }\n if (t.t === 'num') {\n this.next();\n return Number(t.v);\n }\n if (t.t === 'id') {\n this.next();\n if (t.v === 'true') return true;\n if (t.v === 'false') return false;\n if (t.v === 'null') return null;\n if (this.peek()?.t === 'punc' && this.peek()?.v === '(') {\n this.next();\n if (t.v === 'array') return this.parseBody(')');\n const args = this.parseCallArgs();\n return args.find((a) => typeof a === 'string') ?? args[0] ?? '';\n }\n return t.v;\n }\n if (t.t === 'punc' && t.v === '[') {\n this.next();\n return this.parseBody(']');\n }\n if (t.t === 'punc' && t.v === '(') {\n this.next();\n return this.parseBody(')');\n }\n this.next();\n return null;\n }\n private parseCallArgs(): Json[] {\n const args: Json[] = [];\n while (this.peek() && !(this.peek()!.t === 'punc' && this.peek()!.v === ')')) {\n args.push(this.parseValue());\n if (this.peek()?.t === 'punc' && this.peek()?.v === ',') this.next();\n }\n this.next();\n return args;\n }\n private parseBody(close: string): Json {\n const list: Json[] = [];\n const map: Record<string, Json> = {};\n let keyed = false;\n while (this.peek() && !(this.peek()!.t === 'punc' && this.peek()!.v === close)) {\n const first = this.parseValue();\n if (this.peek()?.t === 'arrow') {\n this.next();\n const val = this.parseValue();\n // PHP array keys are scalars; stringify objects defensively.\n map[typeof first === 'object' && first !== null ? JSON.stringify(first) : String(first)] =\n val;\n keyed = true;\n } else {\n list.push(first);\n }\n if (this.peek()?.t === 'punc' && this.peek()?.v === ',') this.next();\n }\n this.next();\n return keyed ? map : list;\n }\n}\n\nfunction parsePhpLiteral(text: string): Json {\n return new Parser(tokenize(text)).parseValue();\n}\n\n// ── Source-region helpers ────────────────────────────────────────────────────\nfunction matchBalanced(src: string, open: number): number {\n const pairs: Record<string, string> = { '(': ')', '[': ']', '{': '}' };\n const stack: string[] = [];\n let i = open;\n const n = src.length;\n while (i < n) {\n const c = src[i] as string;\n if (c === '/' && src[i + 1] === '/') {\n while (i < n && src[i] !== '\\n') i++;\n continue;\n }\n if (c === '/' && src[i + 1] === '*') {\n i += 2;\n while (i < n && !(src[i] === '*' && src[i + 1] === '/')) i++;\n i += 2;\n continue;\n }\n if (c === \"'\" || c === '\"') {\n i++;\n while (i < n && src[i] !== c) {\n if (src[i] === '\\\\') i++;\n i++;\n }\n i++;\n continue;\n }\n if (c in pairs) stack.push(pairs[c] as string);\n else if (c === ')' || c === ']' || c === '}') {\n if (stack.pop() !== c) {\n /* unbalanced — best effort */\n }\n if (stack.length === 0) return i + 1;\n }\n i++;\n }\n return n;\n}\n\nfunction methodBody(src: string, name: string): string | null {\n const m = new RegExp(`function\\\\s+${name}\\\\s*\\\\([^)]*\\\\)`).exec(src);\n if (!m) return null;\n const brace = src.indexOf('{', m.index + m[0].length);\n if (brace < 0) return null;\n const end = matchBalanced(src, brace);\n return src.slice(brace + 1, end - 1);\n}\n\nfunction literalAt(src: string, fromIdx: number): { text: string; end: number } | null {\n let i = fromIdx;\n while (i < src.length && /\\s/.test(src[i] as string)) i++;\n let open: number;\n if (src[i] === '[') open = i;\n else if (src.startsWith('array', i)) open = src.indexOf('(', i);\n else return null;\n const end = matchBalanced(src, open);\n return { text: src.slice(i, end), end };\n}\n\n// ── Per-element extraction ───────────────────────────────────────────────────\ninterface Control {\n key: string;\n def: Record<string, Json>;\n}\ninterface Element {\n name: string;\n label: string;\n nestable: boolean;\n docblock: string;\n controls: Control[];\n cssClass: string | null;\n children: string[];\n keywords: string[];\n}\n\nfunction firstString(re: RegExp, src: string): string | null {\n const m = re.exec(src);\n return m ? (m[1] ?? null) : null;\n}\n\nfunction extractDocblock(src: string): string {\n const m = /\\/\\*\\*([\\s\\S]*?)\\*\\//.exec(src);\n if (!m) return '';\n const lines = (m[1] as string)\n .split('\\n')\n .map((l) => l.replace(/^\\s*\\*?\\s?/, '').replace(/\\s+$/, ''));\n while (lines.length && lines[0] === '') lines.shift();\n if (lines.length && /Bricks Builder\\)\\./.test(lines[0] as string)) lines.shift();\n const owned = lines.findIndex((l) => l.startsWith('Owned by the framework repo'));\n const kept = (owned >= 0 ? lines.slice(0, owned) : lines).map((l) => l.replace(/^•\\s*/, '- '));\n while (kept.length && kept[kept.length - 1] === '') kept.pop();\n while (kept.length && kept[0] === '') kept.shift();\n return kept.join('\\n');\n}\n\nfunction extractControls(src: string): Control[] {\n const body = methodBody(src, 'set_controls');\n if (!body) return [];\n const controls: Control[] = [];\n const re = /\\$this->controls\\[\\s*'([^']+)'\\s*\\](\\[\\s*'([^']+)'\\s*\\])?\\s*=\\s*/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body))) {\n const key = m[1] as string;\n if (m[2]) continue;\n const lit = literalAt(body, m.index + m[0].length);\n if (!lit) continue;\n const def = parsePhpLiteral(lit.text);\n if (def && typeof def === 'object' && !Array.isArray(def))\n controls.push({ key, def: def as Record<string, Json> });\n re.lastIndex = lit.end;\n }\n return controls;\n}\n\nfunction extractChildren(src: string): string[] {\n const body = methodBody(src, 'get_nestable_children');\n if (!body) return [];\n const labels: string[] = [];\n const re = /'label'\\s*=>\\s*esc_html__\\(\\s*'([^']*)'/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body))) labels.push(m[1] as string);\n return labels;\n}\n\nfunction extractKeywords(src: string): string[] {\n const body = methodBody(src, 'get_keywords');\n if (!body) return [];\n const ret = /return\\s+/.exec(body);\n if (!ret) return [];\n const lit = literalAt(body, ret.index + ret[0].length);\n if (!lit) return [];\n const arr = parsePhpLiteral(lit.text);\n return Array.isArray(arr) ? arr.filter((x): x is string => typeof x === 'string') : [];\n}\n\nfunction parseElement(src: string): Element | null {\n const name = firstString(/public\\s+\\$name\\s*=\\s*'vitops-([^']+)'/, src);\n if (!name) return null;\n return {\n name,\n label:\n firstString(/function get_label\\(\\)[\\s\\S]*?return\\s+esc_html__\\(\\s*'([^']*)'/, src) ?? name,\n nestable: /public\\s+\\$nestable\\s*=\\s*true/.test(src),\n docblock: extractDocblock(src),\n controls: extractControls(src),\n cssClass: firstString(\n /\\$this->controls\\[\\s*'_cssClasses'\\s*\\]\\[\\s*'default'\\s*\\]\\s*=\\s*'([^']*)'/,\n src,\n ),\n children: extractChildren(src),\n keywords: extractKeywords(src),\n };\n}\n\n// ── Markdown rendering ───────────────────────────────────────────────────────\n/** Stringify a parsed-PHP Json value for prose (objects → JSON, not [object Object]). */\nconst asText = (v: Json | undefined): string =>\n v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);\n\nfunction controlLine(c: Control): string {\n const def = c.def;\n if (def.type === 'info') return `- _Note:_ ${asText(def.content)}`;\n const label = (def.label as string) || c.key;\n const options =\n def.options && typeof def.options === 'object' && !Array.isArray(def.options)\n ? (def.options as Record<string, string>)\n : null;\n const meta: string[] = [];\n let type = (def.type as string) || 'text';\n if (def.units === true) type += '+units';\n meta.push(type);\n if (def.default !== undefined) {\n const raw = asText(def.default);\n const shown = options && options[raw] ? options[raw] : raw;\n meta.push(`default \\`${shown}\\``);\n }\n if (def.placeholder !== undefined && def.placeholder !== '')\n meta.push(`placeholder \\`${asText(def.placeholder)}\\``);\n if (def.min !== undefined || def.max !== undefined)\n meta.push(\n `range ${def.min != null ? asText(def.min) : '–'}–${def.max != null ? asText(def.max) : '∞'}`,\n );\n const tail: string[] = [];\n if (def.description) tail.push(asText(def.description));\n if (options)\n tail.push(\n `Options: ${Object.values(options)\n .map((o) => `\\`${o}\\``)\n .join(', ')}.`,\n );\n if (Array.isArray(def.css) && def.css.length) {\n const first = def.css[0];\n if (first && typeof first === 'object' && !Array.isArray(first) && 'property' in first)\n tail.push(`Bound to \\`${asText((first as Record<string, Json>).property)}\\`.`);\n }\n if (def.type === 'repeater' && def.fields && typeof def.fields === 'object') {\n const fields = Object.values(def.fields as Record<string, Json>)\n .map((f) =>\n f && typeof f === 'object' && !Array.isArray(f)\n ? asText((f as Record<string, Json>).label)\n : null,\n )\n .filter(Boolean);\n if (fields.length) tail.push(`Fields: ${fields.join(', ')}.`);\n }\n const head = `- **${label}** (${meta.join(', ')})`;\n return tail.length ? `${head} — ${tail.join(' ')}` : head;\n}\n\nfunction renderElement(el: Element): string {\n const out: string[] = [];\n const nest = el.nestable ? 'nestable' : 'not nestable';\n out.push(`## ${el.label} — \\`vitops-${el.name}\\` · ${nest}`);\n out.push('');\n if (el.docblock) {\n out.push(el.docblock);\n out.push('');\n }\n const real = el.controls.filter((c) => c.def.type !== 'info');\n if (real.length) {\n out.push('**Controls**');\n out.push('');\n for (const c of el.controls) out.push(controlLine(c));\n out.push('');\n } else {\n const notes = el.controls.filter((c) => c.def.type === 'info');\n if (notes.length) {\n for (const c of notes) out.push(controlLine(c));\n out.push('');\n }\n }\n if (el.cssClass) {\n out.push(\n `**Base CSS class:** \\`${el.cssClass}\\` (applied automatically; add ratio/modifier classes alongside it in the element's \"CSS classes\" field).`,\n );\n out.push('');\n }\n if (el.children.length) {\n out.push(`**Seeded children:** ${el.children.join(', ')}.`);\n out.push('');\n }\n if (el.keywords.length) {\n out.push(`**Keywords:** ${el.keywords.filter((k) => k !== 'vitops').join(', ')}.`);\n out.push('');\n }\n return out.join('\\n');\n}\n\n// ── OKF helpers ──────────────────────────────────────────────────────────────\ninterface Frontmatter {\n type: string;\n title: string;\n description: string;\n resource?: string;\n tags?: string[];\n}\nfunction frontmatter(fm: Frontmatter): string {\n const q = (s: string) => `\"${s.replace(/\"/g, '\\\\\"')}\"`;\n const lines = [\n `type: ${q(fm.type)}`,\n `title: ${q(fm.title)}`,\n `description: ${q(fm.description)}`,\n ];\n if (fm.resource) lines.push(`resource: ${q(fm.resource)}`);\n if (fm.tags) lines.push(`tags: [${fm.tags.join(', ')}]`);\n lines.push('generator: \"@getvitops/generator\"');\n return `---\\n${lines.join('\\n')}\\n---`;\n}\n\nconst INDEX_NOTE = `<!-- GENERATED by @getvitops/generator — do not edit; regenerate with \\`vitops generate\\`. -->`;\n\nconst ELEMENTS_FRONTMATTER = frontmatter({\n type: 'Bricks Elements Reference',\n title: 'Vitops — Bricks Builder elements reference',\n description:\n 'Every repo-owned Bricks element, its controls, defaults, seeded children and keywords, for driving the Bricks Builder UI.',\n resource: 'bricks/elements',\n tags: ['bricks', 'wordpress', 'elements', 'design-system'],\n});\n\nconst ELEMENTS_PREAMBLE = `${ELEMENTS_FRONTMATTER}\n\n# Vitops — Bricks Builder elements reference\n\nContext for driving the Bricks Builder UI (e.g. Claude for Chrome). Every section below\nis generated from the element's own source, so this reference always matches the elements\ncurrently deployed. See also the CSS class vocabulary in [/css/classes.md](../css/classes.md)\nand the integration guidance in [/bricks/index.md](index.md).\n\n## How they appear in the builder\n\n- The elements register from \\`dist/bricks/load.php\\` and group under a **\"Vitops\"** category\n pinned to the **top** of the element panel. Insert one by searching its **label** (e.g.\n \"Split\", \"Carousel\") or any of its **keywords** (listed per element).\n- Two rendering families:\n - **Web-component elements** render a Lit custom element (\\`<wc-*>\\`, \\`<wc-copy>\\`, …)\n from \\`dist/elements.js\\` and progressively enhance. A few (Image Compare, Split Panel)\n show their children stacked in the builder canvas until the client-side upgrade runs —\n that is expected, not broken.\n - **CSS-pattern elements** (Split, Centered, Menu, Split Link) render plain markup styled\n by the framework CSS — no JS dependency.\n- **Nestable** elements accept child elements dropped into them; some seed starter children\n (listed as \"Seeded children\"). **Non-nestable** elements are configured entirely through\n their controls.\n\n## Configuring layout\n\nSome layout is set through **controls**; some through **CSS classes typed into the element's\nbuilt-in \"CSS classes\" field** (called out per element as modifier classes). Responsive\nsuffixes on those classes engage from a container breakpoint: \\`-sm\\` = 30rem, \\`-md\\` = 48rem,\n\\`-lg\\` = 64rem, \\`-xl\\` = 80rem.\n\nEach control below lists its type, default/placeholder, any select options, and the CSS\ncustom property it writes (when it drives one). Info notes flagged _Note:_ carry the\nmodifier-class and structural guidance from the element itself.\n\n---\n`;\n\nfunction renderElementsDoc(elementsDir: string): string {\n const files = existsSync(elementsDir)\n ? readdirSync(elementsDir).filter((f) => f.endsWith('.php'))\n : [];\n const elements: Element[] = [];\n for (const f of files) {\n try {\n const el = parseElement(readFileSync(join(elementsDir, f), 'utf8'));\n if (el) elements.push(el);\n } catch {\n /* skip unparseable element */\n }\n }\n elements.sort((a, b) => {\n const ia = ORDER.indexOf(a.name);\n const ib = ORDER.indexOf(b.name);\n if (ia >= 0 && ib >= 0) return ia - ib;\n if (ia >= 0) return -1;\n if (ib >= 0) return 1;\n return a.name.localeCompare(b.name);\n });\n const body = elements.map(renderElement).join('\\n---\\n\\n');\n return `${ELEMENTS_PREAMBLE}\\n${body}`;\n}\n\n// ── CSS framework reference (rule-summarized, from the config) ────────────────\nconst code = (xs: string[]) => xs.map((x) => `\\`${x}\\``).join(', ');\n\nfunction renderCssClasses(ds: DesignSystem): string {\n const expanded = expandPalette(ds.colors.palette as Record<string, unknown>);\n const ramps = Object.keys(expanded);\n const roles = Object.keys(ds.colors.roles ?? {});\n const utils = ds.colors.utilities ?? ['bg', 'text', 'icon', 'border'];\n const typeRoles = Object.keys(ds.typography?.roles ?? {});\n const shadows = Object.keys(ds.shadows ?? {});\n const effects = Object.keys(ds.animations?.effects ?? {});\n // Split by keyframe family, because only composite/paint effects get the\n // hover-/focus-/active- state variants — `.transition` deliberately doesn't\n // transition `height`, so a `hover-size-grow` would be a class that resolves\n // to nothing. Listing every effect under \"with the state prefixes above\" is\n // what sent the docs site rendering exactly that.\n const stateful = Object.entries(ds.animations?.effects ?? {})\n .filter(([, e]) => e.kf === 'composite' || e.kf === 'paint')\n .map(([name]) => name);\n const keyframeOnly = effects.filter((name) => !stateful.includes(name));\n const items = (ds.patterns?.items ?? {}) as Record<\n string,\n { roles?: string[]; default_role?: string }\n >;\n const patterns = Object.keys(items);\n const patternRoles = Array.from(\n new Set(\n Object.values(items).flatMap(\n (p) => [p.default_role, ...(p.roles ?? [])].filter(Boolean) as string[],\n ),\n ),\n );\n const spaceNames = ds.spaceScale?.names ?? [];\n const typeNames = ds.typeScale?.names ?? [];\n const families = Object.keys(ds.typography?.families ?? {});\n const radii = Object.keys(ds.patterns?.radii ?? {});\n\n return `${frontmatter({\n type: 'CSS Framework Reference',\n title: 'Vitops CSS framework — class vocabulary',\n description:\n 'Every utility and component class in the Vitops CSS framework, stated as a naming rule over the design tokens it expands.',\n resource: DS_PATH,\n tags: ['css', 'utilities', 'patterns', 'design-system'],\n })}\n\n# Vitops CSS framework — class vocabulary (LLM reference)\n\nA variable-driven CSS framework. Classes encode the design system's **tokens** (colour,\ntype, space, shadow), **responsive grammar**, and **interaction states** — so styling with\nthese classes stays consistent and theme-/dark-mode-aware. Prefer them over hand-written\nCSS or ad-hoc property values.\n\nThis is a **rule reference**, not an exhaustive list: each family below is a naming rule\nplus the set of tokens it expands over. Applying a rule to any listed token yields a valid\nclass (e.g. rule \\`bg-<color>\\` + colour \\`pine-xl\\` → \\`bg-pine-xl\\`).\n\nThe tokens themselves are authored in \\`design-system.json\\` — see\n[/authoring.md](../authoring.md); the systems behind them are explained in\n[/concepts/](../concepts/index.md); per-format output differences (including which of\nthese utilities Tailwind provides natively) in [/formats.md](../formats.md).\n\n## Responsive & state variant grammar\n\nEvery utility accepts a **container-breakpoint prefix**; animation utilities also accept a\n**state prefix**. In CSS/Bricks the separator is \\`-\\`; in Tailwind it is \\`:\\` / \\`@\\`.\n\n| Intent | CSS / Bricks | Tailwind |\n| ----------------- | -------------------------- | ----------------------------------------- |\n| responsive split | \\`md-split-1-2\\` | \\`@md:split-1-2\\` |\n| responsive align | \\`md-items-center\\` | \\`@md:items-center\\` |\n| hover effect | \\`transition hover-fade-in\\` | \\`transition fade-in hover:flip-fade-in\\` |\n\n- Breakpoint prefixes (bare): \\`sm-\\` = 30rem, \\`md-\\` = 48rem, \\`lg-\\` = 64rem, \\`xl-\\` = 80rem.\n- State prefixes (animation effects only): \\`hover-\\`, \\`active-\\`, \\`focus-\\`, and \\`flip-<effect>\\`\n (plays the effect in reverse on toggle). Effects require \\`transition\\` on the element.\n\n## Layout & structure\n\n- **\\`centered\\`** — named-track grid centering content in the reading \\`measure\\` track.\n Widen a **direct child** by adding \\`breakout\\`, \\`spotlight\\`, or \\`fullbleed\\` (each\n breakpoint-prefixable) to that child. Track widths are set via \\`--width-measure\\` /\n \\`--width-breakout\\` / \\`--width-spotlight\\` and \\`--gutter\\`.\n- **\\`rhythm\\`** — relationship-based vertical spacing (margins between headings, paragraphs,\n lists, media) driven by the space scale. Usually paired with \\`centered\\`.\n- **\\`split\\`** — a two-column pair. Ratio rule: **\\`split-<a>-<b>\\`** where \\`<a>-<b>\\` ∈\n \\`1-2\\`, \\`2-1\\`, \\`1-3\\`, \\`3-1\\`, \\`1-4\\`, \\`4-1\\`, \\`2-3\\`, \\`3-2\\` (breakpoint-prefixable); equal\n columns without one. The ratio is a flex **basis**, so a column's padding counts\n inside its share, and \\`min-inline-size: 0\\` is built in so long unbreakable content\n can't stretch a column past it.\n - **Stacking is \\`flex-col\\`** — there is no split-specific class for it:\n \\`class=\"split flex-col md-split-1-2\"\\` is stacked below 48rem and 1:2 above,\n because the \\`<bp>-\\` ratio classes assert the row. While stacked the ratio goes\n inert on its own (a percentage basis against an auto-height column resolves as\n \\`content\\`), unless you give the split a definite \\`block-size\\`.\n - **\\`split-reverse\\`** — swaps the two panels (breakpoint-prefixable). Implemented\n as \\`order\\` on the first child, so it reverses on whichever axis the split is\n currently on: bare, it swaps the columns in a row AND the rows in a stack;\n scoped (\\`md-split-reverse\\`) it swaps only once there are two columns — media\n first in source so it leads on mobile, on the right at width. The ratio stays\n with the source-first child, not with the visual position.\n - **Accessibility:** reversing makes visual order disagree with DOM order, and\n focus order follows the DOM (WCAG 2.4.3 Focus Order). Put focusable content in\n **only one** of the two panels, or the tab order will not be linear. The\n pattern declares \\`reading-flow: flex-visual\\`, which fixes this properly where\n it is supported; support is not yet broad enough to rely on.\n- **Flex** — \\`flex\\`, \\`flex-row\\`, \\`flex-col\\`, \\`flex-row-reverse\\`, \\`flex-col-reverse\\`\n (all breakpoint-prefixable).\n- **Alignment** — \\`items-{start,center,end,stretch}\\`, \\`justify-{start,center,end,between}\\`,\n text align \\`text-{start,center,end}\\` (all breakpoint-prefixable).\n- **Display** — \\`block\\`, \\`inline\\`, \\`inline-block\\`, \\`flex\\`, \\`grid\\`, \\`hidden\\`\n (breakpoint-prefixable, e.g. \\`md-hidden\\`).\n- **Accessibility** — \\`sr-only\\` / \\`not-sr-only\\` (breakpoint-prefixable).\n- **State hooks** — \\`is-active\\`, \\`is-open\\` (styling flags toggled by JS / native state).\n\n## Spacing\n\nThe space scale is ${code(spaceNames)} exposed as \\`--space-<name>\\` tokens.\n\\`rhythm\\` margins consume these tokens; prefer \\`rhythm\\` for vertical flow rather than\nper-element margins.\n\nRule: **\\`gap-<name>\\`**, **\\`gap-x-<name>\\`** (column) and **\\`gap-y-<name>\\`** (row), name ∈\n${code(spaceNames)} — all breakpoint-prefixable (\\`md-gap-l\\`, \\`@md:gap-l\\`). These are the\nframework's own utilities in every format: the fluid steps are deliberately kept out of\nTailwind's \\`--spacing-*\\` namespace (named keys there shadow the size scales, so\n\\`max-w-7xl\\` would resolve to \\`var(--spacing-7xl)\\`), which means Tailwind's numeric\n\\`gap-4\\` still uses its own multiplier and coexists with these.\n\n## Typography\n\nRule: **\\`font-<role>\\`** — role ∈ ${code(typeRoles)}. Each role carries its own family,\nsize (from the type scale ${code(typeNames)}), tracking, transform, weight and \\`text-wrap\\`.\nFamilies: ${code(families)} (\\`--font-*\\`).\n\nBecause the role owns \\`text-wrap\\`, a heading is balanced and copy is \\`pretty\\` with **no\nclass at all** wherever \\`typography.headings\\` maps the bare element to a role. Override one\nelement with \\`text-{wrap,nowrap,balance,pretty}\\` — the per-element escape hatch, for markup\nthat carries no role class. (These four are Tailwind's own in the tailwind format.)\n\n## Colour\n\n**Functional tokens are the primary vocabulary** — classes name the *job*, not the tone, and\nevery one remaps automatically under \\`${DARK_SEL}\\` (background/text ends\nswap; \\`solid\\` fills stay mode-stable with a computed \\`on-\\` foreground). Prefer these over\nraw steps.\n\n**Role names are yours.** \\`colors.roles\\` is an open map: add a key, and the generator emits\nthat role's full token set, its dark flip and every utility below. Your config\ncurrently defines ${code(roles)}. Six of those are a **required core** — the framework's own\ncomponent CSS references \\`${REQUIRED_ROLES.join('`, `')}\\` with no fallback, so removing one\nleaves those components uncoloured (\\`vitops validate\\` warns). Everything beyond them is free.\n\nThe rule is one shape — **\\`<target>-<role>[-<variant>]\\`**, target ∈ \\`bg\\` \\`text\\` \\`icon\\`\n\\`border\\` — and the class name is exactly its token name minus \\`--color-\\`. Variants are\nordinal (\\`xx-muted\\` < \\`x-muted\\` < \\`muted\\` < bare < \\`bold\\` < \\`x-bold\\`) and sparse: only the\ncells that hold their contrast target exist.\n\n**Which cells exist depends on the role's \\`kind\\`:**\n\n*Surface roles* (page and panel colours):\n\n- **Backgrounds** — \\`bg-<role>\\` (the card/panel), \\`bg-<role>-muted\\` (the page behind it),\n \\`bg-<role>-x-muted\\` (well / inset), \\`bg-<role>-bold\\` and \\`-x-bold\\` (inverse surface).\n Elevation is *which* token you reach for, not a raised/sunken pair.\n- **Content** — \\`text-<role>\\` (body), \\`text-<role>-bold\\`, \\`text-<role>-muted\\` (secondary),\n \\`text-<role>-x-muted\\` (placeholder) and \\`-xx-muted\\` (disabled). The last two are\n contrast-exempt by design.\n- **Borders** — \\`border-<role>-muted\\` (hairline), \\`border-<role>\\`, \\`border-<role>-bold\\`\n (the one guaranteed to carry a boundary on its own).\n\n*Chromatic roles* (signal colours) — **there is no bare \\`bg-<role>\\`**; say tint or solid:\n\n- **Tints** — \\`bg-<role>-x-muted\\` (alert wash), \\`bg-<role>-muted\\` (badge).\n- **Solids** — \\`bg-<role>-solid\\`, \\`-solid-bold\\` (hover), \\`-solid-x-bold\\` (active), each\n pairing with \\`text-on-<role>\\` for a guaranteed-contrast foreground.\n- **Content** — \\`text-<role>\\`, \\`text-<role>-bold\\`. There is deliberately no\n \\`text-<role>-muted\\`: it could not hold its contrast target off a light surface, so soften\n coloured text with weight or size instead.\n- **Borders** — \\`border-<role>\\`, \\`border-<role>-bold\\` (decorative status edges).\n\nBoth kinds also get **\\`icon-<role>\\`** — a separate non-text tier, so a glyph may run more\nvivid than text — plus \\`glass\\` (translucent surface + backdrop blur), the \\`--overlay\\` scrim\nand \\`--color-border-focus\\` for focus rings.\n\nEveryday pairings, using the roles this config defines: page\n\\`bg-${roles[0] ?? 'neutral'}-muted\\`, cards \\`bg-${roles[0] ?? 'neutral'}\\` on top of it, body\n\\`text-${roles[0] ?? 'neutral'}\\`, captions \\`text-${roles[0] ?? 'neutral'}-muted\\`; buttons\n\\`bg-${roles[2] ?? roles[0] ?? 'ui-primary'}-solid text-on-${roles[2] ?? roles[0] ?? 'ui-primary'}\\`;\nalerts \\`bg-danger-x-muted text-danger\\`.\n\n**Raw scale** (secondary / fine control) — rule \\`<util>-<hue>-<step>\\` with util ∈\n${code(utils)}: every hue is an 11-step OKLCH scale generated from its seed (or fixed brand\ntones), numeric steps \\`50\\` … \\`950\\` (tinted near-white → tinted near-black) — e.g.\n\\`bg-${ramps[0] ?? 'brand'}-100\\`, \\`text-${ramps[0] ?? 'brand'}-800\\`. Hues: ${code(ramps)}.\n\n> **Raw scale classes are frozen — they do NOT remap in dark mode.**\n> \\`bg-${ramps[0] ?? 'brand'}-800\\` is that exact colour in every appearance. The automatic\n> dark flip described above applies **only** to the functional role tokens, because\n> \\`--color-<hue>-<step>\\` is emitted once and never re-pointed under \\`${DARK_SEL}\\`.\n> A raw step on a page that can switch appearance is a latent bug: it looks correct in\n> whichever mode you built it in and inverts in the other.\n>\n> If you are reaching for a raw step, you usually want a **role** instead — and roles are\n> extensible, so adding one is a two-line config change:\n>\n> | instead of | use | why |\n> | --- | --- | --- |\n> | \\`bg-<hue>-50\\` / \\`-950\\` | \\`bg-<role>\\` (surface kind) | the card plane, flips automatically |\n> | \\`bg-<hue>-100\\` / \\`-900\\` | \\`bg-<role>-muted\\` | the page, or a chromatic tint |\n> | \\`bg-<hue>-500\\`…\\`-700\\` | \\`bg-<role>-solid\\` | vivid fill, mode-stable, pairs with \\`text-on-<role>\\` |\n> | \\`text-<hue>-950\\` / \\`-50\\` | \\`text-<role>\\` | contrast-guaranteed body text |\n> | \\`text-<hue>-800\\` / \\`-200\\` | \\`text-<role>-muted\\` | secondary text |\n> | \\`border-<hue>-200\\` / \\`-800\\` | \\`border-<role>\\` | |\n>\n> Raw steps stay the right tool for genuinely fixed colours — a brand mark, a chart series,\n> an illustration — where the value must not move between appearances.\n\n## Shadows\n\nRule: **\\`drop-shadow-<size>\\`** — size ∈ ${code(shadows)} (applied as a \\`filter\\`, so it\nfollows non-rectangular shapes).\n\n## Animation\n\nAn effect carries no motion of its own — it sets \\`--<prop>-from\\`/\\`-to\\` and picks a keyframe.\nA **driver** supplies the motion, and you always compose one of each:\n\n- \\`animate-view\\` — plays as the element crosses the viewport\n- \\`animate-scroll\\` — scrubs against page scroll\n- \\`animate-trigger\\` — time-based; plays once when \\`.is-active\\` / \\`[data-active]\\` is set\n- \\`transition\\` — transitions the same from/to vars, so it reverses on a state flip\n\nRule: **\\`<effect>\\`** — effect ∈ ${code(effects)}. The state/flip prefixes above pair with\n\\`transition\\` and apply to every one of them.\n\nEach state matches the element **or its direct parent** (\\`.hover-<fx>:hover, :hover > .hover-<fx>\\`),\nwhich is what makes \\`reveal-*\\` usable: it rests at a zero-area \\`clip-path\\`, and \\`clip-path\\` clips\nhit-testing as well as painting, so the element itself can never be hovered.${\n keyframeOnly.length\n ? `\n\n${code(keyframeOnly)} animate \\`height\\`, the only stage that reflows and the only one behind a\nfeature gate: \\`0 → auto\\` is not interpolable without \\`interpolate-size: allow-keywords\\`, so\n\\`transition\\` declares \\`height\\` only inside an \\`@supports\\` for it. The \\`layout\\` **keyframe**\nhas the same dependency — this is not a limit of the transition driver.`\n : ''\n }\n\n**When it plays.** \\`animate-view\\` and \\`.is-active\\` are both timed off the element's **midpoint**:\nmotion starts once that midpoint is 10% of the viewport in, and a one-shot entrance completes at\n25%. Both stops are the element's position on screen rather than a fraction of its own height, so a\nsmall card and a full-bleed section behave alike. Shift the window with \\`--anim-start\\` /\n\\`--anim-end\\`, or replace it outright with \\`--anim-range\\`.\n\nComposed **journeys** chain multiple effects into one entrance: rule \\`<parts>-journey\\`\n(e.g. \\`fade-slide-journey\\`, \\`fade-scale-blur-journey\\`). They need a **keyframe** driver, not\n\\`transition\\`. A journey is entry → hold → exit, so it starts on that same 10% pivot but runs to the\nend of the exit phase — the hold occupies the middle of the crossing instead of the bottom edge of\nthe screen.\n\n**\\`stagger\\`** on a parent offsets each child by \\`--stagger-amount\\` (time-based drivers) and by\n\\`--stagger-range-step\\` (scroll-driven ones — \\`animation-delay\\` is ignored on a progress-based\ntimeline). Journeys set an explicit range and opt out.\n\n## Component patterns\n\nEach pattern is a base class \\`<pattern>\\` with interaction states (hover/active/focus-visible)\nbaked in; coloured patterns add role variants via rule **\\`<pattern>-<role>\\`**. (How the\npattern CSS is assembled — token cascade, \\`--p-<pattern>\\`-style override hooks, state\nshortcuts — is explained in [/concepts/patterns.md](../concepts/patterns.md).)\n\n- Patterns: ${code(patterns)}.\n- Roles (for coloured patterns — \\`badge\\`, \\`tag\\`, \\`status\\`, \\`cta\\`, \\`btn\\`, …):\n ${code(patternRoles)} — e.g. \\`badge-success\\`, \\`cta-danger\\`. A pattern that also styles an\n element accepts the bare role class too (\\`<button class=\"danger\">\\`). The default\n (unsuffixed) variant uses the pattern's \\`default_role\\`.\n- Shape primitives: \\`--br-<name>\\` radii — ${code(radii)}.\n`;\n}\n\n// ── design-system.json authoring reference (walked from the JSON Schema) ─────\n// Field docs are rendered from `jsonSchema`'s `description` metadata (authored\n// once in schema.ts via `desc()`), so this reference cannot drift from validation.\n\ninterface JsonSchemaNode {\n type?: string;\n description?: string;\n properties?: Record<string, JsonSchemaNode>;\n required?: string[];\n additionalProperties?: JsonSchemaNode | boolean;\n anyOf?: JsonSchemaNode[];\n items?: JsonSchemaNode;\n enum?: unknown[];\n}\n\nconst isPrimitive = (n: JsonSchemaNode): boolean =>\n !n.properties && !n.anyOf && n.type != null && n.type !== 'object' && n.type !== 'array';\n\nfunction typeLabel(node: JsonSchemaNode): string {\n if (node.enum) return node.enum.map(String).join(' | ');\n if (node.anyOf)\n return node.anyOf.every(isPrimitive) ? node.anyOf.map((v) => v.type).join(' | ') : 'one of';\n if (node.type === 'array') {\n const it = node.items;\n if (it?.enum) return `array of ${it.enum.map(String).join(' | ')}`;\n return it?.type && it.type !== 'object' ? `array of ${it.type}` : 'array';\n }\n if (node.type === 'object') {\n const ap = node.additionalProperties;\n return ap && typeof ap === 'object' ? 'map' : 'object';\n }\n return node.type ?? 'value';\n}\n\n/** A node's documentable children: object properties, map values, or array items. */\nfunction childEntries(\n node: JsonSchemaNode,\n): Array<{ label: string; node: JsonSchemaNode; required: boolean }> {\n if (node.properties) {\n const req = node.required ?? [];\n return Object.entries(node.properties).map(([k, v]) => ({\n label: k,\n node: v,\n required: req.includes(k),\n }));\n }\n const ap = node.additionalProperties;\n if (ap && typeof ap === 'object' && (ap.description || ap.properties || ap.anyOf))\n return [{ label: '<name>', node: ap, required: false }];\n if (node.items && (node.items.description || node.items.properties || node.items.anyOf))\n return [{ label: '[items]', node: node.items, required: false }];\n return [];\n}\n\nfunction renderSchemaNode(\n label: string,\n node: JsonSchemaNode,\n required: boolean,\n depth: number,\n out: string[],\n): void {\n const indent = ' '.repeat(depth);\n const meta = `(${typeLabel(node)}${required ? ', required' : ''})`;\n out.push(`${indent}- \\`${label}\\` ${meta}${node.description ? ` — ${node.description}` : ''}`);\n if (depth >= 3) return;\n if (node.anyOf && !node.anyOf.every(isPrimitive)) {\n for (const variant of node.anyOf) {\n out.push(`${indent} - *one of*${variant.description ? ` — ${variant.description}` : ''}`);\n for (const c of childEntries(variant))\n renderSchemaNode(c.label, c.node, c.required, depth + 2, out);\n }\n return;\n }\n for (const c of childEntries(node)) renderSchemaNode(c.label, c.node, c.required, depth + 1, out);\n}\n\n/**\n * One `## <key>` section per top-level property: its description, then its\n * fields as a bullet tree. Shared by both references so the two cannot drift in\n * presentation — only in which schema they are pointed at.\n */\nfunction schemaSections(schema: JsonSchemaNode, heading = '##'): string[] {\n const required = schema.required ?? [];\n const sections: string[] = [];\n for (const [key, node] of Object.entries(schema.properties ?? {})) {\n if (key === '$schema') continue;\n const parts: string[] = [\n `${heading} \\`${key}\\`${required.includes(key) ? '' : ' *(optional)*'}`,\n ];\n if (node.description) parts.push('', node.description);\n const bullets: string[] = [];\n for (const c of childEntries(node)) renderSchemaNode(c.label, c.node, c.required, 0, bullets);\n if (bullets.length) parts.push('', ...bullets);\n sections.push(parts.join('\\n'));\n }\n return sections;\n}\n\nfunction renderAuthoring(): string {\n const sections = schemaSections(jsonSchema as unknown as JsonSchemaNode);\n return `${frontmatter({\n type: 'Config Reference',\n title: 'Vitops — design-system.json authoring reference',\n description:\n 'Every field of the design-system.json config, generated from the published JSON Schema so it always matches validation.',\n resource: DS_PATH,\n tags: ['config', 'schema', 'authoring', 'design-system'],\n })}\n\n# \\`design-system.json\\` authoring reference\n\nThe single source of truth every output format is generated from. Each consumer authors\ntheir own config — there is no shared canonical token set. The field docs below are\nrendered from the published JSON Schema, so they always match what \\`vitops validate\\`\nenforces.\n\n- Set \\`\"$schema\": \"${SCHEMA_URL}\"\\` in the config for editor autocomplete + validation.\n- Scaffold a starter config with \\`vitops init\\`; check one with \\`vitops validate\\`.\n- **This can be a standalone file, or live inside a site config.** Anywhere the\n toolchain takes a config — \\`--input\\`, the Vite plugin, the Astro integration's\n \\`css.input\\` — that file may be a \\`design-system.json\\` or the larger site config\n that embeds one under \\`designSystem.themes.<name>\\`. They are told apart by shape,\n and the fields below are the same either way. A site config additionally supplies\n the site-level facts generation reads (its default colour scheme, legal documents,\n icon sprite), so the path is declared once rather than per option.\n- The *why* behind each section: [colour system](concepts/color.md),\n [type & space scales](concepts/scales.md), [component patterns](concepts/patterns.md).\n- What each output format does with these tokens: [formats.md](formats.md).\n\n${sections.join('\\n\\n')}\n`;\n}\n\n// ── Config authoring reference (walked from the site JSON Schema) ────────────\n// The same walker, pointed at the other published schema. Everything a consumer\n// can say about their *company* and their *site* — as opposed to their tokens —\n// is described here, and it is generated rather than written so it cannot claim\n// a field validation does not accept.\n\nfunction renderConfig(): string {\n const schema = configJsonSchema as unknown as JsonSchemaNode;\n const props = schema.properties ?? {};\n const required = schema.required ?? [];\n\n // The top level is three sections, so rendering it the way `authoring.md`\n // renders `design-system.json` would put ~23 unrelated fields under one\n // heading. Each section gets a `##`; each of ITS fields gets a `###`.\n const sections = Object.entries(props).map(([key, node]) => {\n const head = [\n `## \\`${key}\\`${required.includes(key) ? '' : ' *(optional)*'}`,\n ...(node.description ? ['', node.description] : []),\n ].join('\\n');\n // `designSystem` is documented in full by authoring.md; here it needs only\n // its own wrapper fields, not a second copy of the whole token schema.\n const fields = schemaSections(node, '###').join('\\n\\n');\n if (key === 'designSystem')\n return [\n head,\n 'The token set. Its `themes.<name>` entries are full design systems — every field of\\none is in [authoring.md](authoring.md). Only the wrapper is listed here.',\n fields,\n ].join('\\n\\n');\n return [head, fields].join('\\n\\n');\n });\n\n return `${frontmatter({\n type: 'Config Reference',\n title: 'Vitops — config authoring reference',\n description:\n 'Every field of the three-section config (designSystem / organization / site), generated from the published JSON Schema so it always matches validation.',\n resource: CONFIG_PATH,\n tags: ['config', 'schema', 'authoring', 'site', 'organization'],\n })}\n\n# Config authoring reference\n\nThe document that describes a **whole project**: the token set, the company, and the\npublished site. It is the input every command that needs more than tokens is anchored\nto — \\`vitops legal\\`, \\`vitops icons\\`, \\`vitops indexing\\` — and it can also stand in for\na \\`design-system.json\\` anywhere the toolchain takes one, since it carries a full\n\\`designSystem\\`.\n\nConsumers name the file whatever suits them (\\`site.json\\`, \\`company.json\\`,\n\\`vitops.config.json\\`); it is recognised by **shape**, not by name — a document with a\ntop-level \\`designSystem\\` key is this, and one without it is a bare\n\\`design-system.json\\`.\n\n- Set \\`\"$schema\": \"${CONFIG_SCHEMA_URL}\"\\` in the config for editor autocomplete + validation.\n- Check one with \\`vitops validate\\`.\n\n## The three sections\n\n| Section | Holds | Changes when |\n| --- | --- | --- |\n| \\`designSystem\\` | the token set — named themes, which theme, which appearance | the brand's design changes |\n| \\`organization\\` | the company — name, contact, locations, services, profiles | the company changes |\n| \\`site\\` | this published site — locales, domains, environments, SEO, analytics, legal, icons, deployment | this site changes |\n\nThe split is what makes the multi-site case expressible: several sites can carry the\nsame \\`organization\\` and differ only in \\`site\\`. It is also what the generated legal\ndocuments rely on — a privacy policy asserts facts about the *company* (who to contact,\nwhere it is) and facts about the *site* (which forms exist, which analytics run), and\nthose two are separately true.\n\n**Fields are described where they are, not where they were.** If you are migrating a\npre-3.0 flat config, \\`vitops validate\\` names every move rather than reporting a dozen\nunknown keys.\n\n${sections.join('\\n\\n')}\n`;\n}\n\n// ── Output formats reference ──────────────────────────────────────────────────\nfunction renderFormats(ds: DesignSystem): string {\n const clashList = Array.from(TW_CLASH).sort();\n const spaceName = ds.spaceScale?.baseline ?? ds.spaceScale?.names?.[0] ?? 'm';\n return `${frontmatter({\n type: 'Formats Reference',\n title: 'Vitops — output formats (tailwind vs css vs bricks vs design)',\n description:\n 'What each vitops generate format emits, what the target platform provides instead, and the Tailwind-specific rules (which framework utilities are stripped in favour of Tailwind defaults).',\n resource: DS_PATH,\n tags: ['formats', 'tailwind', 'bricks', 'css', 'design', 'design-system'],\n })}\n\n# Output formats — \\`tailwind\\` vs \\`css\\` vs \\`bricks\\` vs \\`design\\`\n\nOne config, four targets: \\`vitops generate --format <tailwind|css|bricks|design>\\`. Three of\nthem are stylesheets, and across those the **class vocabulary is the same** (see\n[css/classes.md](css/classes.md)); what differs is which layers the generator emits versus\nwhich the platform provides, and the variant separator (\\`-\\` in CSS/Bricks, \\`:\\` / \\`@\\` in\nTailwind). The fourth, \\`design\\`, emits no CSS at all.\n\n\\`--format\\` takes a comma-separated list, so the brief composes with a stylesheet:\n\\`vitops generate --format css,design\\`.\n\n## \\`tailwind\\` — single-file Tailwind v4 layer\n\nEmits one self-contained \\`tailwind.css\\` (plus \\`tokens.json\\`): \\`@import \"tailwindcss\"\\`,\n\\`@theme\\` tokens, the framework's structural CSS + component patterns inlined, and\n\\`@utility\\` definitions for the bespoke families (type roles, animation effects,\nsplit ratios, track placement).\n\n**Use Tailwind's own utilities for these class names.** The framework's rules for them are\ndeliberately stripped from the bundle because Tailwind provides them natively — writing\nthem still works, but they are Tailwind's, not the framework's:\n\n${clashList.map((c) => `\\`${c}\\``).join(', ')}\n\nOther Tailwind-specific behaviour:\n\n- **Variants are Tailwind's job.** No pre-expanded breakpoint/state classes are emitted\n (the framework's \\`@container (min-width: …)\\` **variant** blocks are dropped; component\n container queries such as the sitenav's desktop switch are kept); use Tailwind syntax —\n \\`@md:split-1-2\\`, \\`hover:flip-fade-in\\`. Container breakpoints are registered as\n \\`--container-{sm,md,lg,xl}\\` = 30/48/64/80rem, backing the \\`@sm:\\`…\\`@xl:\\` variants.\n\n > **Three spellings, and only two of them work here.**\n >\n > | you write | in \\`tailwind\\` | note |\n > | --- | --- | --- |\n > | \\`@md:flex-row\\` | ✅ container query | the framework's breakpoints (48rem) |\n > | \\`md:flex-row\\` | ✅ media query | **Tailwind's** breakpoints, which differ — \\`sm:\\` is 40rem where \\`@sm:\\` is 30rem |\n > | \\`md-flex-row\\` | ❌ silently nothing | the css/bricks spelling; not emitted in this format |\n >\n > \\`md-*\\` is the trap: it is a real class in \\`css\\`/\\`bricks\\` and a no-op here, and\n > nothing errors — the element simply never changes at the breakpoint. Prefer \\`@md:\\`\n > so one vocabulary of breakpoints applies throughout.\n\n- **Overriding \\`--container-*\\` also moves Tailwind's width scale.** Registering the\n framework breakpoints in \\`@theme\\` re-points \\`max-w-sm\\`…\\`max-w-xl\\` at the same values,\n so \\`max-w-md\\` is 48rem here rather than Tailwind's stock 28rem. Use\n \\`max-w-(--container-md)\\` style arbitrary values if you need to be explicit.\n- **The space scale is NOT mapped into Tailwind's \\`--spacing-*\\` namespace** (that would\n corrupt Tailwind's numeric multipliers and \\`max-w-*\\` sizes). Numeric utilities like\n \\`p-4\\` keep Tailwind's 0.25rem meaning; use the design-system scale via arbitrary\n values — \\`p-(--space-${spaceName})\\`, \\`gap-(--space-${spaceName})\\`.\n- **Functional colour roles are plain \\`:root\\` variables, not \\`@theme\\` colours**, so\n Tailwind doesn't auto-derive utilities from them; the emitted \\`@utility\\` set\n (\\`bg-<role>\\`, \\`text-<role>-muted\\`, …) is the public API. The raw hue scales ARE\n \\`@theme\\` colours, so native \\`bg-<hue>-500\\`-style utilities work.\n\n This split is deliberate and load-bearing. When a token sits in \\`@theme\\` *and* an\n \\`@utility\\` of the derived name exists, Tailwind merges both into one rule with the\n \\`@theme\\` declaration last — regardless of source order. Only palette hues belong in\n \\`@theme\\`, where nothing competes for the name. Role tokens stay in a plain \\`:root\\`\n block, and \\`format-parity.test.ts\\` derives that guard from the emitted token names so\n it cannot go quiet if the grammar moves again.\n- **\\`colors.utilities\\` is a floor here, not a ceiling.** It controls which families get\n explicit role \\`@utility\\` rules, exactly as in \\`css\\`/\\`bricks\\`. But the raw hue scales\n are \\`@theme\\` colours, and Tailwind derives *every* colour family from those on demand\n (\\`ring-\\`, \\`divide-\\`, \\`accent-\\`, \\`caret-\\`, …), so hue-step utilities you did not enable\n still resolve in this format.\n\n## \\`css\\` — standalone bundle\n\nEmits a bundled, self-contained \\`styles.css\\` + \\`tokens.json\\` + \\`design-manifest.json\\`.\nThe colour and font/scale layers are fully included, and every utility family is\npre-expanded — including breakpoint/state variants with \\`-\\` separators\n(\\`md-split-1-2\\`, \\`hover-fade-in\\`). For non-Bricks, non-Tailwind consumers and the\ndocs build.\n\n**Cascade layers.** The bundle ships three, in precedence order:\n\n\\`\\`\\`\n@layer vitops.base, vitops.components, vitops.utilities;\n\\`\\`\\`\n\n- \\`vitops.base\\` — the reset (\\`box-sizing: border-box\\` on every element and pseudo-element,\n a 16px root, no body margin) and the pure \\`:root\\` token blocks. Lowest of the three, so\n your own reset overrides it — unlayered, or from a layer you declare before \\`vitops.base\\`.\n- \\`vitops.components\\` — the animation engine, the structural patterns (\\`.rhythm\\`,\n \\`.centered\\`, \\`.region\\`, \\`.split\\`, \\`.reveal\\`) and every UI pattern.\n- \\`vitops.utilities\\` — \\`bg-*\\`, \\`text-*\\`, \\`border-*\\`, \\`drop-shadow-*\\`, \\`font-*\\`,\n \\`gap-*\\`, animation effects, the layout utilities (\\`.m-*\\`, \\`.flex-*\\`, \\`.items-*\\`,\n \\`.split-<a>-<b>\\`, track placement) and the display/\\`sr-only\\` families.\n\nSo a utility overrides a pattern: \\`class=\"card bg-danger-muted\"\\` tints the card,\n\\`class=\"split flex-col\"\\` stacks the split, \\`class=\"table text-center\"\\` centres the table.\nYour own unlayered CSS beats all three — see [concepts/patterns.md](concepts/patterns.md) for\nthe override story and the one gotcha (a reset must be layered and ordered first).\n\nThe classification is by RULE, not by file: a partial that mixes patterns and utilities is\nsplit in two rather than shelved whole. \\`layout.css\\` (patterns) and \\`layout-utilities.css\\`\n(utilities) are the same family in two files for exactly this reason, and the \\`tailwind\\`\nformat reaches the same arrangement by its own route — patterns in \\`@layer components\\`,\nutilities as \\`@utility\\`.\n\nKnown gap: the \\`typography.headings\\` bare-element bindings (\\`h1\\`, \\`h2\\`, \\`body\\`) are\nemitted alongside \\`.font-<role>\\` and so sit in \\`vitops.utilities\\`, where a tag rule\noutranks every pattern — \\`<h2 class=\"pull-quote\">\\` keeps the heading's font-size in\n\\`css\\`/\\`bricks\\` and the pattern's in \\`tailwind\\`, which puts the bindings in \\`@layer base\\`.\nGive the element a \\`.font-<role>\\` class to pin it either way.\n\n## \\`bricks\\` — WordPress / Bricks Builder payload\n\nEmits the full deployable theme payload: \\`styles.min.css\\`, the Bricks import JSONs\n(\\`bricks-colors-{named,semantic}.json\\`, \\`bricks-variables.json\\`), \\`tokens.json\\`, the JS\nbundles (polyfills / elements / deferred), the Bricks element PHP under \\`bricks/\\`, and\nthis docs bundle under \\`docs/\\`.\n\n- **Bricks provides the token layer.** \\`color.css\\` and \\`type-tokens.css\\` are one-line\n stubs: the colour \\`:root\\` tokens, dark-mode overrides, colour utility classes, fonts,\n and type/space scales are generated live by Bricks' Color / Font / Variables Managers\n from the imported JSONs. Semantic palette entries carry \\`darkModeEnabled\\` + a \\`dark\\` ref so\n Bricks emits the dark-mode overrides on import.\n- Everything else (patterns, shadows, typography roles, animation effects, structural\n framework CSS) ships in \\`styles.min.css\\` as in the other formats.\n- Pattern states reference shadows by name, compiled to\n \\`filter: drop-shadow(var(--shadow-<name>))\\`.\n\n## \\`design\\` — the agent-facing brief\n\nEmits exactly one file, \\`DESIGN.md\\`, in the\n[google-labs-code/design.md](https://github.com/google-labs-code/design.md) format: YAML\nfront matter carrying the tokens (\\`colors\\`, \\`typography\\`, \\`rounded\\`, \\`spacing\\`,\n\\`components\\`, with \\`{group.token}\\` references) followed by a prose body carrying the\nrationale. It is meant to be run with \\`--out .\\` — DESIGN.md conventionally sits at a repo\nroot beside \\`AGENTS.md\\`, not in a build directory.\n\n**No CSS, no \\`tokens.json\\`, nothing else.** This format is a description of the system for\na tool that has to work without it — a coding agent in another repo, a Figma import, a\ndesigner. It is not a build target, and \\`vitops lint\\` does not accept it.\n\nThree things the format cannot represent, and what is emitted instead:\n\n| Ours | Why it doesn't fit | Emitted as |\n| --- | --- | --- |\n| fluid \\`clamp()\\` type / space steps | a spec \\`Dimension\\` is a number + px/em/rem | the **max** (desktop) value, with the prose saying so |\n| the automatic dark flip | the spec has no notion of a second appearance | **light** values only, with the flip explained in prose |\n| a \\`50%\\` radius | same \\`Dimension\\` restriction | dropped from \\`rounded\\`, named in the Shapes prose |\n\nRole tokens are emitted as \\`{colors.<hue>-<step>}\\` **references** into the raw ramps rather\nthan flattened hexes, so the role → ramp lineage survives the export. \\`on-solid\\` is the\nexception — it is a computed contrast literal with no step behind it.\n\n\\`meta.name\\` / \\`meta.description\\` in \\`design-system.json\\` supply the brand name and the\nOverview paragraph; everything else is derived from the config, so the brief cannot drift\nfrom what the other three formats build.\n`;\n}\n\n// ── Concept docs (colour / scales / patterns) ─────────────────────────────────\nfunction renderColorConcept(ds: DesignSystem): string {\n const hues = Object.keys(ds.colors.palette ?? {});\n const roles = Object.keys(ds.colors.roles ?? {});\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops colour system — seeded scales, target-prefixed tokens, automatic dark mode',\n description:\n 'How palette hues become 11-step OKLCH scales on a shared lightness ladder, how semantic roles derive target-prefixed tokens from them, and how dark mode flips automatically.',\n resource: DS_PATH,\n tags: ['color', 'oklch', 'dark-mode', 'design-system'],\n })}\n\n# Colour system\n\nAuthoring is two maps in \\`design-system.json\\` (see [authoring.md](../authoring.md)):\n\\`colors.palette\\` (hues) and \\`colors.roles\\` (semantic role → hue). Everything else —\nscales, role tokens, utilities, dark mode — is derived.\n\n## From seed to scale\n\nEach palette hue becomes an **11-step numeric OKLCH scale**, \\`--color-<hue>-50…950\\`,\nrunning tinted near-white → tinted near-black. Two authoring modes:\n\n- **Seeded** (\\`{ seed, anchors? }\\`): the scale is generated from one colour. The seed is\n preserved at its natural lightness step; \\`anchors\\` pin specific steps and the rest\n interpolate around them.\n- **Fixed** (\\`{ tones }\\`): a brand kit used verbatim — each authored tone lands at its\n nearest step, endpoints are tinted off-white/off-black, no interpolation.\n\nCurrent hues: ${code(hues)}.\n\n## The token grammar\n\nEvery colour token is named:\n\n\\`\\`\\`\n--color-<target>-<role>[-<variant>] target ∈ bg | text | icon | border\n\\`\\`\\`\n\nThe target sits **inside** the name on purpose. \\`--color-bg-danger-muted\\` and\n\\`--color-text-danger-muted\\` are different tokens, so there is nothing to arbitrate between\nthem — an earlier grammar put both on one \\`<family>-<role>-<modifier>\\` name and needed a\nprecedence rule, which made half the variants unreachable and the rest non-monotonic.\n\n**The token name is also the utility class name**, minus the \\`--color-\\` prefix. Write\n\\`class=\"bg-danger-muted\"\\` and you are using \\`--color-bg-danger-muted\\`. One vocabulary, not\ntwo (see [css/classes.md](../css/classes.md)).\n\nVariants are ordinal — \\`xx-muted\\` < \\`x-muted\\` < \\`muted\\` < (bare) < \\`bold\\` < \\`x-bold\\` — and\nthe tables are **sparse**: only cells that actually hold their contrast target exist.\n\\`bold\\` means *more emphatic in the current appearance*, not darker.\n\n## Role kinds\n\nA role in \\`colors.roles\\` (currently ${code(roles)}) is one of two kinds, and the kind decides\nwhich tokens exist:\n\n- **\\`surface\\`** — a page or panel colour. \\`bg-<role>\\` is the card, \\`bg-<role>-muted\\` the page\n behind it, \\`bg-<role>-x-muted\\` a well, \\`bg-<role>-bold\\` the inverse surface a tooltip sits\n on. Full text scale, and \\`border-<role>-bold\\` as the contrast-guaranteed boundary.\n- **\\`chromatic\\`** (the default, and what the bare-string form means) — a signal colour.\n Backgrounds split into *tints* (\\`bg-<role>-x-muted\\`, \\`bg-<role>-muted\\`) and *solids*\n (\\`bg-<role>-solid\\`, \\`-solid-bold\\`, \\`-solid-x-bold\\`). There is deliberately **no bare\n \\`bg-<role>\\`**: \"how loud?\" is a question the author answers. \\`text-on-<role>\\` is the\n guaranteed foreground for the solid family.\n\nPlus \\`--surface-glass\\` (translucent surface), \\`--overlay\\` (scrim) and\n\\`--color-border-focus\\` (the focus ring, taken from \\`ui-primary\\`'s solid tone).\n\n## Automatic dark mode\n\nDark mode re-points which step each token reads, under \\`${DARK_SEL}\\`:\nbackground and text ends of each scale swap, while the **solid family stays mode-stable**\nalong with the \\`text-on-<role>\\` foreground computed against it — so a filled button keeps\nits identity when the appearance flips. There is no per-appearance scheme grammar to author\nand no named steps: a role token means the same *job* in both appearances.\n\nRaw hue steps (\\`--color-<hue>-<step>\\`) are the exception — they are fixed values and are\n**not** re-pointed. Reach for a role token unless you specifically want a colour that\nignores the appearance.\n\nTwo attributes, one flip: \\`data-brx-theme\\` is Bricks' own (Bricks sets it on the\nWordPress target), \\`data-theme\\` is what the shipped \\`<color-scheme-toggle>\\` writes on\n\\`<html>\\`, so the toggle works on every other target. Set either.\n\nThe OS preference is a **second, opt-in block**. Set\n\\`designSystem.defaultColorScheme: \"system\"\\` in your site config and the same delta is emitted again inside\n\\`@media (prefers-color-scheme: dark)\\`, under\n\\`${SYSTEM_DARK_SEL}\\` — i.e. whenever no explicit choice has been made. That is what makes\n\\`<color-scheme-toggle>\\`'s \"System\" position resolve to the OS (it *removes* the attribute,\nso without this block it fell through to light), and it gives a no-JS page the OS\nappearance, which the toggle alone never could. An explicit light choice still wins.\n\nIt is opt-in rather than default because turning it on flips a site dark for dark-OS\nvisitors, which is the site's decision and not the design system's.\n\n## Contrast guarantees\n\nEnforced **at build time** — a violation fails \\`generate\\`, so an unreadable pairing cannot\nship. In both appearances:\n\n| tier | target | applies to |\n| --- | --- | --- |\n| text | APCA Lc ≥ 75 | \\`text-<role>\\` on the role's primary background |\n| secondary | Lc ≥ 60 | text on any other background plane; \\`text-<role>-muted\\`; \\`text-on-<role>\\` on its solid |\n| non-text | Lc ≥ 45 | \\`icon-<role>\\`, and a surface role's \\`border-<role>-bold\\` |\n\nTwo deliberate exemptions: \\`text-<role>-x-muted\\` (placeholders) and \\`-xx-muted\\` (disabled\ntext) are *required* to look unavailable, and holding them to the body-text bar would defeat\nthe affordance. Nothing else is exempt.\n\nChromatic text is checked against the **surface planes it actually sits on**, not only its\nown tints — coloured text appears over the page far more often than over its own wash.\n\nA \\`tones\\` kit thin enough that snapping can't cover a tier is reported rather than shipped;\nthe fix is another tone, and the failure says so.\n`;\n}\n\nfunction renderScalesConcept(ds: DesignSystem): string {\n const t = ds.typeScale;\n const s = ds.spaceScale;\n const scaleLine = (label: string, sc: typeof t): string =>\n sc\n ? `- **${label}**: base \\`${sc.base}\\` at step \\`${sc.names?.[(sc.baseStep ?? 1) - 1] ?? sc.baseStep}\\`, ratio ${sc.ratio}${sc.fluid ? ` (${sc.fluid.minRatio} below ${sc.fluid.minVw})` : ''}; steps ${code(sc.names ?? [])}.`\n : `- **${label}**: not configured.`;\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops type & space scales — fluid modular scales',\n description:\n 'How typeScale and spaceScale compile to clamp()-based fluid modular scales, and which utilities consume the resulting tokens.',\n resource: DS_PATH,\n tags: ['typography', 'spacing', 'fluid', 'modular-scale', 'design-system'],\n })}\n\n# Type & space scales\n\nBoth scales share one model (authored in \\`design-system.json\\` as \\`typeScale\\` /\n\\`spaceScale\\` — see [authoring.md](../authoring.md)): a **fluid modular scale**.\n\n## The model\n\n- \\`base\\` anchors the value at \\`baseStep\\`; every other step is a power of the \\`ratio\\`\n away (step n = base × ratio^(n − baseStep)).\n- With \\`fluid\\`, each step compiles to a **\\`clamp()\\`**: the scale uses \\`fluid.minRatio\\`\n at/below \\`fluid.minVw\\` and grows to \\`ratio\\` at \\`fluid.maxVw\\`, interpolating between —\n so large steps spread apart on wide viewports and compress on phones, with no\n breakpoint jumps. \\`baseline\\` names the pivot step that stays closest to \\`base\\`.\n- \\`names\\` become the token suffixes.\n\n${scaleLine('Type', t)}\n${scaleLine('Space', s)}\n\n## What consumes them\n\n- **Type**: \\`--text-<name>\\` tokens → typography role sizes (\\`font-<role>\\` classes,\n heading defaults) and text-size utilities.\n- **Space**: \\`--space-<name>\\` tokens → gap (\\`g\\`), spacing utilities, and \\`rhythm\\`\n (relationship-based vertical margins between headings, paragraphs, lists, media).\n Prefer \\`rhythm\\` for vertical flow over per-element margins.\n- In the \\`tailwind\\` format these stay in their own namespaces (\\`--text-*\\` via \\`@theme\\`,\n \\`--space-*\\` as plain vars) — see [formats.md](../formats.md) for why \\`--spacing-*\\` is\n deliberately not used.\n`;\n}\n\nfunction renderPatternsConcept(ds: DesignSystem): string {\n const items = (ds.patterns?.items ?? {}) as Record<string, { group?: string }>;\n const groups = Object.keys(ds.patterns?.groups ?? {});\n const patternNames = Object.keys(items);\n const hookTable = Object.entries(BASE_HOOK)\n .map(([prop, sfx]) => `| \\`${prop}\\` | \\`--${sfx}-<pattern>\\` |`)\n .join('\\n');\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops component patterns — token cascade, override hooks, states',\n description:\n 'How pattern CSS is assembled: the token cascade (defaults → groups → per-pattern overrides), per-pattern override-hook variables, state shortcuts, and role variants.',\n resource: DS_PATH,\n tags: ['patterns', 'components', 'cascade', 'css', 'design-system'],\n })}\n\n# Component patterns — the CSS chain\n\nPatterns (currently ${code(patternNames)}) are authored declaratively under \\`patterns\\` in\n\\`design-system.json\\` (see [authoring.md](../authoring.md)) and compiled to CSS in a\n**components cascade layer** — so utility classes, which live in a later layer, always win over\npattern styling without specificity fights. \\`class=\"card bg-danger-muted\"\\` tints the card.\n\nThe layer names differ by format, because each defers to its host:\n\n| format | layer stack (last wins) |\n| --- | --- |\n| \\`css\\`, \\`bricks\\` | \\`vitops.base\\` → \\`vitops.components\\` → \\`vitops.utilities\\` |\n| \\`tailwind\\` | Tailwind's own \\`theme\\` → \\`base\\` → \\`components\\` → \\`utilities\\` |\n\n**Your own CSS beats all of it.** Unlayered styles outrank every cascade layer regardless of\nspecificity, so a plain stylesheet, an Astro scoped \\`<style>\\`, or a Bricks-authored class\noverrides the framework with no \\`!important\\` and no specificity escalation. That is the\nintended override story.\n\nThe one thing to watch: a **reset** must be layered too, and ordered *below* the framework —\nleft unlayered it beats the very component rules it is meant to sit under (a bare\n\\`p { margin: 0 }\\` would defeat \\`.rhythm\\`). Declare the order before you load the stylesheet,\nsince layer precedence is fixed by first declaration:\n\n\\`\\`\\`html\n<style>@layer my.reset, vitops.base, vitops.components, vitops.utilities;</style>\n<link rel=\"stylesheet\" href=\"/styles.css\">\n\\`\\`\\`\n\nPut it *after* the link and \\`my.reset\\` becomes a new name introduced later — which sorts\n**last**, i.e. highest priority, and the reset wins. That is the one non-obvious step.\n\n## 1 — Token cascade\n\nShared geometry resolves through a variable chain, most-specific first:\n\n- \\`patterns.defaults\\` → \\`--<prop>-default\\` (cascade-wide fallbacks).\n- \\`patterns.groups.<group>\\` → \\`--<prop>-<group>\\` (e.g. groups ${code(groups)}); a pattern\n opts in via its \\`group\\` key.\n- Per-pattern: each grouped pattern gets aliases \\`--<prop>-<name>-group\\` →\n \\`var(--<prop>-<group>)\\`, and \\`overrides\\` replace individual aliases with literal values.\n- \\`patterns.radii\\` → \\`--br-<name>\\` shape primitives; \\`patterns.z\\` → \\`--z-tier-<name>\\`.\n\n## 2 — Base declarations & override hooks\n\nEach pattern's \\`base\\` block is emitted on its selector:\n\n- \\`class\\` only → \\`.<class ?? name>\\`, at normal class specificity.\n- \\`element\\` only → a **zero-specificity** \\`:where(<element>)\\` rule, so author CSS can always\n override it.\n- **both** → one \\`:where(<element>, .<class>)\\` rule (e.g. \\`:where(button, .btn)\\`). The element\n gets the styling with no class needed, the class carries it to any other tag, and — because the\n whole thing sits at zero specificity — any explicit class wins, including a louder pattern\n (\\`.cta\\`) or a component's own rule (\\`.dialog__close\\`).\n\nGeometry properties are wrapped in a **per-pattern override hook**:\n\n| base property | hook variable |\n| --- | --- |\n${hookTable}\n\ne.g. \\`padding: var(--p-btn, 0.4em 0.8em)\\` — a consumer restyles every button by setting\n\\`--p-btn\\` on \\`:root\\`, without touching the pattern. The hook is named after the pattern's\n**key**, not its class.\n\n\\`background\\` and \\`background-color\\` share the \\`bg\\` hook, since a pattern may author either.\nThat is what makes a pattern's fill **undoable** — a flat, border-only card:\n\n\\`\\`\\`html\n<!-- via the hook: applies wherever you set it, including :root for all cards -->\n<div class=\"card\" style=\"--bg-card: transparent; --ds-card: none\">…</div>\n\n<!-- or compose a utility, which reads better inline and is what most authors want -->\n<div class=\"card bg-transparent\" style=\"--ds-card: none\">…</div>\n\\`\\`\\`\n\n\\`bg-transparent\\` and \\`bg-inherit\\` are emitted for \\`css\\`/\\`bricks\\`; in \\`tailwind\\` they\ncome from Tailwind itself. There is no utility for the shadow, so \\`--ds-card: none\\` is the\nway to drop it in every format.\n\nRole variants are emitted as their own rules and are **not** wrapped, so setting \\`--bg-card\\`\ntunes the default fill without silently defeating \\`.card-danger\\`.\n\n## 3 — States\n\n\\`states\\` (hover / active / focus-visible) compile from shortcuts:\n\n- \\`step: n\\` — intensify the pattern's colour one rung: fills swap\n \\`--color-bg-<role>-solid\\` → \\`-solid-bold\\`; text patterns swap\n \\`--color-text-<role>\\` → \\`--color-text-<role>-bold\\`.\n- \\`scale: 0.97\\` — transform scale; \\`lift: \"<length>\"\\` — \\`translate: 0 calc(-1 * <length>)\\`.\n- \\`shadow: \"<name>\"\\` — \\`filter: drop-shadow(var(--shadow-<name>))\\`; \\`shadow: true\\` — the\n generic lift box-shadow.\n- \\`ring: true\\` — focus ring (\\`box-shadow\\` in the role's solid tone, or\n \\`--color-border-focus\\` when the pattern has no role; outline removed).\n- \\`css: { … }\\` — raw declarations escape hatch.\n\nAny pattern with states also gets a composed transition block (translate / scale / filter /\nbox-shadow / colours, \\`--interact-duration\\` / \\`--interact-easing\\` overridable). Hover\nrules are wrapped in \\`@media (hover: hover)\\` so touch devices never stick.\n\n## 4 — Role variants\n\n\\`roles\\` lists semantic colour variants: class patterns emit \\`.<pattern>-<role>\\`\n(\\`.badge-success\\`). A pattern with an \\`element\\` emits both the bare role class on the\nelement and the \\`-<role>\\` form (\\`:where(button, .btn).danger, .btn-danger\\`), so the same\nvariant works on a non-element host — both at class specificity, so neither outranks a\nplain class. Fill\npatterns set \\`background-color: var(--color-bg-<role>-solid)\\` +\n\\`color: var(--color-text-on-<role>)\\`; text patterns use \\`var(--color-text-<role>)\\`, the\ntoken guaranteed legible over a surface in both appearances. \\`default_role\\` colours the\nbare, unsuffixed pattern. States re-apply per variant with the variant's role.\n`;\n}\n\n// ── Reserved index.md listings (no frontmatter) ──────────────────────────────\nfunction renderTopIndex(): string {\n return `${INDEX_NOTE}\n\n# Vitops design system\n\nLLM-oriented documentation bundle (Open Knowledge Format) for the Vitops design system — a\nvariable-driven CSS framework plus progressively-enhanced web components, generated from\n\\`design-system.json\\` and published alongside the deployed theme.\n\n# Contents\n\n* [Authoring reference](authoring.md) - every design-system.json field, generated from the JSON Schema\n* [Config reference](config.md) - every field of the three-section config (designSystem / organization / site), generated from the JSON Schema\n* [Output formats](formats.md) - tailwind vs css vs bricks vs design: what's emitted, what the platform provides, which utilities Tailwind owns\n* [Concepts](concepts/) - the colour system, type/space scales, and pattern CSS architecture\n* [CSS framework](css/) - the class vocabulary (colour, type, space, layout, animation, component patterns), stated as naming rules\n* [Bricks Builder](bricks/) - custom elements and how to style them\n`;\n}\n\nfunction renderIconsConcept(): string {\n return `${frontmatter({\n type: 'Design Concept',\n title: 'Vitops icons — one semantic vocabulary across icon sets',\n description:\n 'Semantic icon names that resolve per configured set, how the bundle is derived on a server build, and the three delivery paths (astro-icon, astro-iconset, SVG sprite).',\n resource: DS_PATH,\n tags: ['icons', 'svg', 'sprite', 'astro-icon', 'design-system'],\n })}\n\n# Icons\n\nIcons are named by **meaning**, not by set. \\`menu\\` resolves to \\`fa7-solid:bars\\`,\n\\`lucide:menu\\` or \\`ph:list\\` depending on which set the site configures, so changing\nsets is a config edit rather than a find-and-replace across templates.\n\nThe escape hatch is deliberate and always available: **a name containing \\`:\\` passes\nthrough untouched**. \\`<Icon name=\"simple-icons:zoho\" />\\` renders that exact glyph\nwhether or not the semantic map knows it.\n\n## Declaring them\n\nThe \\`icons\\` block lives in the **site config**, not \\`design-system.json\\` — it\ndescribes what a site uses, not what the design system defines.\n\n\\`\\`\\`json\n{\n \"icons\": {\n \"ui\": \"ph\",\n \"brand\": \"simple-icons\",\n \"weight\": \"bold\",\n \"semantic\": [\"menu\", \"close\", \"arrow-right\"],\n \"simple-icons\": [\"zoho\", \"cloudflare\"],\n \"sprite\": true\n }\n}\n\\`\\`\\`\n\n\\`ui\\` and \\`brand\\` pick which set a semantic name resolves against. Any other key is\nan iconify collection name with an explicit list, passed through verbatim.\n\n**\\`weight\\` is only meaningful for sets that encode weight in the icon NAME.**\nPhosphor does (\\`list\\`, \\`list-bold\\`, \\`list-fill\\`), so \\`ph\\` accepts it; Font Awesome\nsplits weights across collections instead (\\`fa7-solid\\` vs \\`fa7-regular\\`), so there\nthe weight is part of the prefix and this key is ignored.\n\n## Why the bundle list exists\n\nastro-icon is **zero-config on a static build**. Under \\`output: 'server'\\` it bundles\n*every icon in a set* unless given an \\`include\\` map — which is why projects end up\nhand-maintaining one.\n\nThe \\`icons\\` option on \\`getvitops()\\` derives it by scanning your source, merged with\nwhatever you declare. On a static build **no include is passed at all**: there is\nnothing to trim there, and a list could only drop a glyph the scan couldn't see.\n\nTwo failure modes, treated differently on purpose:\n\n- A name you **declared** that doesn't resolve is a config error and **throws**.\n- A name only the **scan** found and can't resolve just **warns** — a bare unmapped\n name is more often a local \\`src/icons/*.svg\\` than a mistake, and a dev server\n that dies on a template typo is worse than one that tells you.\n\nNames computed at runtime (\\`<Icon name={expr} />\\`) can't be read statically. They are\nreported with file and line, never guessed at — declare them in \\`semantic\\` or a\nper-set list. Run \\`vitops icons\\` to see the whole report.\n\n## Delivery\n\n| Path | Used by | Needs |\n| --- | --- | --- |\n| \\`astro-icon\\` / \\`astro-iconset\\` | Astro sites | the integration, an optional peer |\n| **SVG sprite** (\\`icons.svg\\`) | Bricks/WordPress, EmDash renderers, plain HTML | \\`icons.sprite: true\\` |\n\nThe sprite is the no-JavaScript path: \\`<svg><use href=\"/vitops/icons.svg#ph--list\"></svg>\\`.\nIds are the qualified name with \\`:\\` replaced by \\`--\\` (\\`:\\` is not valid in a fragment\nidentifier), **plus a set-independent \\`icon-<name>\\` alias for every semantic name** —\nso sprite markup survives an icon-set change the same way \\`resolveIcon\\` protects Astro\ncall sites.\n\nIn WordPress, \\`vitops_icon('menu')\\` and \\`[vitops_icon name=\"menu\"]\\` emit that markup,\nand a **Vitops → Icon** Bricks element wraps the same helper.\n\n⚠️ An external-file \\`<use>\\` is **same-origin only** and dead under \\`file://\\`. Serving\n\\`dist/\\` from a different origin makes every icon vanish with no console error.\n\n## Markup\n\nAlways the framework's \\`.icon\\` box:\n\n\\`\\`\\`html\n<span class=\"icon\" aria-hidden=\"true\"><svg>…</svg></span>\n\\`\\`\\`\n\n\\`.icon\\` sizes in \\`em\\` via \\`--icon-size\\` (default \\`1.25em\\`) and sets \\`fill: currentColor\\`,\nso an icon inherits the colour of whatever it sits in. Because \\`.cta\\` and\n\\`:where(button, .btn)\\` are already \\`inline-flex\\` with a \\`gap\\`, **a start or end icon is\nchild order — not a modifier class**.\n\nIcons are \\`aria-hidden\\` by default. Pass a label only when the icon carries meaning on\nits own; beside a text label it would be announced twice.\n\nNote \\`.icon-mask\\` is a different thing: the CSS-only adornment path used by\n\\`.link--icon::before\\`, where the glyph is a \\`mask-image\\` on a pseudo-element and there\nis no markup to hang an \\`<svg>\\` on.\n`;\n}\n\nfunction renderConceptsIndex(): string {\n return `${INDEX_NOTE}\n\n# Design-system concepts\n\n# Contents\n\n* [Colour system](color.md) - seeded OKLCH scales on a shared lightness ladder, target-prefixed tokens, automatic dark mode\n* [Type & space scales](scales.md) - fluid modular scales and the tokens they emit\n* [Component patterns](patterns.md) - token cascade, override hooks, states, role variants\n* [Icons](icons.md) - semantic names across icon sets, bundle derivation, sprite delivery\n`;\n}\n\nfunction renderCssIndex(): string {\n return `${INDEX_NOTE}\n\n# CSS framework\n\n# Contents\n\n* [Class vocabulary](classes.md) - every utility and component class, summarized by naming rule\n`;\n}\n\nfunction renderBricksIndex(): string {\n return `${INDEX_NOTE}\n\n# Bricks Builder integration\n\n# Styling\n\nPrefer adding the framework **CSS classes** — see [/css/classes.md](../css/classes.md) — in a\nBricks element's \"CSS classes\" field over hand-setting spacing, colour, or typography through\nthe Bricks Builder property panels. The classes encode the design system's tokens, responsive\ngrammar, and interaction states, so they stay consistent, respond to theme / dark mode, and\nupdate with the system. Values typed directly into Bricks' property controls are one-off,\ndrift from the system, and don't react to theme changes — reserve them for genuinely bespoke,\none-element cases.\n\n# Contents\n\n* [Elements reference](elements.md) - every custom Vitops element, its controls, defaults, seeded children and keywords\n* [Class vocabulary](../css/classes.md) - the framework CSS classes to apply to elements\n`;\n}\n\n/**\n * Build the OKF docs bundle for a config. Returns a `{ relPath: content }` map;\n * the caller writes it wherever the bundle should live (e.g. `<outDir>/docs`).\n */\nexport function generateDocs(ds: DesignSystem, assetsDir: string): Record<string, string> {\n const elementsDir = join(assetsDir, 'bricks', 'elements');\n return {\n 'index.md': renderTopIndex(),\n 'authoring.md': renderAuthoring(),\n 'config.md': renderConfig(),\n 'formats.md': renderFormats(ds),\n 'concepts/index.md': renderConceptsIndex(),\n 'concepts/color.md': renderColorConcept(ds),\n 'concepts/scales.md': renderScalesConcept(ds),\n 'concepts/patterns.md': renderPatternsConcept(ds),\n 'concepts/icons.md': renderIconsConcept(),\n 'css/index.md': renderCssIndex(),\n 'css/classes.md': renderCssClasses(ds),\n 'bricks/index.md': renderBricksIndex(),\n 'bricks/elements.md': renderElementsDoc(elementsDir),\n };\n}\n","/**\n * `DESIGN.md` emitter — the `design` format.\n *\n * DESIGN.md (google-labs-code/design.md, alpha) is a single plain-text file that\n * gives AI coding agents a persistent, structured understanding of a visual\n * identity: YAML front matter carrying the tokens, then a prose body carrying the\n * *why*. It is the agent-facing sibling of `tokens.json` — where that file is a\n * verbatim dump for programmatic consumers, this one is curated for a reader.\n *\n * Three impedance mismatches between our schema and the spec, resolved the same\n * way every time (and stated in the prose so the file is self-describing):\n *\n * • **Fluid sizes are `clamp()`**; a spec `Dimension` is a bare number + px/em/rem.\n * → Emit the scale's **max** rem as the canonical size and say in the prose that\n * the real token is fluid. A `clamp()` string would fail every consumer's parse.\n * • **Dark mode has no first-class representation.** → `colors` carries the LIGHT\n * values; the Colors prose explains that the framework flips functionally at\n * runtime, so an agent that uses the role tokens gets dark mode for free and\n * should never hand-pick a dark value.\n * • **A role is not a ramp alias.** Functional tokens resolve to a ramp step, so\n * they are emitted as `{colors.<hue>-<step>}` **references** rather than\n * flattened hexes — that keeps the role → ramp lineage visible in the file,\n * which is the one thing a flattened export destroys. `on-solid` is the\n * exception: it is a computed contrast literal with no step behind it.\n */\nimport type { DesignSystem } from './schema.ts';\nimport { DARK_SEL, type RoleSpec, roleHue } from './shared.ts';\nimport { tokenClass, type ExpandedHue, type FunctionalRole } from './tokens.ts';\n\n/** Structural view of `generate.ts`'s ScaleStep (kept local to avoid a cycle). */\ninterface Step {\n name: string;\n value: string;\n max: string;\n}\n\nexport interface DesignMdCtx {\n ds: DesignSystem;\n expandedPalette: Record<string, ExpandedHue>;\n scaleRoles: FunctionalRole[];\n typeSteps: Step[];\n spaceSteps: Step[];\n shadows: Record<string, string> | undefined;\n}\n\ninterface PatternItem {\n group?: string;\n overrides?: Record<string, string>;\n element?: string;\n class?: string;\n fill?: boolean;\n default_role?: string;\n base?: Record<string, string>;\n states?: Record<string, Record<string, unknown>>;\n roles?: string[];\n}\n\n// ── minimal YAML writer ───────────────────────────────────────────────────────\n// Hand-rolled rather than pulled in as a dependency: the generator emits a fixed,\n// known shape (scalars two levels deep), and every string is double-quoted so\n// nothing here has to reason about YAML's plain-scalar edge cases — `#RRGGBB`\n// starting a comment, `{colors.x}` reading as a flow mapping, `2xl` as a key.\nconst q = (s: string) => `\"${s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n/** Keys are quoted only when they would not survive as a plain scalar. */\nconst key = (k: string) => (/^[A-Za-z_][A-Za-z0-9_-]*$/.test(k) ? k : q(k));\nconst scalar = (v: string | number) => (typeof v === 'number' ? String(v) : q(v));\n\nconst yamlMap = (name: string, entries: [string, string | number][], indent = ''): string =>\n entries.length === 0\n ? ''\n : `${indent}${name}:\\n` +\n entries.map(([k, v]) => `${indent} ${key(k)}: ${scalar(v)}`).join('\\n') +\n '\\n';\n\n// ── value resolution ──────────────────────────────────────────────────────────\n/** `var(--x)` → `x`, else undefined. Tolerates a fallback: `var(--x, y)` → `x`. */\nconst varName = (v: string): string | undefined => {\n const m = /^var\\(\\s*--([a-z0-9-]+)\\s*(?:,[^)]*)?\\)$/i.exec(v.trim());\n return m ? (m[1] as string) : undefined;\n};\n\n/** A spec `Dimension` is a number plus px / em / rem — nothing else parses. */\nconst isDimension = (v: string) => /^-?(?:\\d+\\.?\\d*|\\.\\d+)(?:px|em|rem)$/.test(v.trim());\n\n/**\n * Only these reach a `Color` slot. `inherit` / `currentColor` / `initial` are\n * valid CSS in a pattern's `base` and meaningless as a token value, so a\n * component that says `color: inherit` emits no `textColor` at all rather than\n * an unresolvable one.\n */\nconst isColorLiteral = (v: string) =>\n /^#[0-9a-f]{3,8}$/i.test(v.trim()) ||\n /^(?:rgba?|hsla?|hwb|oklch|oklab|lch|lab|color-mix)\\(/i.test(v.trim()) ||\n /^(?:transparent|white|black)$/i.test(v.trim());\n\nexport function emitDesignMd(ctx: DesignMdCtx): string {\n const { ds, expandedPalette, scaleRoles, typeSteps, spaceSteps, shadows } = ctx;\n const meta = ds.meta ?? {};\n const name = meta.name ?? 'Design System';\n const roleMap = ds.colors.roles as Record<string, RoleSpec>;\n const patterns = ds.patterns ?? {};\n const pDefaults = (patterns.defaults ?? {}) as Record<string, string>;\n const pRadii = (patterns.radii ?? {}) as Record<string, string>;\n const pGroups = (patterns.groups ?? {}) as Record<string, Record<string, string>>;\n const pItems = (patterns.items ?? {}) as Record<string, PatternItem>;\n\n // ── colors ─────────────────────────────────────────────────────────────────\n // Raw ramps first (they are what everything else references), then the\n // functional role tokens as refs into them, then the spec's recommended names\n // as refs into those. Three layers, each one hop from the last.\n const ramps: [string, string][] = [];\n for (const [hue, expanded] of Object.entries(expandedPalette))\n for (const [step, hex] of Object.entries(expanded.numeric)) ramps.push([`${hue}-${step}`, hex]);\n\n const rampNames = new Set(ramps.map(([k]) => k));\n /** `var(--color-<hue>-<step>)` → `{colors.<hue>-<step>}`; literals pass through. */\n const rampRef = (value: string): string => {\n const v = varName(value);\n const bare = v?.startsWith('color-') ? v.slice('color-'.length) : undefined;\n return bare && rampNames.has(bare) ? `{colors.${bare}}` : value;\n };\n\n const roleTokens: [string, string][] = [];\n for (const fr of scaleRoles)\n for (const [token, value] of Object.entries(fr.light))\n // Flattened as the utility class name (`bg-surface`, `text-on-danger`) —\n // the same string an agent would write in markup, so the brief and the\n // markup vocabulary are one thing rather than two.\n roleTokens.push([tokenClass(fr.role, token), rampRef(value)]);\n\n const colorNames = new Set([...rampNames, ...roleTokens.map(([k]) => k)]);\n /** Recommended-name alias, emitted only when the role behind it exists. */\n const aliasAs = (as: string, token: string): [string, string][] =>\n colorNames.has(token) ? [[as, `{colors.${token}}`]] : [];\n // The spec's non-normative recommended names (`primary`, `on-primary`,\n // `error`, …). Ours are role-scoped, so nothing here is a new value — each is\n // a one-hop reference, which is exactly what makes a generic DESIGN.md\n // consumer (and the linter's `primary`-must-exist rule) work against a\n // vocabulary that never uses those words.\n const interop: [string, string][] = [\n ...aliasAs('primary', 'bg-ui-primary-solid'),\n ...aliasAs('on-primary', 'text-on-ui-primary'),\n ...aliasAs('secondary', 'bg-ui-secondary-solid'),\n ...aliasAs('on-secondary', 'text-on-ui-secondary'),\n ...aliasAs('tertiary', 'bg-ui-accent-solid'),\n ...aliasAs('on-tertiary', 'text-on-ui-accent'),\n ...aliasAs('neutral', 'bg-neutral'),\n ...aliasAs('surface', 'bg-surface'),\n ...aliasAs('on-surface', 'text-surface'),\n ...aliasAs('error', 'bg-danger-solid'),\n ...aliasAs('on-error', 'text-on-danger'),\n ];\n\n // ── typography ─────────────────────────────────────────────────────────────\n const fonts = (ds.fonts ?? {}) as Record<string, string>;\n const families = (ds.typography?.families ?? {}) as Record<string, string>;\n /** `display` → `var(--font-display)` → the actual stack. */\n const fontStack = (family: string | undefined): string | undefined => {\n if (!family) return undefined;\n const declared = families[family];\n if (declared == null) return fonts[family];\n const v = varName(declared);\n const bare = v?.startsWith('font-') ? v.slice('font-'.length) : undefined;\n return (bare && fonts[bare]) ?? declared;\n };\n const textMax = new Map(typeSteps.map((s) => [s.name, s.max]));\n /** `var(--text-3xl)` → that step's MAX rem (a clamp() is not a Dimension). */\n const typeSize = (size: string | number | undefined): string | undefined => {\n if (size == null) return undefined;\n const raw = String(size);\n const v = varName(raw);\n const bare = v?.startsWith('text-') ? v.slice('text-'.length) : undefined;\n const resolved = bare != null ? textMax.get(bare) : raw;\n return resolved != null && isDimension(resolved) ? resolved : undefined;\n };\n\n const typoRoles = (ds.typography?.roles ?? {}) as Record<\n string,\n Record<string, string | number | undefined>\n >;\n const typography: [string, [string, string | number][]][] = [];\n for (const [role, spec] of Object.entries(typoRoles)) {\n const props: [string, string | number][] = [];\n const stack = fontStack(spec.family as string | undefined);\n if (stack) props.push(['fontFamily', stack]);\n const size = typeSize(spec.size);\n if (size) props.push(['fontSize', size]);\n if (spec.weight != null) props.push(['fontWeight', Number(spec.weight)]);\n const lh = spec['line-height'];\n if (lh != null) {\n const n = Number(lh);\n props.push(['lineHeight', Number.isFinite(n) ? n : String(lh)]);\n }\n const tracking = spec.tracking;\n if (tracking != null && isDimension(String(tracking)))\n props.push(['letterSpacing', String(tracking)]);\n if (props.length) typography.push([role, props]);\n }\n\n // ── rounded ────────────────────────────────────────────────────────────────\n // DEFAULT + the named radii + one entry per pattern GROUP, because a component\n // references its group's radius (`{rounded.control}`), not a bare literal —\n // the group alias layer is the whole point of the cascade.\n //\n // A spec `Dimension` is a number plus px/em/rem, so a bare `0` is rejected\n // even though it is perfectly good CSS: normalise it to `0px`, which is the\n // same value in every context a radius is used. A radius that is genuinely not\n // a Dimension (`50%`, for a circle) cannot be normalised and is dropped from\n // the map rather than emitted as an error — `unroundable` carries it into the\n // Shapes prose so it is stated, not lost.\n const unroundable: [string, string][] = [];\n const asDimension = (v: string): string | undefined => {\n const t = v.trim();\n if (isDimension(t)) return t;\n return /^-?0+(?:\\.0+)?$/.test(t) ? '0px' : undefined;\n };\n const rounded: [string, string][] = [];\n const pushRadius = (name: string, value: string) => {\n const dim = asDimension(value);\n if (dim) rounded.push([name, dim]);\n else unroundable.push([name, value]);\n };\n if (pDefaults.br) pushRadius('DEFAULT', pDefaults.br);\n for (const [n, v] of Object.entries(pRadii)) pushRadius(n, v);\n const roundedNames = new Set(rounded.map(([k]) => k));\n /** `var(--br-default)` → `{rounded.DEFAULT}`, `var(--br-pill, 999px)` → `{rounded.pill}`. */\n const roundedRef = (value: string): string => {\n const v = varName(value);\n const bare = v?.startsWith('br-') ? v.slice('br-'.length) : undefined;\n if (bare === 'default') return '{rounded.DEFAULT}';\n return bare && roundedNames.has(bare) ? `{rounded.${bare}}` : value;\n };\n for (const [group, props] of Object.entries(pGroups)) {\n if (props.br == null) continue;\n const ref = roundedRef(props.br);\n if (ref !== props.br) rounded.push([group, ref]);\n else pushRadius(group, props.br);\n }\n const roundedAll = new Set(rounded.map(([k]) => k));\n\n // ── spacing ────────────────────────────────────────────────────────────────\n // Max rem again: the emitted `--space-*` tokens are fluid clamps.\n const spacing: [string, string][] = [];\n if (ds.spaceScale?.base) spacing.push(['base', ds.spaceScale.base]);\n for (const s of spaceSteps)\n if (!spacing.some(([k]) => k === s.name)) spacing.push([s.name, s.max]);\n\n // ── components ─────────────────────────────────────────────────────────────\n /** Walk a pattern's geometry cascade: overrides → group → defaults. */\n const cascade = (p: PatternItem, prop: string): string | undefined =>\n p.overrides?.[prop] ?? (p.group ? pGroups[p.group]?.[prop] : undefined) ?? pDefaults[prop];\n\n /** A colour-ish CSS value → a `{colors.x}` ref, a literal, or nothing. */\n const colorValue = (value: string | undefined): string | undefined => {\n if (value == null) return undefined;\n const v = varName(value);\n if (v != null) {\n if (colorNames.has(v)) return `{colors.${v}}`;\n const bare = v.startsWith('color-') ? v.slice('color-'.length) : undefined;\n if (bare && colorNames.has(bare)) return `{colors.${bare}}`;\n return undefined;\n }\n return isColorLiteral(value) ? value.trim() : undefined;\n };\n\n /**\n * Resolve a `base` declaration that goes through the group alias layer\n * (`var(--br-card-group)` → the card's `br` cascade), and turn the result into\n * a `{rounded.*}` ref where one exists.\n */\n const geometry = (\n p: PatternItem,\n pname: string,\n baseProp: string,\n token: string,\n ): string | undefined => {\n const declared = p.base?.[baseProp];\n if (declared == null) return undefined;\n const v = varName(declared);\n if (v !== `${token}-${pname}-group`) return declared;\n const resolved = cascade(p, token);\n if (resolved == null) return undefined;\n if (token !== 'br') return resolved;\n const ref = roundedRef(resolved);\n if (ref !== resolved) return ref;\n // A bare literal here came from the group's own `br` — and the group IS a\n // `rounded` entry — UNLESS the pattern overrode it, in which case the value\n // is this pattern's alone and pointing at the group would be a lie.\n return p.overrides?.br == null && p.group && roundedAll.has(p.group)\n ? `{rounded.${p.group}}`\n : resolved;\n };\n\n const components: [string, [string, string][]][] = [];\n const roleVariants: string[] = [];\n for (const [pname, p] of Object.entries(pItems)) {\n if (!p.base) continue;\n const base = p.base;\n // Mirrors generate.ts's fill inference exactly — a component whose fill is\n // guessed differently here would describe colours the CSS never sets.\n const fills =\n p.fill ??\n (pname === 'button' ||\n pname === 'badge' ||\n base['background-color'] != null ||\n base['background'] != null);\n const props: [string, string][] = [];\n if (fills) {\n const bg =\n colorValue(base['background-color']) ??\n colorValue(base['background']) ??\n (p.default_role ? colorValue(`var(--color-bg-${p.default_role}-solid)`) : undefined);\n if (bg) props.push(['backgroundColor', bg]);\n }\n const fg =\n colorValue(base['color']) ??\n (fills && p.default_role ? colorValue(`var(--color-text-on-${p.default_role})`) : undefined);\n if (fg) props.push(['textColor', fg]);\n // A radius that didn't survive into `rounded` (a `50%` circle) would emit\n // either a broken reference or a non-Dimension literal here, so the property\n // is dropped instead; the Shapes prose names those patterns.\n const br = geometry(p, pname, 'border-radius', 'br');\n const brRef = /^\\{rounded\\.([^}]+)\\}$/.exec(br ?? '');\n if (brRef && roundedAll.has(brRef[1] as string)) props.push(['rounded', br as string]);\n else if (br && asDimension(br)) props.push(['rounded', asDimension(br) as string]);\n else if (br) {\n // The Shapes prose wants the value, not the plumbing: `var(--br-circle,\n // 50%)` is how the cascade spells it, `50%` is what the reader needs.\n const named = varName(br);\n const bare = named?.startsWith('br-') ? named.slice('br-'.length) : undefined;\n unroundable.push([pname, (bare ? pRadii[bare] : undefined) ?? br]);\n }\n const pad = geometry(p, pname, 'padding', 'p');\n if (pad) props.push(['padding', pad]);\n if (props.length) components.push([pname, props]);\n\n // A hover that carries `step` intensifies the pattern's own colour; that is\n // a real variant an agent must reproduce, so it gets its own entry (the\n // spec's `-hover` sibling-key convention).\n const hover = p.states?.hover;\n const dr = p.default_role;\n if (hover && typeof hover.step === 'number' && dr) {\n const strong = hover.step >= 1;\n const hv = fills\n ? colorValue(`var(--color-bg-${dr}-${strong ? 'solid-bold' : 'solid'})`)\n : colorValue(`var(--color-text-${dr}${strong ? '-bold' : ''})`);\n if (hv) components.push([`${pname}-hover`, [[fills ? 'backgroundColor' : 'textColor', hv]]]);\n }\n if (p.roles?.length)\n roleVariants.push(\n `\\`${pname}\\` → ${p.roles.map((r) => `\\`.${p.class ?? pname}-${r}\\``).join(', ')}`,\n );\n }\n\n // ── front matter ───────────────────────────────────────────────────────────\n const fm: string[] = ['---', 'version: alpha', `name: ${q(name)}`];\n if (meta.description) fm.push(`description: ${q(meta.description)}`);\n fm.push('colors:');\n fm.push(' # Raw hue ramps — 11 OKLCH steps each, tinted near-white → tinted near-black.');\n for (const [k, v] of ramps) fm.push(` ${key(k)}: ${scalar(v)}`);\n fm.push(' # Functional role tokens (LIGHT values). These are the public API: use these,');\n fm.push(' # not the raw steps, and dark mode resolves itself. See \"## Colors\" below.');\n for (const [k, v] of roleTokens) fm.push(` ${key(k)}: ${scalar(v)}`);\n if (interop.length) {\n fm.push(\" # Aliases for the spec's recommended names — references, not new values.\");\n for (const [k, v] of interop) fm.push(` ${key(k)}: ${scalar(v)}`);\n }\n if (typography.length) {\n fm.push('typography:');\n for (const [role, props] of typography) {\n fm.push(` ${key(role)}:`);\n for (const [k, v] of props) fm.push(` ${k}: ${scalar(v)}`);\n }\n }\n fm.push(yamlMap('rounded', rounded).trimEnd());\n fm.push(yamlMap('spacing', spacing).trimEnd());\n if (components.length) {\n fm.push('components:');\n for (const [cname, props] of components) {\n fm.push(` ${key(cname)}:`);\n for (const [k, v] of props) fm.push(` ${k}: ${scalar(v)}`);\n }\n }\n fm.push('---');\n\n return `${fm.filter(Boolean).join('\\n')}\\n\\n# ${name}\\n\\n${prose({\n ctx,\n name,\n meta,\n roleMap,\n ramps,\n rounded,\n unroundable,\n roleVariants,\n typography: typography.map(([r]) => r),\n })}`;\n}\n\n// ── prose body ────────────────────────────────────────────────────────────────\n/**\n * Section order is normative (Overview → Colors → Typography → Layout →\n * Elevation → Shapes → Components → Do's and Don'ts); a consumer that parses\n * sections positionally breaks if they are reordered.\n *\n * Every section interpolates live config, so this cannot drift into describing a\n * system the generator no longer emits — the same discipline `docs.ts` follows.\n */\nfunction prose(a: {\n ctx: DesignMdCtx;\n name: string;\n meta: { name?: string | undefined; description?: string | undefined };\n roleMap: Record<string, RoleSpec>;\n ramps: [string, string][];\n rounded: [string, string][];\n unroundable: [string, string][];\n roleVariants: string[];\n typography: string[];\n}): string {\n const { ctx, name, meta, roleMap, rounded, unroundable, roleVariants } = a;\n const { ds, expandedPalette, scaleRoles, typeSteps, spaceSteps, shadows } = ctx;\n const hues = Object.keys(expandedPalette);\n const roles = Object.keys(roleMap);\n const shadowNames = Object.keys(shadows ?? {});\n const typeNames = typeSteps.map((s) => s.name);\n const spaceNames = spaceSteps.map((s) => s.name);\n const bodyRole = ds.typography?.headings?.body ?? 'body';\n const s = (list: string[]) => list.map((x) => `\\`${x}\\``).join(', ');\n\n const overview =\n meta.description ??\n `${name} is a variable-driven design system: an OKLCH colour engine, fluid ` +\n `modular type and space scales, and a small set of component patterns, all ` +\n `expressed as CSS custom properties with utility classes over them.`;\n\n return `## Overview\n\n${overview}\n\nEvery value in this document is generated from a single \\`design-system.json\\` and\nemitted as CSS custom properties plus utility classes. **Prefer the class vocabulary\nover hand-written CSS** — \\`vitops docs classes\\` prints the full list, and \\`vitops lint\\`\nreports classes that resolve to nothing.\n\nThe token names below are the contract. Reach for a raw ramp step only when no\nfunctional role expresses what you mean.\n\n> Most tokens here are consumed by **utility classes**, not by the \\`components\\` block —\n> \\`bg-<role>\\`, \\`text-<role>-muted\\` and friends are the API. \\`design.md lint\\` reports\n> those as \\`orphaned-tokens\\`; that rule assumes a component-only system and does not\n> apply. Everything else it reports is worth reading.\n\n## Colors\n\n${hues.length} hue${hues.length === 1 ? '' : 's'} (${s(hues)}), each generated as an 11-step\nOKLCH scale from a seed — step \\`50\\` is a tinted near-white, \\`950\\` a tinted near-black,\nwith chroma damped toward both ends so the extremes read as neutral rather than washed.\n\n${roles.length} semantic **roles** map onto those hues:\n\n${roles.map((r) => `- \\`${r}\\` → \\`${roleHue(roleMap[r] as RoleSpec)}\\``).join('\\n')}\n\nA role is **not** an alias for a ramp. It resolves to tokens named\n\\`<target>-<role>[-<variant>]\\`, where target is one of \\`bg\\` \\`text\\` \\`icon\\` \\`border\\`. The\ntarget is part of the name on purpose: \\`bg-danger-muted\\` and \\`text-danger-muted\\` are\ndifferent tokens, so there is no ambiguity about which one a name refers to. **The token\nname is also the utility class name** — write \\`class=\"bg-danger-muted\"\\` and you are using\n\\`--color-bg-danger-muted\\`.\n\nVariants are ordinal: \\`xx-muted\\` < \\`x-muted\\` < \\`muted\\` < (bare) < \\`bold\\` < \\`x-bold\\`.\n\\`bold\\` means *more emphatic in the current appearance*, not darker.\n\nRoles come in two kinds, and the kind decides which tokens exist:\n\n- **surface** (page and panel colours) — \\`bg-<role>\\` is the card/panel, \\`bg-<role>-muted\\`\n the page behind it, \\`bg-<role>-x-muted\\` a well. Full text scale, \\`border-<role>-bold\\`\n as the contrast-guaranteed boundary.\n- **chromatic** (signal colours) — backgrounds are either *tints*\n (\\`bg-<role>-x-muted\\` / \\`-muted\\`) or *solids*\n (\\`bg-<role>-solid\\` / \\`-solid-bold\\` / \\`-solid-x-bold\\`). **There is no bare \\`bg-<role>\\`**:\n say how loud you mean. \\`text-on-<role>\\` is the guaranteed-contrast foreground for the\n solid family.\n\n**Dark mode is automatic, and this file only lists the light values.** The spec has no\nway to express a second appearance, so do not try to reconstruct one: the framework\nre-points each token at a different ramp step under \\`${DARK_SEL}\\`, so \\`bg-<role>\\`\nbecomes dark and \\`text-<role>\\` becomes light on their own. The solid family and\n\\`text-on-<role>\\` stay mode-stable by design, so a filled button keeps its identity.\n**An agent that styles with the role tokens gets dark mode for free; one that flattens\nthem to hexes breaks it.**\n\nContrast is enforced at build time, not by convention — a violation fails the build.\nText is held to APCA Lc 75 on a role's primary background and Lc 60 on its secondary\nplanes; icons and the surface boundary to Lc 45; and chromatic text is checked against\nthe *surface* planes it actually sits on, not just its own tints. Pairing\n\\`text-<role>\\` with \\`bg-<role>\\`, or \\`text-on-<role>\\` with \\`bg-<role>-solid\\`, is always\nsafe. Pairing a raw ramp step with another raw ramp step is not.\n\n## Typography\n\nFont stacks are named, and roles consume the name rather than the stack — so swapping a\ntypeface is one edit:\n\n${Object.entries((ds.fonts ?? {}) as Record<string, string>)\n .map(([n, stack]) => `- **${n}** — \\`${stack}\\``)\n .join('\\n')}\n\nType is a fluid modular scale: ${typeNames.length} steps (${s(typeNames)}) built from a\n${ds.typeScale?.base ?? '1rem'} base at a ${ds.typeScale?.ratio ?? 1.2} ratio${\n ds.typeScale?.fluid\n ? `, interpolating between a ${ds.typeScale.fluid.minRatio} ratio at ${ds.typeScale.fluid.minVw} viewport width and the full ratio at ${ds.typeScale.fluid.maxVw}`\n : ''\n }. **The \\`fontSize\\` values in the front matter are the maximum (desktop) sizes** — the\nreal tokens are \\`clamp()\\` expressions, which the spec's \\`Dimension\\` type cannot hold.\nNever hard-code the emitted number; use the scale (\\`--text-<step>\\`) or the role class.\n\nEach typography role is a class (\\`.font-<role>\\`): ${s(a.typography.map((t) => `font-${t}`))}.\nRoles also carry properties this format has no slot for — \\`text-transform\\`,\n\\`text-wrap\\`, and a \\`color\\` — so **apply the role class rather than copying its\nfront-matter properties**, or uppercase eyebrows and balanced headings silently\ndisappear. Base page text is bound to the \\`${bodyRole}\\` role, so prose inherits it.\n\n## Layout & Spacing\n\nSpacing is its own fluid modular scale: ${spaceNames.length} steps (${s(spaceNames)}) from a\n${ds.spaceScale?.base ?? '1rem'} base at a ${ds.spaceScale?.ratio ?? 1.25} ratio. As with type,\nthe front-matter values are the maxima and the live tokens are fluid.\n\nLayout is composed from utilities rather than bespoke CSS:\n\n- \\`.centered\\` — track-based centering: content sits in a centred measure while\n full-bleed children can still break out. Use it instead of \\`margin-inline: auto\\`.\n- \\`.rhythm\\` — vertical rhythm between flow children, so sibling spacing is one\n decision rather than per-element margins.\n- \\`.flex\\` / \\`.split-<a>-<b>\\` / \\`.grid\\` — the structural families, with container-query\n variants prefixed \\`sm-\\` / \\`md-\\` / \\`lg-\\` / \\`xl-\\` (30 / 48 / 64 / 80rem).\n \\`.split\\` is a two-column pair. Stack it with \\`.flex-col\\` and let a\n breakpoint-prefixed ratio un-stack it (\\`split flex-col md-split-1-2\\`);\n \\`.split-reverse\\` swaps the two panels. Reversing puts visual order out of step\n with DOM order, so keep focusable content in only one panel.\n\nBreakpoints are **container** queries, not viewport media queries: a component\nresponds to the space it is given, so the same markup works in a sidebar and a full-width\nsection.\n\n## Elevation & Depth\n\n${\n shadowNames.length\n ? `Depth comes from ${shadowNames.length} named shadow${shadowNames.length === 1 ? '' : 's'} (${s(shadowNames)}), applied as \\`--shadow-<name>\\` tokens or \\`.drop-shadow-<name>\\` utilities:\n\n${shadowNames.map((n) => `- \\`${n}\\` — \\`${(shadows ?? {})[n]}\\``).join('\\n')}\n\nEach value is deliberately a **single layer with no spread and no \\`inset\\`**: the same\ntoken feeds both \\`box-shadow\\` (pattern geometry) and \\`filter: drop-shadow()\\` (the\nutilities), and \\`drop-shadow()\\` rejects all three, which would drop the whole filter.`\n : `This system is flat: no shadow tokens are defined. Convey hierarchy with the\nsurface planes (\\`surface-bg\\` / \\`surface-bg-muted\\` / \\`surface-bg-bold\\`) and borders.`\n}\n\nSurfaces stack tonally as well: \\`surface-bg-bold\\` is the *raised* plane in both\nappearances, so a card on a page reads as lifted without any shadow at all.\n\n## Shapes\n\nCorner radii resolve through a cascade rather than being set per component:\n\\`--br-<pattern>\\` (your override hook) → \\`--br-<pattern>-group\\` → the group's radius →\n\\`--br-default\\`. Overriding one variable restyles every pattern in that tier.\n\n${rounded.map(([k, v]) => `- \\`${k}\\` — \\`${v}\\``).join('\\n')}\n\nChange a group's radius to restyle a whole tier; change \\`DEFAULT\\` to restyle everything\nthat has not opted out.\n${\n unroundable.length\n ? `\n**Not in the front matter above**, because the spec's \\`Dimension\\` type only holds\npx / em / rem — these are real radii in the system and have to be applied as CSS:\n\n${unroundable.map(([k, v]) => `- \\`${k}\\` — \\`${v}\\``).join('\\n')}`\n : ''\n}\n\n## Components\n\nPatterns are classes, not components — apply them to whatever element is semantically\ncorrect. Two tiers of button exist and the distinction is intent, not looks:\n\n- **\\`.cta\\`** is *persuasion* — filled, bolder, more padding, lifts on hover. Usually on an\n \\`<a>\\`, because a call to action usually navigates.\n- **\\`.btn\\`** is *affordance* — it only says \"this is interactive\". It is emitted at zero\n specificity for both \\`<button>\\` and \\`.btn\\`, so a bare \\`<button>\\` gets it with no class\n and **any** explicit class overrides it.\n\n${\n roleVariants.length\n ? `Role variants are systematic rather than enumerated above. A filled pattern's variant sets\n\\`background-color: var(--<role>-solid)\\` with \\`color: var(--<role>-on-solid)\\`; a text\npattern's sets \\`color: var(--color-<role>-bold)\\`:\n\n${roleVariants.map((r) => `- ${r}`).join('\\n')}`\n : ''\n}\n\nInteraction states are generated from a small grammar — \\`step\\` (intensify the colour),\n\\`scale\\`, \\`lift\\`, \\`shadow\\`, \\`ring\\` — so hover, active and focus-visible stay consistent\nacross every pattern. Focus rings are never removed, only restyled.\n\n## Do's and Don'ts\n\n- **Do** use functional role tokens (\\`ui-primary-solid\\`, \\`surface-bg\\`) over raw ramp steps.\n- **Do** pair \\`<role>-text\\` with \\`<role>-bg\\`, and \\`<role>-on-solid\\` with \\`<role>-solid\\` —\n those pairings are contrast-tested; arbitrary ones are not.\n- **Do** apply the \\`.font-<role>\\` classes rather than copying their font properties.\n- **Do** reach for a utility class before writing CSS; run \\`vitops lint\\` to catch classes\n that resolve to nothing.\n- **Don't** hard-code the \\`fontSize\\` / \\`spacing\\` numbers from the front matter — they are\n the maxima of fluid \\`clamp()\\` scales.\n- **Don't** flatten role tokens to hex values: that is exactly what breaks dark mode.\n- **Don't** invent a colour outside the ${hues.length} ramps${\n scaleRoles.length ? ` or the ${scaleRoles.length} roles` : ''\n }; add a hue to the config instead.\n- **Don't** edit this file by hand — it is generated from \\`design-system.json\\`. Change the\n config and re-run \\`vitops generate --format design\\`.\n`;\n}\n","/**\n * What the config already tells us about third parties that receive personal\n * information.\n *\n * A privacy policy's riskiest sentence is the one naming service providers: if\n * it says \"Plausible\" while the site runs Google Analytics, the document is a\n * compliance defect, not a typo. The site config already records which analytics\n * ID is set, whether Turnstile is deployed and where the site is hosted — so the\n * sentence derives from those signals rather than from a hand-maintained string\n * that drifts the moment someone swaps providers.\n *\n * Presence of the key is the signal, matching how `analytics` already works\n * (provider identity is implied by which ID is set, not by an enum).\n *\n * This table is deliberately small and covers only what the schema can imply.\n * Everything else — payment processors, CRMs, mail senders — is declared by the\n * consumer in `legal.privacyPolicy.processors`, which flows through the same\n * pipeline. This is not a directory of the web; it's the set of providers the\n * toolchain itself can vouch for.\n */\nimport type { Config } from '../config.ts';\n\nexport interface Processor {\n /** The provider as a reader would recognise it. */\n name: string;\n /** Reads after \"for\": \"…to Stripe for payment processing\". */\n purpose: string;\n /** Reads inside a sentence: \"…including the United States\". */\n country?: string | undefined;\n privacyUrl?: string | undefined;\n /**\n * Cookies this provider sets. An empty array is meaningful and not the same as\n * `undefined`: it asserts the provider is cookieless (Plausible), which the\n * cookie notice states positively rather than omitting.\n */\n cookies?: string[] | undefined;\n /** A user-facing opt-out, when the provider offers one. */\n optOut?: string | undefined;\n}\n\n/**\n * The providers the config can imply. Keyed for testability — a test can assert\n * a given config resolves to a given key without matching on prose.\n */\nexport const KNOWN_PROCESSORS = {\n googleAnalytics: {\n name: 'Google Analytics',\n purpose: 'website analytics',\n country: 'the United States',\n privacyUrl: 'https://policies.google.com/privacy',\n cookies: ['_ga', '_gid'],\n optOut: 'https://tools.google.com/dlpage/gaoptout',\n },\n googleTagManager: {\n name: 'Google Tag Manager',\n purpose: 'tag management',\n country: 'the United States',\n privacyUrl: 'https://policies.google.com/privacy',\n cookies: [],\n },\n plausible: {\n name: 'Plausible Analytics',\n purpose: 'website analytics',\n country: 'the European Union',\n privacyUrl: 'https://plausible.io/privacy',\n // Plausible sets no cookies and stores no cross-site identifiers. Stated as\n // an empty list rather than omitted, so the cookie notice can say so.\n cookies: [],\n },\n clarity: {\n name: 'Microsoft Clarity',\n purpose: 'session replay and heatmaps',\n country: 'the United States',\n privacyUrl: 'https://privacy.microsoft.com/privacystatement',\n // Clarity records what a visitor does on the page, not just that they were\n // here, so the purpose says \"session replay\" rather than \"analytics\" — a\n // reader deciding whether to consent needs to know they may be recorded.\n cookies: ['_clck', '_clsk', 'MUID'],\n optOut: 'https://privacy.microsoft.com/privacystatement',\n },\n // Matomo appears twice on purpose: whether it sets cookies is a *configuration*\n // choice (`analytics.matomo.cookies`), and the notice says something materially\n // different in each case. One entry with a conditional cookie list would put\n // that branch in the prose layer, where the rule is that templates own wording\n // and never facts.\n matomo: {\n name: 'Matomo',\n purpose: 'website analytics',\n privacyUrl: 'https://matomo.org/privacy-policy/',\n cookies: ['_pk_id', '_pk_ses'],\n },\n matomoCookieless: {\n name: 'Matomo',\n purpose: 'website analytics',\n privacyUrl: 'https://matomo.org/privacy-policy/',\n // `disableCookies` is on: Matomo stores no identifier on the device. The\n // empty list is the assertion — see the Processor.cookies note above.\n cookies: [],\n },\n turnstile: {\n name: 'Cloudflare Turnstile',\n purpose: 'bot protection on forms',\n country: 'the United States',\n privacyUrl: 'https://www.cloudflare.com/privacypolicy/',\n cookies: ['cf_clearance'],\n },\n cloudflare: {\n name: 'Cloudflare',\n purpose: 'website hosting and content delivery',\n country: 'the United States',\n privacyUrl: 'https://www.cloudflare.com/privacypolicy/',\n cookies: [],\n },\n vercel: {\n name: 'Vercel',\n purpose: 'website hosting',\n country: 'the United States',\n privacyUrl: 'https://vercel.com/legal/privacy-policy',\n cookies: [],\n },\n netlify: {\n name: 'Netlify',\n purpose: 'website hosting',\n country: 'the United States',\n privacyUrl: 'https://www.netlify.com/privacy/',\n cookies: [],\n },\n} satisfies Record<string, Processor>;\n\nexport type KnownProcessorKey = keyof typeof KNOWN_PROCESSORS;\n\n/** Substring → hosting provider. `deployment.platform` is a free-form string. */\nconst HOSTING_PATTERNS: [RegExp, KnownProcessorKey][] = [\n [/cloudflare|workers|pages\\.dev/i, 'cloudflare'],\n [/vercel/i, 'vercel'],\n [/netlify/i, 'netlify'],\n];\n\n/**\n * Which known providers this config implies, in a stable order (analytics →\n * security → hosting) so the rendered sentence doesn't churn between builds.\n *\n * Returns keys rather than processors so a caller can test the detection\n * independently of the prose attached to it.\n */\nexport function detectProcessorKeys(cfg: Config): KnownProcessorKey[] {\n const site = cfg.site;\n const keys: KnownProcessorKey[] = [];\n const analytics = site.analytics;\n if (analytics?.googleAnalyticsId) keys.push('googleAnalytics');\n if (analytics?.googleTagManagerId) keys.push('googleTagManager');\n if (analytics?.plausibleDomain) keys.push('plausible');\n if (analytics?.clarityId) keys.push('clarity');\n // Cookieless is the default, matching the tag the Astro integration emits\n // (`_paq.push(['disableCookies'])` unless `cookies: true`). The two must agree:\n // a notice claiming no cookies while the tag sets them is the defect this whole\n // table exists to prevent.\n if (analytics?.matomo) keys.push(analytics.matomo.cookies ? 'matomo' : 'matomoCookieless');\n if (site.security?.turnstile?.siteKey) keys.push('turnstile');\n\n const platform = site.deployment?.platform;\n const hosting = platform && HOSTING_PATTERNS.find(([re]) => re.test(platform))?.[1];\n // Turnstile already names Cloudflare; listing it twice reads as sloppy and\n // implies two relationships where there is one.\n if (hosting && !keys.includes(hosting)) keys.push(hosting);\n return keys;\n}\n\n/**\n * Every processor this policy must disclose: the ones implied by the config,\n * then the ones the consumer declared.\n *\n * Consumer entries come last and are never deduplicated against the built-ins —\n * an explicit declaration is a statement of fact we have no grounds to drop.\n */\nexport function resolveProcessors(cfg: Config): Processor[] {\n const detected = detectProcessorKeys(cfg).map((k) =>\n matomoCountry(KNOWN_PROCESSORS[k] as Processor, cfg.site),\n );\n const declared = cfg.site.legal?.privacyPolicy?.processors ?? [];\n return [...detected, ...declared];\n}\n\n/**\n * Matomo is the one provider whose location the config actually knows.\n *\n * Matomo Cloud is hosted in the EU; a self-hosted instance is wherever the\n * consumer put it, which is very often their own infrastructure in their own\n * country. So the cross-border transfer sentence is asserted only for the case we\n * can see. Naming a transfer that isn't happening is the same class of error as\n * omitting one that is — the config records facts, and \"we don't know\" is a fact.\n */\nfunction matomoCountry(processor: Processor, site: Config['site']): Processor {\n if (processor.name !== 'Matomo') return processor;\n const url = site.analytics?.matomo?.url ?? '';\n return /\\.matomo\\.cloud/i.test(url) ? { ...processor, country: 'the European Union' } : processor;\n}\n","/**\n * Site config → the facts a legal document asserts.\n *\n * The division of labour here is the whole point: **the config records facts,\n * the template owns prose.** Nothing in this module writes a sentence a lawyer\n * would need to review, and nothing in a template invents a fact. That is what\n * lets the wording be corrected without touching a consumer's config, and a\n * consumer's provider to change without touching the prose.\n *\n * Everything it returns is derived from config the site already has to hold to\n * function — which analytics ID is set, which forms exist, where it deploys —\n * plus the facts a consumer declares in `legal.privacyPolicy`. There is no\n * source of truth here beyond `Config`.\n *\n * Pure: no I/O, no clock. `lastUpdated` comes from the config rather than\n * `Date.now()` so a rebuild produces a byte-identical document.\n */\nimport { t } from '@getvitops/utils';\nimport { resolvePrivacyContact, type ContactObject, type Config } from '../config.ts';\nimport { resolveProcessors, type Processor } from './providers.ts';\n\n/**\n * The facts every legal template renders from.\n *\n * List-shaped fields are `string[]`, not pre-joined strings, because they land\n * in bullet positions: a template that splices an empty string into a list emits\n * a stray `-` bullet, and that is exactly the kind of silent breakage a\n * published policy must not have.\n */\nexport interface PolicyVars {\n businessName: string;\n url: string;\n /** Reads after \"at\": \"…contact our Privacy Officer at <this>.\" */\n mailingAddress: string;\n lastUpdated: string | undefined;\n /** Extra retention sentence, when the consumer stated one. */\n retention: string | undefined;\n /** A consumer-supplied governing-law phrase, which wins over the two below. */\n governingLaw: string | undefined;\n /** Province/territory, spelled out — \"Ontario\", never \"ON\". */\n governingProvince: string | undefined;\n governingCountry: string;\n\n /** Circumstances in which personal information is collected. */\n collectionReasons: string[];\n /** Categories of personal information collected. */\n piiCollected: string[];\n /** What the browser sends automatically. */\n techInfo: string[];\n /** Why that technical information is used. */\n techInfoPurposes: string[];\n /** What cookies track. */\n cookieTracked: string[];\n /** Why cookies are used. */\n cookiePurposes: string[];\n /** A sentence about the consent tool, or `undefined` when there is none. */\n cookieTool: string | undefined;\n /** How collected information is used. */\n usePurposes: string[];\n /** Choices a visitor has. */\n optOutOptions: string[];\n /** The subset of `optOutOptions` about cookies — an e-mail unsubscribe link is\n * not a cookie choice, and listing it in a cookie notice reads as padding. */\n cookieOptOutOptions: string[];\n\n processors: Processor[];\n /** Reads after \"including\": \"…the United States and the European Union\". */\n countries: string | undefined;\n consentModel: 'opt-in' | 'opt-out' | 'none';\n cookieCategories: string[];\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────────\n\n/** \"A\", \"A and B\", \"A, B and C\". */\nexport function list(items: string[]): string {\n if (items.length <= 1) return items[0] ?? '';\n return `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`;\n}\n\n/** Order-preserving dedupe — the bullet lists are assembled from several sources. */\nconst uniq = (items: (string | undefined)[]): string[] => [\n ...new Set(items.filter((s): s is string => !!s)),\n];\n\n/**\n * Render a contact into the phrase that follows \"at\". Prefers e-mail (the\n * channel a reader can actually use from the page) and adds the postal address\n * when there is one, because access and correction requests are commonly posted.\n */\nfunction formatContact(contact: ContactObject | undefined): string {\n if (!contact) return '';\n const a = contact.address;\n const postal =\n a &&\n [\n a.streetAddress,\n a.addressLocality,\n [a.addressRegion, a.postalCode].filter(Boolean).join(' '),\n a.addressCountry,\n ]\n .filter(Boolean)\n .join(', ');\n if (contact.email && postal) return `${contact.email}, or by mail at ${postal}`;\n return contact.email ?? postal ?? '';\n}\n\n/**\n * What a form field actually collects, as a noun phrase.\n *\n * Typed fields carry their meaning (`email` is an e-mail address in any form);\n * `text` does not, so it falls back to the field's name. A policy that under-\n * describes what a form collects is the failure mode worth avoiding, so an\n * unrecognised text field lands in a catch-all bullet rather than being dropped.\n */\nfunction fieldPhrase(name: string, type: string): string | undefined {\n switch (type) {\n // `hidden` is not visitor-supplied and a honeypot exists to be left empty —\n // describing either as collected information would be inaccurate.\n case 'hidden':\n return undefined;\n case 'email':\n return 'your e-mail address';\n case 'tel':\n return 'your telephone number';\n case 'url':\n return 'any website address you provide';\n case 'date':\n return 'any dates you provide';\n case 'file':\n return 'any files or documents you upload';\n case 'textarea':\n return 'the content of the messages you send us';\n case 'number':\n return 'any numeric details you provide';\n case 'password':\n return 'account credentials';\n case 'select':\n case 'radio':\n case 'checkbox':\n return 'your answers to the questions we ask';\n default:\n break;\n }\n if (/name/i.test(name)) return 'your name';\n if (/compan|organi|business/i.test(name)) return 'your company or organization name';\n if (/address|street|city|province|state|postal|zip|country/i.test(name))\n return 'your mailing address';\n return 'the other details you enter in our forms';\n}\n\nconst PROVINCES: Record<string, string> = {\n AB: 'Alberta',\n BC: 'British Columbia',\n MB: 'Manitoba',\n NB: 'New Brunswick',\n NL: 'Newfoundland and Labrador',\n NS: 'Nova Scotia',\n NT: 'Northwest Territories',\n NU: 'Nunavut',\n ON: 'Ontario',\n PE: 'Prince Edward Island',\n QC: 'Quebec',\n SK: 'Saskatchewan',\n YT: 'Yukon',\n};\n\n/**\n * `addressRegion` is conventionally a two-letter code, which is right for a\n * postal address and wrong inside a governing-law clause — \"the laws of ON\" is\n * not a sentence a lawyer would sign off. Anything already spelled out (or from\n * another country) passes through untouched.\n */\nfunction expandProvince(region: string | undefined): string | undefined {\n if (!region) return undefined;\n return PROVINCES[region.toUpperCase()] ?? region;\n}\n\n/** Every field across every `form` template, honeypots excluded. */\nfunction formFields(site: Config['site']): { name: string; type: string }[] {\n const out: { name: string; type: string }[] = [];\n for (const tpl of Object.values(site.templates ?? {})) {\n if (tpl.type !== 'form') continue;\n for (const f of tpl.fields ?? []) out.push({ name: f.name, type: f.type });\n }\n return out;\n}\n\n// ── Derivation ──────────────────────────────────────────────────────────────────\n\nexport function derivePolicyVars(cfg: Config): PolicyVars {\n // The two sections this reads from. Everything the policy asserts about the\n // *company* comes from `organization`; everything it asserts about what the\n // *site* does (forms, analytics, cookies, A/B) comes from `site`.\n const site = cfg.site;\n const org = cfg.organization;\n const locale = site.defaultLocale;\n const legal = site.legal;\n const privacy = legal?.privacyPolicy;\n const processors = resolveProcessors(cfg);\n const fields = formFields(site);\n const hasForms = fields.length > 0;\n // Any configured provider counts, whether its config is an ID string\n // (`googleAnalyticsId`) or an object (`matomo`). Checking only for strings\n // would silently under-report a Matomo-only site as having no analytics at all.\n const hasAnalytics = Object.values(site.analytics ?? {}).some((v) =>\n typeof v === 'string' ? v.length > 0 : !!v,\n );\n const cookieProcessors = processors.filter((p) => p.cookies?.length);\n const consent = legal?.cookieConsent;\n const contact = resolvePrivacyContact(cfg);\n\n const businessName =\n org?.legalName ?? (org?.name != null ? t(org.name, locale, locale) : undefined) ?? 'we';\n\n const collectionReasons = uniq([\n 'contact us through e-mail, telephone, mail or other correspondence',\n hasForms ? 'submit one of the forms on our Site' : undefined,\n org?.services && Object.keys(org.services).length > 0\n ? 'register for a service we provide'\n : undefined,\n fields.some((f) => /newsletter|subscribe|mailing/i.test(f.name))\n ? 'register to receive our newsletter'\n : undefined,\n ]);\n\n // Only claim to collect what a configured form actually asks for. With no\n // forms, the generic categories stand in — the site still receives whatever a\n // visitor sends by e-mail.\n const piiCollected = uniq([\n ...(hasForms\n ? fields.map((f) => fieldPhrase(f.name, f.type))\n : [\n 'your full name',\n 'contact information, such as your address, telephone number, or e-mail address',\n ]),\n 'any other personal information that you choose to submit to us',\n ]);\n\n // Session replay is a materially different disclosure from page-view analytics\n // and cannot be folded into `hasAnalytics`: a policy that lists \"the pages you\n // view\" while the site records mouse movement, scrolling and clicks is\n // under-disclosing, not summarising.\n const hasSessionReplay = !!site.analytics?.clarityId;\n\n const techInfo = uniq([\n 'your domain name',\n 'your numerical IP address',\n hasAnalytics ? 'the pages you view and the files you request' : undefined,\n hasAnalytics ? 'the type of browser and operating system you use' : undefined,\n hasAnalytics ? 'the address of the site that referred you' : undefined,\n hasSessionReplay\n ? 'a recording of how you interacted with a page, including mouse movement, scrolling and clicks'\n : undefined,\n ]);\n\n const techInfoPurposes = uniq([\n hasAnalytics ? 'measure the performance of our Site' : undefined,\n hasSessionReplay ? 'see where visitors encounter difficulty using our Site' : undefined,\n site.security?.turnstile?.siteKey\n ? 'protect our Site and its forms from automated abuse'\n : undefined,\n 'better understand how visitors use our Site',\n 'improve our Site to better meet your needs',\n ]);\n\n const ab = site.abTesting;\n const cookieTracked = uniq([\n 'your IP address',\n 'the type of web browser and operating system used',\n 'the pages of the Site visited',\n ab?.enabled ? 'which version of a page you were shown' : undefined,\n hasSessionReplay ? 'how you moved through and interacted with a page' : undefined,\n ]);\n\n const cookiePurposes = uniq([\n 'keep the Site functioning as you move between pages',\n hasAnalytics ? 'understand how our Site is used, in aggregate' : undefined,\n hasSessionReplay ? 'recognise a returning visit as part of the same session' : undefined,\n ab?.enabled ? 'keep you on a consistent version of the Site between visits' : undefined,\n site.security?.turnstile?.siteKey ? 'distinguish visitors from automated traffic' : undefined,\n ]);\n\n const cookieTool = consent?.enabled\n ? consent.type === 'opt-in'\n ? 'You may also choose which categories of cookies to allow using the consent banner shown when you first visit our Site, and you may change that choice at any time.'\n : 'You may also withdraw your consent to non-essential cookies at any time using the consent controls on our Site.'\n : undefined;\n\n const usePurposes = uniq([\n 'respond to your inquiries',\n 'supply you with requested products or services',\n site.notifications?.email\n ? 'route your message to the appropriate person in our organization'\n : undefined,\n site.tracking?.enabled ? 'measure the effectiveness of our marketing' : undefined,\n 'send you informational or promotional communication',\n 'carry out other purposes that are disclosed to you and to which you consent',\n 'carry out any other purpose permitted or required by law',\n ]);\n\n const cookieOptOutOptions = uniq([\n 'You may configure your browser to refuse cookies, though parts of our Site may not function as intended.',\n consent?.enabled ? cookieTool : undefined,\n ...processors\n .filter((p) => p.optOut)\n .map((p) => `You may opt out of ${p.name} directly at ${p.optOut}.`),\n ]);\n\n const optOutOptions = uniq([\n 'You may unsubscribe from any commercial e-mail we send using the \"unsubscribe\" link in that e-mail.',\n ...cookieOptOutOptions,\n ]);\n\n const countries = list(uniq(processors.map((p) => p.country)));\n\n const address = contact?.address ?? org?.address;\n\n return {\n businessName,\n url: site.domains?.canonical ?? '',\n mailingAddress: formatContact(contact),\n lastUpdated: privacy?.lastUpdated,\n retention: privacy?.retention,\n governingLaw: legal?.termsOfService?.governingLaw,\n governingProvince: expandProvince(address?.addressRegion),\n governingCountry: address?.addressCountry ?? 'Canada',\n collectionReasons,\n piiCollected,\n techInfo,\n techInfoPurposes,\n cookieTracked,\n cookiePurposes,\n cookieTool,\n usePurposes,\n optOutOptions,\n cookieOptOutOptions,\n processors,\n countries: countries || undefined,\n consentModel: consent?.enabled ? (consent.type ?? 'opt-in') : 'none',\n cookieCategories: consent?.categories ?? [],\n };\n}\n","/**\n * The legal documents are authored in markdown; consumers need markdown, HTML\n * and EmDash Portable Text. This parses the markdown **once** into a small block\n * model, and the three outputs render from that.\n *\n * The subset is **closed by construction** — we author every template, so the\n * parser does not need to be a markdown implementation, it needs to be exactly\n * as capable as the templates are. That is why it *throws* on anything outside\n * the subset rather than passing it through: an unrecognised construct that\n * silently degrades to a paragraph is how a published policy ends up with a\n * literal `| --- |` in it. A template that grows a table fails the test suite\n * instead.\n *\n * Supported, and nothing else:\n * block `#`/`##`/`###` headings, `- ` bullets, `> ` quote, paragraphs\n * inline `**strong**`, `` `code` ``\n *\n * HTML rendering delegates to `nodesToHtml` from `@getvitops/utils`, which\n * already solves escaping and void elements — this module maps to `ContentNode`\n * and stops there.\n */\nimport { nodesToHtml, type ContentNode } from '@getvitops/utils';\n\nexport interface Span {\n text: string;\n strong?: boolean;\n code?: boolean;\n}\n\nexport type Block =\n | { kind: 'heading'; level: 1 | 2 | 3; spans: Span[] }\n | { kind: 'paragraph'; spans: Span[] }\n | { kind: 'list'; items: Span[][] }\n | { kind: 'quote'; spans: Span[] };\n\n/** Constructs that look like markdown but are outside the subset. */\nconst UNSUPPORTED: [RegExp, string][] = [\n [/^#{4,}\\s/, 'headings deeper than ###'],\n [/^\\s*\\d+[.)]\\s/, 'ordered lists'],\n [/^\\s*```/, 'code fences'],\n [/^\\s*\\|/, 'tables'],\n [/^\\s*[*+]\\s/, 'bullets other than `- `'],\n [/^\\s+-\\s/, 'nested lists'],\n];\n\n// Bold and code spans, in one pass so a `**` inside backticks stays literal.\nconst INLINE = /(\\*\\*[^*]+\\*\\*|`[^`]+`)/g;\n\nfunction parseInline(text: string, where: string): Span[] {\n const spans: Span[] = [];\n let last = 0;\n for (const m of text.matchAll(INLINE)) {\n const token = m[0];\n if (m.index > last) spans.push({ text: text.slice(last, m.index) });\n if (token.startsWith('`')) spans.push({ text: token.slice(1, -1), code: true });\n else spans.push({ text: token.slice(2, -2), strong: true });\n last = m.index + token.length;\n }\n if (last < text.length) spans.push({ text: text.slice(last) });\n\n // Check what's left as literal text, so `**bold**` doesn't trip the `*` guard\n // and a cookie name like `_ga` (already inside a code span) doesn't either.\n for (const span of spans) {\n if (span.strong || span.code) continue;\n if (/!?\\[[^\\]]*\\]\\(/.test(span.text))\n throw new Error(\n `legal template uses links or images, which are outside the subset: ${where}`,\n );\n if (span.text.includes('**'))\n throw new Error(`legal template has an unmatched \\`**\\`: ${where}`);\n if (span.text.includes('`'))\n throw new Error(`legal template has an unmatched backtick: ${where}`);\n }\n return spans;\n}\n\n/** Markdown (our subset) → blocks. Throws on anything it does not model. */\nexport function parseMarkdown(md: string): Block[] {\n const blocks: Block[] = [];\n const lines = md.split('\\n');\n let paragraph: string[] = [];\n\n const flush = () => {\n if (paragraph.length === 0) return;\n const text = paragraph.join(' ');\n blocks.push({ kind: 'paragraph', spans: parseInline(text, text.slice(0, 60)) });\n paragraph = [];\n };\n\n for (const line of lines) {\n for (const [re, what] of UNSUPPORTED)\n if (re.test(line))\n throw new Error(`legal template uses ${what}, outside the subset: ${line}`);\n\n if (line.trim() === '') {\n flush();\n continue;\n }\n\n const heading = /^(#{1,3})\\s+(.*)$/.exec(line);\n if (heading) {\n flush();\n blocks.push({\n kind: 'heading',\n level: heading[1]!.length as 1 | 2 | 3,\n spans: parseInline(heading[2]!.trim(), line),\n });\n continue;\n }\n\n const quote = /^>\\s+(.*)$/.exec(line);\n if (quote) {\n flush();\n blocks.push({ kind: 'quote', spans: parseInline(quote[1]!.trim(), line) });\n continue;\n }\n\n const bullet = /^-\\s+(.*)$/.exec(line);\n if (bullet) {\n flush();\n const item = parseInline(bullet[1]!.trim(), line);\n // Consecutive `- ` lines are one list; a blank line between them starts a\n // new one, which is what markdown means and what the templates rely on.\n const prev = blocks[blocks.length - 1];\n if (prev?.kind === 'list') prev.items.push(item);\n else blocks.push({ kind: 'list', items: [item] });\n continue;\n }\n\n paragraph.push(line.trim());\n }\n flush();\n return blocks;\n}\n\n// ── ContentNode / HTML ──────────────────────────────────────────────────────────\n\nfunction spanNodes(spans: Span[]): ContentNode[] {\n return spans.map((s) =>\n s.strong ? { tag: 'strong', text: s.text } : s.code ? { tag: 'code', text: s.text } : s.text,\n );\n}\n\n/**\n * Blocks → `ContentNode[]`, the framework-agnostic tree the site config already\n * uses for `templates` of type `nodes` and `NodeRenderer.astro` already renders.\n */\nexport function toContentNodes(blocks: Block[]): ContentNode[] {\n return blocks.map((b): ContentNode => {\n switch (b.kind) {\n case 'heading':\n return { tag: `h${b.level}`, children: spanNodes(b.spans) };\n case 'paragraph':\n return { tag: 'p', children: spanNodes(b.spans) };\n case 'quote':\n return { tag: 'blockquote', children: [{ tag: 'p', children: spanNodes(b.spans) }] };\n case 'list':\n return {\n tag: 'ul',\n children: b.items.map((item) => ({ tag: 'li', children: spanNodes(item) })),\n };\n }\n });\n}\n\nexport function toHtmlFragment(blocks: Block[]): string {\n return nodesToHtml(toContentNodes(blocks));\n}\n\n// ── Portable Text (EmDash) ──────────────────────────────────────────────────────\n\n/**\n * Blocks → EmDash Portable Text, matching the shape already seeded in\n * `packages/create/templates/emdash/seed/seed.json`.\n *\n * Two deliberate mappings:\n * - the `# ` heading is **dropped** — in EmDash the page title is a field\n * (`data.title`), and repeating it as the first content block renders twice;\n * - the review blockquote becomes a `vitops.banner` with `tone: \"warning\"`,\n * which is exactly the block the hand-written placeholder pages used.\n *\n * `_key`s are derived from position rather than randomness, so regenerating an\n * unchanged config produces an identical seed and a clean diff.\n */\nexport function toPortableText(blocks: Block[], prefix: string): unknown[] {\n const out: unknown[] = [];\n blocks.forEach((b, i) => {\n const key = `${prefix}-${i}`;\n if (b.kind === 'heading' && b.level === 1) return;\n\n if (b.kind === 'quote') {\n out.push({\n _type: 'vitops.banner',\n _key: key,\n message: b.spans.map((s) => s.text).join(''),\n tone: 'warning',\n dismissible: false,\n });\n return;\n }\n\n const block = (spans: Span[], k: string, extra: Record<string, unknown>) => ({\n _type: 'block',\n _key: k,\n markDefs: [],\n children: spans.map((s, j) => ({\n _type: 'span',\n _key: `${k}-${j}`,\n text: s.text,\n marks: [s.strong && 'strong', s.code && 'code'].filter(Boolean),\n })),\n ...extra,\n });\n\n if (b.kind === 'list') {\n b.items.forEach((item, j) =>\n out.push(block(item, `${key}-${j}`, { style: 'normal', listItem: 'bullet', level: 1 })),\n );\n return;\n }\n\n out.push(block(b.spans, key, { style: b.kind === 'heading' ? `h${b.level}` : 'normal' }));\n });\n return out;\n}\n","/**\n * Pieces every legal template shares.\n *\n * Kept deliberately tiny: anything that grows here is prose leaking out of the\n * jurisdiction-specific templates into a shared file, which is how a document\n * ends up asserting something that isn't true of the body of law it claims to\n * follow. Formatting helpers belong here; sentences almost never do.\n */\nimport type { PolicyVars } from '../derive.ts';\n\n/**\n * The banner every generated document opens with.\n *\n * Not optional and not configurable. These documents are rendered from a\n * template by a build tool, not drafted for a specific business by someone who\n * can be asked follow-up questions — and the one failure mode with real\n * consequences is a consumer publishing one as-is. It is a blockquote so it\n * renders as a callout in HTML and as a warning banner in EmDash.\n */\nexport const REVIEW_NOTICE =\n \"> Generated from this site's configuration. It is a starting point, not legal advice — have it reviewed before you publish it, and make sure it matches what your site actually does.\";\n\n/** A markdown bullet list. Empty in, empty out — never a stray `-`. */\nexport function bullets(items: string[]): string {\n return items.map((item) => `- ${item}`).join('\\n');\n}\n\n/**\n * Taken from config rather than the clock, so a rebuild of an unchanged config\n * produces a byte-identical document.\n */\nexport function updatedLine(v: Pick<PolicyVars, 'lastUpdated'>): string {\n return v.lastUpdated ? `\\nLast updated: ${v.lastUpdated}\\n` : '';\n}\n","/**\n * Cookie notice — Canada.\n *\n * The one document here that is almost entirely derived: which cookies a site\n * sets follows from which providers it uses, and the config already knows that.\n * The prose is a frame around `v.processors` and `v.cookieCategories`.\n *\n * Rendered as headings and bullets rather than a table, deliberately — the\n * markdown subset the renderer supports is closed, and a table would widen it\n * for one document. Bullets also survive a narrow viewport, which a four-column\n * cookie table does not.\n */\nimport { list, type PolicyVars } from '../derive.ts';\nimport { bullets, REVIEW_NOTICE, updatedLine } from './shared.ts';\n\nexport function cookiesCa(v: PolicyVars): string {\n return `# Cookie Notice\n${updatedLine(v)}\n${REVIEW_NOTICE}\n\nThis notice explains how ${v.businessName} uses cookies and similar technologies on ${v.url} (the \"Site\"). It supplements our Privacy Policy.\n\n## What Cookies Are\n\nA cookie is a small text file that a website asks your browser to store. Cookies let a site remember things between pages and between visits — for example, that you have already dismissed a message. Similar technologies, such as local storage, do much the same thing.\n\n## What We Use Them For\n\n${bullets(v.cookiePurposes)}\n\nCookies used on this Site may track:\n\n${bullets(v.cookieTracked)}\n\n${providersSection(v)}${categoriesSection(v)}\n## Your Choices\n\n${bullets(v.cookieOptOutOptions)}\n\nMost browsers let you see which cookies are stored, delete them individually or in bulk, and block them entirely. Blocking all cookies will stop parts of the Site from working as intended.\n\n## Contact\n\nIf you have questions about our use of cookies, please contact us at ${v.mailingAddress}.\n`;\n}\n\n/**\n * \"This site sets no cookies\" is a real and increasingly common answer — a\n * cookieless analytics provider is a selling point, not an omission. Saying it\n * plainly beats an empty section that reads as an oversight.\n */\nfunction providersSection(v: PolicyVars): string {\n const setting = v.processors.filter((p) => p.cookies?.length);\n const cookieless = v.processors.filter((p) => p.cookies?.length === 0);\n\n if (setting.length === 0) {\n const named = cookieless.length\n ? ` The third party ${cookieless.length === 1 ? 'service' : 'services'} we use on this Site — ${list(\n cookieless.map((p) => p.name),\n )} — ${cookieless.length === 1 ? 'does' : 'do'} not set cookies of ${\n cookieless.length === 1 ? 'its' : 'their'\n } own.`\n : '';\n return `## Cookies Set on This Site\n\nBeyond the cookies strictly necessary to serve and secure the Site, we do not set cookies.${named}\n`;\n }\n\n return `## Cookies Set on This Site\n\n${bullets(\n setting.map(\n (p) =>\n // Cookie names go in code spans, not bare: `_ga, _gid` in running markdown\n // is a matched pair of underscores, which a downstream renderer turns into\n // emphasis and eats the names.\n `**${p.name}** (${p.purpose}) — ${(p.cookies ?? []).map((c) => `\\`${c}\\``).join(', ')}${\n p.privacyUrl ? `. Privacy policy: ${p.privacyUrl}` : ''\n }`,\n ),\n)}\n${\n cookieless.length\n ? `\\nWe also use ${list(cookieless.map((p) => p.name))}, which ${\n cookieless.length === 1 ? 'does' : 'do'\n } not set cookies of ${cookieless.length === 1 ? 'its' : 'their'} own.\\n`\n : ''\n}`;\n}\n\n/** Only meaningful when a consent tool actually offers the categories. */\nfunction categoriesSection(v: PolicyVars): string {\n if (v.consentModel === 'none' || v.cookieCategories.length === 0) return '';\n return `\n## Cookie Categories\n\nOur consent controls group cookies into the following categories, which you can accept or decline${\n v.consentModel === 'opt-in'\n ? ' before any non-essential cookie is set'\n : ' at any time after your first visit'\n }:\n\n${bullets(v.cookieCategories)}\n`;\n}\n","/**\n * Privacy policy — Canada (PIPEDA).\n *\n * Ported from the pandoc prototype at `packages/core/legal-templates/`. Two\n * things changed in the port and both are load-bearing:\n *\n * 1. `${var}` is now real TypeScript interpolation rather than a pandoc Lua\n * filter, so an unresolved variable is a compile error. The filter left\n * unknown keys as the literal text `${key}` — which would ship a live\n * privacy policy containing `${countries}`.\n * 2. Lists are built from arrays, not by splicing a string into a fixed bullet.\n * An empty derived value used to produce a stray `- ; and` bullet.\n *\n * The prose is jurisdiction-specific: it names the Office of the Privacy\n * Commissioner of Canada and frames transfers as \"outside of Canada\". Do not\n * reuse it for another jurisdiction — add a sibling template instead.\n */\nimport type { PolicyVars } from '../derive.ts';\nimport { bullets, REVIEW_NOTICE, updatedLine } from './shared.ts';\n\nexport function privacyCa(v: PolicyVars): string {\n return `# Privacy Policy\n${updatedLine(v)}\n${REVIEW_NOTICE}\n\nThis is the privacy policy of ${v.businessName} (\"Business\"). It summarizes what personal information we collect and how we use and disclose this information.\n\nBy using our website (the \"Site\"), you signify your consent to the terms of our Privacy Policy. If you do not agree with any terms of this Privacy Policy, please do not use this Site or submit any personal information to us, or use the preference tools we provide to adjust your settings. This Privacy Policy also describes certain choices you have on how we use your personal information.\n\nWe reserve the right to modify this Privacy Policy at any time. We will reflect any such modifications to this Privacy Policy on our Site. We suggest that you periodically consult this Privacy Policy. Your continued use of the Site after any such changes constitutes your acceptance of this Privacy Policy, as revised.\n\n**Privacy Policy Summary.**\n\n${bullets([\n 'What Personal Information We Collect',\n 'How We Use Personal Information',\n 'How We Share Personal Information',\n 'Your Choices',\n])}\n\n## Full Privacy Policy\n\n### What Personal Information We Collect and How We Collect It\n\nPersonal information is information about an identifiable individual. We collect personal information only for purposes that a reasonable person would consider appropriate in the circumstances and only with your knowledge and consent, except where otherwise required or permitted by law. Business collects personal information when you voluntarily provide it through our Site or when you provide it to us through other means. For example, we may collect personal information when you:\n\n${bullets(v.collectionReasons)}\n\nThe personal information we may collect will depend on the service you request and may include:\n\n${bullets(v.piiCollected)}\n\n### How Business Collects Information Through Technological Means\n\nWhen you visit our Site, we may collect information that is automatically sent to us by your web browser. This information may include:\n\n${bullets(v.techInfo)}\n\nWe use this information to:\n\n${bullets(v.techInfoPurposes)}\n\nThe amount of information that is sent by your web browser depends on the browser and settings you use. Please refer to the instructions provided by your browser if you want to learn more about what information it sends to websites you visit or how you may change or restrict this.\n\nBusiness may use cookies and other similar devices on this Site to enhance functionality. These devices may track information which includes:\n\n${bullets(v.cookieTracked)}\n\nWe use this information to:\n\n${bullets(v.cookiePurposes)}\n\nIf you wish to disable cookies, refer to your browser help menu to learn how.${v.cookieTool ? ` ${v.cookieTool}` : ''}\n\n### How Business Uses and Discloses Personal Information\n\nThe personal information we collect may be used by Business for the purposes for which it was collected, as provided in this Privacy Policy, or for other purposes that are disclosed to you and to which you consent.\n\nFor example, we may use your personal information to:\n\n${bullets(v.usePurposes)}\n\n${providersSection(v)}\n\nBusiness reserves the right to transfer personal information in the event that we merge with or are acquired by a third party. We also may disclose your personal information for any other purpose required or permitted by law or to which you consent.\n\n### Your Choices\n\n${bullets(v.optOutOptions)}\n\n### How We Protect Personal Information\n\nThe security of your personal information is important to us. We protect your personal information in our control through appropriate security safeguards against loss, theft, unauthorized access, disclosure, copying, use or modification. These safeguards include physical measures (such as locked filing cabinets), organizational measures (such as employee training and restricted access), and technological measures (such as encryption and passwords). Personal information may be accessed by persons within our organization who require such access to carry out the purposes described in this Privacy Policy, or such other purposes as permitted or required by law. Personal information we collect is maintained with the source of the information at ${v.url}.\n\nWe retain personal information that we collect only as long as necessary for the purposes for which it was collected or to meet legal requirements. We destroy personal information when it is no longer needed for such purposes.${v.retention ? ` In general, we keep personal information for ${v.retention}.` : ''}\n\nIt is important to understand that no security measures are absolute. We cannot guarantee the safety of any information you provide to us.\n${transferSection(v)}\n### Accessing and Correcting Your Personal Information\n\nYou have a right to access your personal information and to request a correction to it if you believe it is inaccurate. If you have submitted personal information and would like to have access to it, or if you would like to have it corrected, please contact us using the contact information provided below. We may require you verify your identity before allowing you to access your personal information.\n\n### How to Contact Us\n\nIf you have any questions regarding this Privacy Policy, to submit a complaint, or to access or correct your information, please contact our Privacy Officer at ${v.mailingAddress}. If you are not satisfied with our response to your privacy concerns, you may contact the Office of the Privacy Commissioner of Canada at www.priv.gc.ca or 1-800-282-1376.\n`;\n}\n\n/**\n * Named separately because a site with no third parties at all should not claim\n * to have service providers, and one with them owes the reader their identity —\n * \"we may share with service providers\" without naming them is the vaguest and\n * least useful sentence a policy can contain.\n */\nfunction providersSection(v: PolicyVars): string {\n if (v.processors.length === 0)\n return 'We do not transfer personal information to third party service providers.';\n return `We may transfer personal information to third party service providers that assist us with carrying out these purposes. When we transfer personal information to service providers, we require them to protect the information in a manner consistent with our privacy practices and applicable privacy laws. These service providers are:\n\n${bullets(\n v.processors.map(\n (p) => `${p.name}, for ${p.purpose}${p.privacyUrl ? ` (privacy policy: ${p.privacyUrl})` : ''}`,\n ),\n)}\n\nWe remain responsible for personal information in the possession of our service providers.`;\n}\n\n/** Omitted entirely when nothing leaves the country — a false claim otherwise. */\nfunction transferSection(v: PolicyVars): string {\n if (!v.countries) return '';\n return `\n### We May Transfer Personal Information to Other Countries\n\nSome or all of the personal information we collect may be stored or processed in jurisdictions outside of Canada, including ${v.countries}. As a result, this information may be subject to access requests from governments, courts or law enforcement in those jurisdictions according to laws in those jurisdictions.\n`;\n}\n","/**\n * Terms of service — Canada.\n *\n * Unlike the privacy policy, this has no prototype in the repo to port: the\n * prose is new. It is written as **generic website terms** — the clauses almost\n * every informational site needs (acceptable use, intellectual property,\n * disclaimer, limitation of liability, governing law) and nothing more.\n *\n * It deliberately does NOT cover the things that actually vary between\n * businesses and carry the most risk: sales and refunds, subscriptions and\n * renewals, user-generated content and its moderation, accounts and\n * termination, professional advice, or anything sector-regulated. A site doing\n * any of those needs clauses drafted for it — the review banner says so, and\n * this file should not grow them, because a template that half-covers payments\n * is more dangerous than one that visibly omits them.\n */\nimport type { PolicyVars } from '../derive.ts';\nimport { bullets, REVIEW_NOTICE, updatedLine } from './shared.ts';\n\nexport function termsCa(v: PolicyVars): string {\n return `# Terms of Service\n${updatedLine(v)}\n${REVIEW_NOTICE}\n\nThese terms govern your use of ${v.url} (the \"Site\"), operated by ${v.businessName} (\"we\", \"us\"). By accessing or using the Site, you agree to these terms. If you do not agree to them, please do not use the Site.\n\nWe may change these terms from time to time. The version published on the Site is the one that applies, and your continued use of the Site after a change means you accept the revised terms.\n\n## Use of the Site\n\nYou may use the Site for lawful purposes only. You agree not to:\n\n${bullets([\n 'use the Site in any way that breaches any applicable law or regulation',\n 'attempt to gain unauthorized access to the Site, its servers, or any connected system',\n 'interfere with or disrupt the operation of the Site, including by introducing malicious code',\n 'collect or harvest information about other users of the Site',\n 'reproduce, duplicate, or resell any part of the Site except as these terms permit',\n])}\n\nWe may suspend or withdraw access to the Site, in whole or in part, at any time and without notice.\n\n## Intellectual Property\n\nUnless stated otherwise, the content of the Site — including text, graphics, logos, and layout — is owned by or licensed to us and is protected by copyright and other intellectual property laws. You may view, download, and print content from the Site for your own personal, non-commercial use. Any other use requires our prior written permission.\n\n## Accuracy of Information\n\nWe take reasonable care to keep the Site accurate and current, but we make no representation or warranty that the content is complete, accurate, or up to date. Content on the Site is provided for general information only and should not be relied on as advice for your particular circumstances.\n\n## Third Party Links and Services\n\nThe Site may link to, or rely on, websites and services operated by others. We do not control those sites and services and are not responsible for their content, availability, or practices. A link is not an endorsement.\n\n## Disclaimer\n\n**The Site is provided \"as is\" and \"as available\", without warranty of any kind, whether express or implied.** To the fullest extent permitted by law, we disclaim all warranties, including implied warranties of merchantability, fitness for a particular purpose, and non-infringement. We do not warrant that the Site will be uninterrupted, secure, or error free.\n\n## Limitation of Liability\n\n**To the fullest extent permitted by law, we will not be liable for any indirect, incidental, special, consequential, or punitive damages, or for any loss of profits, revenue, data, or goodwill, arising out of or in connection with your use of the Site** — whether the claim is based in contract, tort, or any other legal theory, and whether or not we were advised of the possibility of such damages.\n\nNothing in these terms excludes or limits liability that cannot be excluded or limited under applicable law.\n\n## Privacy\n\nOur handling of personal information is described in our Privacy Policy, which forms part of these terms.\n\n## Governing Law\n\nThese terms are governed by the laws of ${governingLaw(v)}. You agree to the exclusive jurisdiction of the courts of that jurisdiction for any dispute arising out of or in connection with these terms or the Site.\n\n## Contact\n\nIf you have questions about these terms, please contact us at ${v.mailingAddress}.\n`;\n}\n\n/**\n * Canadian law is split between the provinces and the federal Parliament, so the\n * conventional clause names both. Without a province we can only name the\n * country — better a broader clause than one asserting a province we guessed.\n */\nfunction governingLaw(v: PolicyVars): string {\n if (v.governingLaw) return v.governingLaw;\n return v.governingProvince\n ? `${v.governingProvince} and the federal laws of ${v.governingCountry} applicable therein`\n : v.governingCountry;\n}\n","/**\n * The jurisdiction registry.\n *\n * Adding a jurisdiction is: author the three templates, add one key here, add\n * one member to `JURISDICTIONS` in `config.ts`. The `satisfies` below makes the\n * second and third steps a compile error if you skip either — a config could\n * otherwise name a jurisdiction with no templates behind it and silently render\n * against the wrong body of law.\n *\n * Every jurisdiction owes all three documents. A partial set would mean\n * `legal.termsOfService.enabled` silently emitting nothing.\n */\nimport type { Jurisdiction } from '../../config.ts';\nimport type { PolicyVars } from '../derive.ts';\nimport { cookiesCa } from './cookies.ca.ts';\nimport { privacyCa } from './privacy.ca.ts';\nimport { termsCa } from './terms.ca.ts';\n\nexport type LegalDoc = 'privacy' | 'terms' | 'cookies';\n\nexport type DocSet = Record<LegalDoc, (v: PolicyVars) => string>;\n\nexport const TEMPLATES = {\n ca: { privacy: privacyCa, terms: termsCa, cookies: cookiesCa },\n} satisfies Record<Jurisdiction, DocSet>;\n\n/** Stable output order, independent of which docs a given config enables. */\nexport const DOC_ORDER: LegalDoc[] = ['privacy', 'terms', 'cookies'];\n\n/** Output filename stem per document — also the Bricks shortcode's allowlist. */\nexport const DOC_SLUGS: Record<LegalDoc, string> = {\n privacy: 'privacy-policy',\n terms: 'terms-of-service',\n cookies: 'cookie-notice',\n};\n","/**\n * Generate a site's legal documents from its config.\n *\n * Shaped after `generateDocs` rather than after a `generate()` format, and the\n * reason is structural: `generate()` is keyed to a **`DesignSystem`**, while a\n * privacy policy renders from a **`Config`**. Bolting it on as a `Format`\n * would mean a format that ignores its own input. So this is a sibling public\n * function that returns a `{ relPath: content }` map and lets each caller write\n * it where it belongs — the CLI to stdout or a directory, the bricks build into\n * `dist/legal/`, the Astro integration into a content collection.\n *\n * Pure: no filesystem, no clock, no shared state.\n */\nimport { derivePolicyVars, type PolicyVars } from './derive.ts';\nimport { parseMarkdown, toContentNodes, toHtmlFragment, toPortableText } from './render.ts';\nimport { DOC_ORDER, DOC_SLUGS, TEMPLATES, type LegalDoc } from './templates/index.ts';\nimport type { Config } from '../config.ts';\nimport type { ContentNode } from '@getvitops/utils';\n\nexport type LegalOutput = 'md' | 'html' | 'portable-text';\n\nexport interface GenerateLegalOptions {\n /** Which documents to render. Defaults to those enabled in the config. */\n docs?: LegalDoc[];\n /** Output format. Default `md`. */\n output?: LegalOutput;\n}\n\nconst EXT: Record<LegalOutput, string> = {\n md: 'md',\n html: 'html',\n 'portable-text': 'json',\n};\n\n/** Which documents the config asks for, in a stable order. */\nexport function enabledDocs(cfg: Config): LegalDoc[] {\n const legal = cfg.site.legal;\n const on: Record<LegalDoc, boolean> = {\n privacy: !!legal?.privacyPolicy?.enabled,\n terms: !!legal?.termsOfService?.enabled,\n cookies: !!legal?.cookieConsent?.enabled,\n };\n return DOC_ORDER.filter((d) => on[d]);\n}\n\n/** Render one document to markdown. The other outputs derive from this. */\nexport function renderMarkdown(cfg: Config, doc: LegalDoc, vars?: PolicyVars): string {\n const jurisdiction = cfg.site.legal?.jurisdiction ?? 'ca';\n // `validateConfig` rejects an unregistered jurisdiction, so this is a guard for\n // callers that skipped validation rather than an expected path.\n const set = TEMPLATES[jurisdiction];\n if (!set) throw new Error(`no legal templates for jurisdiction \"${jurisdiction}\"`);\n return set[doc](vars ?? derivePolicyVars(cfg));\n}\n\n/**\n * Render one document as a `ContentNode` tree — the framework-agnostic shape the\n * site config already uses for `templates` of type `nodes`, so an Astro consumer\n * can hand it to `NodeRenderer` instead of injecting a string of HTML.\n */\nexport function renderNodes(cfg: Config, doc: LegalDoc): ContentNode[] {\n return toContentNodes(parseMarkdown(renderMarkdown(cfg, doc)));\n}\n\n/**\n * Every enabled legal document, keyed by output path.\n *\n * Documents are keyed by filename (`privacy-policy.md`) rather than by document\n * id so a caller can write the map verbatim.\n */\nexport function generateLegal(\n cfg: Config,\n opts: GenerateLegalOptions = {},\n): Record<string, string> {\n const output = opts.output ?? 'md';\n const docs = opts.docs ?? enabledDocs(cfg);\n // Derived once: every document asserts the same facts, and re-deriving per\n // document would let them disagree if the derivation ever stopped being pure.\n const vars = derivePolicyVars(cfg);\n\n const out: Record<string, string> = {};\n for (const doc of docs) {\n const md = renderMarkdown(cfg, doc, vars);\n const slug = DOC_SLUGS[doc];\n const content =\n output === 'md'\n ? md\n : output === 'html'\n ? toHtmlFragment(parseMarkdown(md))\n : JSON.stringify(toPortableText(parseMarkdown(md), slug), null, 2) + '\\n';\n out[`${slug}.${EXT[output]}`] = content;\n }\n return out;\n}\n\nexport { derivePolicyVars, type PolicyVars } from './derive.ts';\nexport { detectProcessorKeys, KNOWN_PROCESSORS, resolveProcessors } from './providers.ts';\nexport type { KnownProcessorKey, Processor } from './providers.ts';\nexport { parseMarkdown, toContentNodes, toHtmlFragment, toPortableText } from './render.ts';\nexport type { Block, Span } from './render.ts';\nexport { DOC_ORDER, DOC_SLUGS, TEMPLATES } from './templates/index.ts';\nexport type { DocSet, LegalDoc } from './templates/index.ts';\n","/**\n * Build an SVG sprite from an icon `include` map.\n *\n * This is the delivery path for consumers that cannot run an icon integration:\n * Bricks/WordPress, EmDash's renderers, anything rendering HTML outside an Astro\n * build. Markup is `<svg><use href=\"…/icons.svg#ph--caret-down\"/></svg>` — no\n * runtime JS and no network call, which is what keeps it inside the tier rules\n * (a runtime-fetching element would be behaviour JS with no fallback to enhance).\n *\n * The icon DATA comes from the `@iconify-json/*` collections, which stay optional\n * peers loaded dynamically: `@iconify-json/ph` alone is ~4.5 MB and the semantic\n * map spans five sets, so depending on them directly would be indefensible for\n * every consumer who never asks for a sprite.\n */\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { IconifyJSON } from '@iconify/types';\nimport { getIconData, iconToSVG, replaceIDs } from '@iconify/utils';\n\nexport interface IconSpriteOptions {\n /** Exactly `generateIconInclude()`'s shape: collection → icon names. */\n include: Record<string, string[]>;\n /**\n * Extra ids pointing at an already-included icon, e.g. `{ 'icon-menu': 'ph:list' }`,\n * so a consumer can reference a semantic name without knowing the set.\n */\n aliases?: Record<string, string>;\n /**\n * Directory to resolve `@iconify-json/*` from. Defaults to `process.cwd()`.\n *\n * Load-bearing: the collections are the CONSUMER's dependency, not this\n * package's, so a bare `import('@iconify-json/ph/…')` from inside the\n * generator resolves against the generator's own node_modules and misses them\n * entirely — which reads as \"not installed\" on a project that has them.\n */\n resolveFrom?: string;\n /** Injected in tests so the emitter can run without any @iconify-json/* installed. */\n loadSet?: (prefix: string) => Promise<IconifyJSON | null>;\n}\n\nexport interface IconSpriteResult {\n svg: string;\n /** Every `<symbol>` id emitted, in order. */\n ids: string[];\n /** `prefix:name` entries that were asked for but not found. */\n missing: string[];\n}\n\n/**\n * `ph:caret-down` → `ph--caret-down`.\n *\n * The one place this grammar lives. `Icon.astro` mirrors it and `icon.test.ts`\n * guards the pair, because a drift here resolves `<use>` to nothing and renders\n * as an empty box rather than an error.\n */\nexport function spriteId(qualified: string): string {\n return qualified.replace(':', '--');\n}\n\n/**\n * Default loader: the collection JSON shipped by `@iconify-json/<prefix>`.\n *\n * Resolved through a `createRequire` rooted at the consumer's directory, then\n * imported by absolute path — a bare specifier would resolve against this\n * package instead, where the collections deliberately aren't installed.\n */\nasync function loadCollection(prefix: string, from: string): Promise<IconifyJSON | null> {\n try {\n const req = createRequire(pathToFileURL(join(from, 'noop.js')));\n const path = req.resolve(`@iconify-json/${prefix}/icons.json`);\n const mod = await import(pathToFileURL(path).href, { with: { type: 'json' } });\n return (mod.default ?? mod) as IconifyJSON;\n } catch {\n return null;\n }\n}\n\nexport async function buildIconSprite(o: IconSpriteOptions): Promise<IconSpriteResult> {\n const from = o.resolveFrom ?? process.cwd();\n const load = o.loadSet ?? ((prefix: string) => loadCollection(prefix, from));\n const symbols: string[] = [];\n const ids: string[] = [];\n const missing: string[] = [];\n /** qualified name → its rendered body+viewBox, so an alias can reuse it. */\n const rendered = new Map<string, { viewBox: string; body: string }>();\n\n for (const [prefix, names] of Object.entries(o.include)) {\n if (!names?.length) continue;\n const set = await load(prefix);\n if (!set) {\n throw new Error(\n `[vitops icons] Cannot build the sprite: the \"${prefix}\" icon set is not installed. ` +\n `Run \\`pnpm add -D @iconify-json/${prefix}\\`, or drop it from your icons config.`,\n );\n }\n for (const name of names) {\n // getIconData resolves aliases and parent chains, so `include` can name\n // either a real icon or one of the set's own aliases.\n const data = getIconData(set, name);\n if (!data) {\n missing.push(`${prefix}:${name}`);\n continue;\n }\n const built = iconToSVG(data, { height: 'none' });\n // MANDATORY. Two icons carrying the same internal gradient/clip id would\n // otherwise collide once concatenated into one document, and the second\n // silently renders with the first's paint.\n const body = replaceIDs(built.body);\n const id = spriteId(`${prefix}:${name}`);\n rendered.set(`${prefix}:${name}`, { viewBox: built.attributes.viewBox, body });\n ids.push(id);\n symbols.push(`<symbol id=\"${id}\" viewBox=\"${built.attributes.viewBox}\">${body}</symbol>`);\n }\n }\n\n for (const [alias, target] of Object.entries(o.aliases ?? {})) {\n const hit = rendered.get(target);\n if (!hit) {\n missing.push(`${target} (aliased as ${alias})`);\n continue;\n }\n // The body is DUPLICATED rather than nested as <use href=\"#target\"> inside\n // the symbol. Nested-use is legal but unreliable precisely under an\n // external-file <use>, which is exactly how this sprite is consumed; a\n // handful of duplicated paths in a ~40 KB file is the cheaper trade.\n ids.push(alias);\n symbols.push(`<symbol id=\"${alias}\" viewBox=\"${hit.viewBox}\">${hit.body}</symbol>`);\n }\n\n const svg =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" style=\"display:none\" aria-hidden=\"true\">` +\n symbols.join('') +\n `</svg>\\n`;\n\n return { svg, ids, missing };\n}\n\n/**\n * One icon's renderable parts, for inlining into markup.\n *\n * Exists because `<Icon />` cannot go through astro-icon: its `./components`\n * entry is a TypeScript file that Vite must transform, so it can only be\n * reached by a statically-analysable import — and a static import is exactly\n * what made the optional peer mandatory for anyone rendering Popover, Details\n * or Drawer. Reading the collection directly sidesteps the peer entirely and\n * shares this file's loader with the sprite, so both paths draw the same glyph.\n */\nexport async function loadIconSvg(\n qualified: string,\n opts?: { resolveFrom?: string; loadSet?: (prefix: string) => Promise<IconifyJSON | null> },\n): Promise<{ viewBox: string; body: string } | null> {\n const i = qualified.indexOf(':');\n if (i <= 0) return null;\n const prefix = qualified.slice(0, i);\n const name = qualified.slice(i + 1);\n const from = opts?.resolveFrom ?? process.cwd();\n const load = opts?.loadSet ?? ((p: string) => loadCollection(p, from));\n const set = await load(prefix);\n if (!set) return null;\n const data = getIconData(set, name);\n if (!data) return null;\n const built = iconToSVG(data, { height: 'none' });\n // Same id-collision guard as the sprite: several inlined icons share one\n // document, so an un-rewritten gradient id would cross-render.\n return { viewBox: built.attributes.viewBox, body: replaceIDs(built.body) };\n}\n","/**\n * Pure, parameterized port of the Vitops design-system generator.\n *\n * `generate({ input, format, outDir })` reads a consumer's `design-system.json`,\n * validates it, and emits consumer-ready output for the chosen format into\n * `outDir`. Unlike the original CWD-bound script it mutates no shared state: every\n * generated token layer is built in memory and either bundled (css/bricks) or\n * inlined (tailwind) before writing.\n *\n * Framework-static assets (the hand-written CSS partials, the Bricks PHP + loader,\n * and the pre-built JS bundles) live under `assets/` in this package and are read /\n * copied from there — they are the same for every consumer.\n */\nimport { readFileSync, writeFileSync, mkdirSync, cpSync, existsSync, readdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createHash } from 'node:crypto';\nimport { transform } from 'lightningcss';\nimport { validate, type DesignSystem } from './schema.ts';\nimport { generateDocs } from './docs.ts';\nimport { emitDesignMd } from './design-md.ts';\nimport { generateLegal } from './legal/index.ts';\nimport { buildIconSprite } from './icons-sprite.ts';\nimport { resolveInput, resolveConfig, type Config } from './config.ts';\nimport { generateIconInclude, resolveIcon } from '@getvitops/utils';\nimport {\n BASE_HOOK,\n DARK_SEL,\n SYSTEM_DARK_SEL,\n TW_CLASH,\n type RoleSpec,\n roleHue,\n roleKind,\n} from './shared.ts';\nimport {\n checkContrast,\n expandPalette,\n functionalRole,\n ladderWarnings,\n monotonicityErrors,\n NUMERIC_STEPS,\n tokenClass,\n tokenVar,\n type ExpandedHue,\n type FunctionalRole,\n} from './tokens.ts';\n\nexport type Format = 'bricks' | 'css' | 'tailwind' | 'design';\n\n/**\n * Formats that emit a stylesheet. `design` is the odd one out — it emits a\n * single `DESIGN.md` brief and no CSS at all — so anything that expects to\n * import the generator's output (the Vite plugin's injected stylesheet, the\n * Astro integration) types against this narrower set.\n */\nexport type StylesheetFormat = Exclude<Format, 'design'>;\n\nexport interface GenerateOptions {\n /**\n * The config to build from — a path, or an already-parsed object.\n *\n * **Either kind is accepted.** A bare `design-system.json`, or the larger\n * `Config` that embeds one (commonly `company.json` / `site.json`), in\n * which case the design system is `designSystem.themes[theme]` with its\n * `extends` chain resolved. The two are told apart by shape, not by filename —\n * see `isConfig`.\n *\n * Passing a site config here also supplies `site`, so the site-level facts\n * generation depends on (`designSystem.defaultColorScheme`, the legal\n * documents, the icon sprite) don't need the same path declared twice. Each of\n * those is still gated on a field in that config, so nothing new appears\n * unless the config asks for it.\n */\n input: string | DesignSystem | Config;\n /** Output target. Default: 'bricks'. */\n format?: Format;\n /** Directory to write outputs into. Default: 'dist'. */\n outDir?: string;\n /** Override the framework asset root (advanced/testing). */\n assetsDir?: string;\n /**\n * Which `designSystem.themes` entry to build. Default: the config's\n * `defaultTheme`, else `default`. An error on a bare `design-system.json`,\n * which holds one design system and no themes map.\n */\n theme?: string;\n /**\n * Environment whose A/B variant applies to the site config, wherever it came\n * from (`input` or `site`). Default: `'production'`.\n */\n siteEnv?: string;\n /**\n * The site config, when it is a *different* file from `input` — enabling\n * legal-document output into `<outDir>/legal/*.html` and supplying\n * `designSystem.defaultColorScheme`.\n *\n * Redundant when `input` is already a site config; set both and this one wins.\n */\n site?: string | Config;\n /**\n * Emit the `prefers-color-scheme: dark` block (see `BuildOptions`).\n *\n * Normally this comes from the site config's `designSystem.defaultColorScheme: \"system\"`, which\n * is where the fact belongs. This is the escape hatch for consumers with a\n * `design-system.json` and no site config at all: requiring a whole\n * `Config` — which must carry a full `designSystem` — to set one boolean\n * would be out of proportion. Set explicitly, it wins over the site config.\n */\n systemColorScheme?: boolean;\n}\n\nexport interface GenerateResult {\n format: Format;\n outDir: string;\n written: string[];\n}\n\nconst HERE = dirname(fileURLToPath(import.meta.url));\nconst DEFAULT_ASSETS = join(HERE, '..', 'assets');\n\n// ── colour machinery ─────────────────────────────────────────────────────────\n// Every hue is an 11-step numeric OKLCH scale on a shared lightness ladder (see\n// tokens.ts); every role resolves to `--color-<target>-<role>[-<variant>]`.\n// Dark mode re-points which step each token reads; the solid family is stable.\nconst UTILITY_PROPS: Record<string, string> = {\n bg: 'background-color',\n text: 'color',\n icon: 'color',\n border: 'border-color',\n outline: 'outline-color',\n fill: 'fill',\n stroke: 'stroke',\n};\n\n/**\n * Which token target a utility family draws from. Four families have tokens of\n * their own; the other three are aliases, because an SVG fill wants the icon\n * tier (3:1, may run vivid) and an outline wants the border tier — minting\n * separate tokens for them would be three more things to keep in contrast.\n */\nconst UTILITY_SOURCE: Record<string, string> = {\n bg: 'bg',\n text: 'text',\n icon: 'icon',\n border: 'border',\n outline: 'border',\n fill: 'icon',\n stroke: 'icon',\n};\n\n/** The target segment of a token key (`bg-solid-bold` → `bg`). */\nconst targetOf = (key: string): string => {\n const i = key.indexOf('-');\n return i === -1 ? key : key.slice(0, i);\n};\n\nexport interface ColorUtility {\n /** Class name, without the leading dot. */\n cls: string;\n /** CSS property the class sets. */\n prop: string;\n /** `var(--…)` reference the class resolves to. */\n value: string;\n}\n\n/**\n * The framework's container breakpoints. `sm-`/`md-`/`lg-`/`xl-` prefixes in the\n * css/bricks formats; `@sm:`/`@md:`/… in tailwind, where they are registered as\n * `--container-*` in `@theme` and Tailwind expands the variants itself.\n */\nexport const BREAKPOINTS: readonly (readonly [string, string])[] = [\n ['sm', '30rem'],\n ['md', '48rem'],\n ['lg', '64rem'],\n ['xl', '80rem'],\n] as const;\n\n/**\n * Gap utilities over the space scale, emitted from one list into all three\n * formats — same arrangement as `roleColorUtilities`, for the same reason.\n *\n * These did not exist. `vitops docs css` advertised a `g` class that was never\n * emitted, so the honest answer for a css/bricks consumer was an inline\n * `style=\"gap: …\"`, which is what this repo's own `index.html` does throughout.\n * Tailwind does not fill the hole either: the fluid space steps are deliberately\n * kept OUT of Tailwind's `--spacing-*` namespace (named keys there shadow the\n * size scales — `max-w-7xl` would resolve to `var(--spacing-7xl)`), so `gap-md`\n * is not something Tailwind can derive on its own. Measured against\n * tailwindcss@4.3.3: an explicit `@utility gap-md` is honoured, coexists with\n * the built-in numeric `gap-4`, and picks up variants (`@md:gap-md`).\n *\n * The whole matrix is emitted rather than a useful-looking subset: an undefined\n * step produces no rule and no error in either format, so a missing\n * `md-gap-x-2xl` would be indistinguishable from a working one.\n */\nexport function gapUtilities(steps: { name: string }[]): ColorUtility[] {\n const FAMILIES: [string, string][] = [\n ['gap', 'gap'],\n ['gap-x', 'column-gap'],\n ['gap-y', 'row-gap'],\n ];\n return steps.flatMap(({ name }) =>\n FAMILIES.map(([prefix, prop]) => ({\n cls: `${prefix}-${name}`,\n prop,\n value: `var(--space-${name})`,\n })),\n );\n}\n\n/**\n * Every role colour utility, each class name emitted EXACTLY once.\n *\n * There is now a single axis. The target lives *inside* the token name, so\n * `bg-danger-muted` and `text-danger-muted` are different tokens and the\n * collision the old plane/stop precedence rule existed to arbitrate cannot\n * arise. Both the css/bricks and tailwind paths render from this one list, which\n * is what keeps the three formats in step; `format-parity.test.ts` holds them\n * there.\n *\n * The class name IS the token name minus `--color-`, so there is no separate\n * naming rule to drift — see `tokenClass` in tokens.ts.\n */\nexport function roleColorUtilities(\n roles: readonly FunctionalRole[],\n utilities: readonly string[],\n): ColorUtility[] {\n const out: ColorUtility[] = [];\n for (const fr of roles) {\n for (const fam of utilities) {\n const source = UTILITY_SOURCE[fam];\n if (source == null) continue;\n for (const key of Object.keys(fr.light)) {\n if (targetOf(key) !== source) continue;\n const canonical = tokenClass(fr.role, key);\n // Alias families keep the token but rename the leading segment:\n // `border-danger-bold` → `outline-danger-bold`.\n const cls = fam === source ? canonical : fam + canonical.slice(source.length);\n out.push({\n cls,\n prop: UTILITY_PROPS[fam] as string,\n value: `var(${tokenVar(fr.role, key)})`,\n });\n }\n }\n }\n return out;\n}\n\n/** Render the shared set as plain rules (css/bricks formats). */\nconst colorUtilityRules = (u: ColorUtility[]): string =>\n u.map(({ cls, prop, value }) => `.${cls} { ${prop}: ${value}; }`).join('\\n');\n\nconst decls = (obj: Record<string, string>, indent = ' ') =>\n Object.entries(obj)\n .map(([k, v]) => `${indent}${k}: ${v};`)\n .join('\\n');\n\n// ── fluid modular scale ───────────────────────────────────────────────────────\ninterface ScaleConfig {\n base: string;\n ratio: number;\n steps?: number;\n names?: string[];\n baseStep?: number;\n baseline?: string;\n fluid?: { minVw: string; maxVw: string; minRatio: number };\n}\ninterface ScaleStep {\n name: string;\n value: string;\n max: string;\n offset: number;\n}\nconst round = (n: number) => Number(n.toFixed(4)).toString();\nconst rem = (v: string) => parseFloat(v);\nconst buildScale = (s: ScaleConfig): ScaleStep[] => {\n const names = s.names ?? Array.from({ length: s.steps ?? 0 }, (_, i) => String(i + 1));\n const base = rem(s.base);\n const baseStep = s.baseStep ?? Math.ceil(names.length / 2);\n const baselineIdx = s.baseline ? names.indexOf(s.baseline) : baseStep - 1;\n return names.map((name, i) => {\n const k = i - (baseStep - 1);\n const vMax = base * Math.pow(s.ratio, k);\n const max = `${round(vMax)}rem`;\n let value = max;\n if (s.fluid) {\n const { minVw, maxVw, minRatio } = s.fluid;\n const vMin = base * Math.pow(minRatio, k);\n const lo = Math.min(vMin, vMax);\n const hi = Math.max(vMin, vMax);\n if (lo !== hi) {\n const slope = (vMax - vMin) / (rem(maxVw) - rem(minVw));\n const intercept = vMin - slope * rem(minVw);\n const sign = slope < 0 ? '-' : '+';\n const pref = `calc(${round(intercept)}rem ${sign} ${round(Math.abs(slope * 100))}vw)`;\n value = `clamp(${round(lo)}rem, ${pref}, ${round(hi)}rem)`;\n }\n }\n return { name, value, max, offset: i - baselineIdx };\n });\n};\n\n// ── typography ─────────────────────────────────────────────────────────────────\ninterface TypographyRole {\n family?: string;\n [key: string]: string | number | undefined;\n}\nconst TYPO_KEYMAP: Record<string, [string, string]> = {\n family: ['font-family', 'ff'],\n size: ['font-size', 'fs'],\n weight: ['font-weight', 'fw'],\n style: ['font-style', 'fst'],\n 'line-height': ['line-height', 'lh'],\n tracking: ['letter-spacing', 'ls'],\n 'text-decoration': ['text-decoration', 'td'],\n 'text-transform': ['text-transform', 'tt'],\n 'text-wrap': ['text-wrap', 'tw'],\n color: ['color', 'color'],\n};\n/**\n * Wrong spellings worth naming explicitly, because each is a plausible reading of\n * the key it isn't. `transform`/`decoration` were documented in the schema for a\n * while and shipped title-case navigation to production; `letter-spacing` and\n * `font-*` are the natural guesses for keys we chose to shorten.\n */\nconst ALSO_MEANT: Record<string, string> = {\n transform: 'text-transform',\n decoration: 'text-decoration',\n 'letter-spacing': 'tracking',\n wrap: 'text-wrap',\n 'font-family': 'family',\n 'font-size': 'size',\n 'font-weight': 'weight',\n 'font-style': 'style',\n lineHeight: 'line-height',\n};\nconst TYPO_IDENTITY: Record<string, string> = {\n 'font-style': 'normal',\n 'letter-spacing': 'normal',\n 'text-decoration': 'none',\n 'text-transform': 'none',\n 'text-wrap': 'wrap',\n};\n\n// ── animation state defaults ─────────────────────────────────────────────────\nconst STATE_DEFAULT: Record<string, string> = {\n opacity: '1',\n 'translate-x': '0',\n 'translate-y': '0',\n 'scale-x': '1',\n 'scale-y': '1',\n rotate: '0deg',\n blur: '0px',\n shadow: '0 0 0 transparent',\n brightness: '1',\n grayscale: '0',\n contrast: '1',\n saturate: '1',\n sepia: '0',\n 'hue-rotate': '0deg',\n clip: 'none',\n // The layout stage. `.transition` only declares `height` inside\n // `@supports (interpolate-size: allow-keywords)`, since `0 → auto` is not\n // interpolable without it — but the default belongs here either way, so the\n // flip resolves to the element's natural height rather than to nothing.\n height: 'auto',\n};\n\ninterface Pattern {\n group?: string;\n overrides?: Record<string, string>;\n element?: string;\n class?: string;\n fill?: boolean;\n default_role?: string;\n base?: Record<string, string>;\n states?: Record<string, Record<string, unknown>>;\n roles?: string[];\n}\n\nconst id = (key: string) => createHash('sha256').update(key).digest('hex').slice(0, 6);\n\n/**\n * The in-memory output of building a design system. String fields are CSS/JSON\n * ready to write; the generated CSS partials feed the css/bricks bundler.\n */\ninterface Built {\n generated: Record<string, string>; // filename (under generated/) -> css\n bricksColorsNamed: string;\n bricksColorsSemantic: string;\n bricksVariables: string;\n tokensJson: string;\n designManifest: string;\n tailwind: string;\n designMd: string;\n // captured for the tailwind bundler\n twTypeTokensCss: string;\n twPatternTokensCss: string;\n patternsCss: string;\n}\n\n// Exported for tests only — deliberately NOT re-exported from index.ts, so the\n// package's public API stays `generate` / `generateDocs` / `validate`.\nexport interface BuildOptions {\n /**\n * Also flip to dark when the OS asks and no explicit choice has been made —\n * `@media (prefers-color-scheme: dark)`.\n *\n * A build flag rather than a `DesignSystem` field: it describes what a *site*\n * wants, not what the system defines, so it comes from the site config's\n * `designSystem.defaultColorScheme` and `generate()` stays keyed to a `DesignSystem`.\n * Off by default, because turning it on flips a site dark for dark-OS users.\n */\n systemColorScheme?: boolean;\n}\n\nexport function build(\n ds: DesignSystem,\n format: Format,\n assetsDir: string,\n buildOpts: BuildOptions = {},\n): Built {\n const BRICKS = format === 'bricks';\n // Every hue expands to its 11-step numeric OKLCH scale; every role resolves\n // to functional tokens over its hue. Dark mode is the automatic flip.\n const expandedPalette = expandPalette(ds.colors.palette as Record<string, unknown>);\n const roleMap = ds.colors.roles as Record<string, RoleSpec>;\n const scaleRoles: FunctionalRole[] = [];\n for (const [role, spec] of Object.entries(roleMap)) {\n const hueName = roleHue(spec);\n const hue = expandedPalette[hueName];\n if (hue == null) throw new Error(`role \"${role}\" references unknown palette hue \"${hueName}\"`);\n scaleRoles.push(functionalRole(role, hueName, hue, roleKind(spec)));\n }\n const surfaceRole = scaleRoles.find((r) => r.role === 'surface');\n // The focus ring is role-less by default, so it needs one nominated source.\n // `ui-primary` is the interaction hue — a ring in the brand colour would drift\n // away from the buttons and links it appears on.\n const focusRole = scaleRoles.find((r) => r.role === 'ui-primary') ?? scaleRoles[0];\n\n // A pinned brand colour that sits off the shared lightness ladder is legal —\n // the author asked for that exact colour — but past ~0.03 L the hue reads\n // visibly heavier or lighter than its siblings at that step, so say so.\n for (const w of ladderWarnings(expandedPalette)) console.warn(`[vitops] ${w}`);\n\n // A pinned colour far enough off the ladder can leave the ramp non-monotonic —\n // some step lighter than the one above it. That is an error, not a warning:\n // `snap`, the mode-stable solid family and the dark tables all assume the\n // order, so an inverted ramp runs hover states backwards. Same reasoning as the\n // contrast contract below — this is exactly the drift the fixed ladder exists\n // to eliminate, and it is always author-caused, so it is always actionable.\n {\n const errors = monotonicityErrors(expandedPalette);\n if (errors.length) throw new Error(errors.join('\\n'));\n }\n\n // The contrast contract runs at BUILD time, not only in tests: a consumer\n // editing their own palette has no test suite, and an illegible pairing that\n // ships is far more expensive than a build that stops. Chromatic roles are\n // checked against the surface planes they actually sit on, since coloured text\n // appears over the page far more often than over its own tint.\n {\n const numericOf = (hueName: string) => expandedPalette[hueName]?.numeric ?? {};\n const resolve = (val: string): string => {\n const m = /^var\\(--color-([a-z0-9-]+)-(\\d+)\\)$/.exec(val);\n return m ? (numericOf(m[1] as string)[m[2] as never] ?? val) : val;\n };\n const planeKeys = ['bg', 'bg-muted', 'bg-x-muted'] as const;\n const surfaceBg = surfaceRole\n ? {\n light: planeKeys.flatMap((k) =>\n surfaceRole.light[k] ? [resolve(surfaceRole.light[k] as string)] : [],\n ),\n dark: planeKeys.flatMap((k) =>\n surfaceRole.dark[k] ? [resolve(surfaceRole.dark[k] as string)] : [],\n ),\n }\n : undefined;\n const failures = scaleRoles.flatMap((fr) => checkContrast(fr, numericOf, surfaceBg));\n if (failures.length)\n throw new Error(\n `colour contrast contract failed (${failures.length} pairing${\n failures.length === 1 ? '' : 's'\n }):\\n ${failures.join('\\n ')}`,\n );\n }\n const patterns = ds.patterns;\n const shadows = ds.shadows;\n const typography = ds.typography;\n const UTILITIES = (ds.colors.utilities ?? ['bg', 'text', 'icon', 'border']).filter(\n (u) => u in UTILITY_PROPS,\n );\n\n const generated: Record<string, string> = {};\n\n /**\n * The two background utilities that aren't derived from the palette, so\n * neither the generated scale nor Bricks' own palette import produces them.\n *\n * They exist to undo a pattern's fill — `class=\"card bg-transparent\"` for a\n * flat, border-only card. Tailwind ships both as built-ins, so the tailwind\n * format deliberately emits neither and defers, exactly as it does for the\n * `TW_CLASH` names.\n */\n const NON_PALETTE_BG =\n `/* Undo a pattern's fill (Tailwind provides these natively in that format). */\\n` +\n `.bg-transparent { background-color: transparent; }\\n` +\n `.bg-inherit { background-color: inherit; }\\n`;\n\n // ── color.css ──────────────────────────────────────────────────────────────\n if (BRICKS) {\n generated['color.css'] =\n '/* Colours provided by Bricks (palette import generates tokens + utilities). */\\n' +\n NON_PALETTE_BG;\n } else {\n let css = `/* GENERATED from design-system.json — do not edit by hand. */\\n:root {\\n`;\n css += ` color-scheme: light;\\n`;\n css += ` /* Hue scales (numeric steps, 50 = tinted near-white … 950 = tinted near-black) */\\n`;\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const [n, hex] of Object.entries(hue.numeric))\n css += ` --color-${name}-${n}: ${hex};\\n`;\n css += `\\n /* Role tokens (the public API) */\\n`;\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.light))\n css += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n if (focusRole) {\n css += `\\n /* Focus ring — a boundary, so it takes the solid tone, not a border tint. */\\n`;\n css += ` --color-border-focus: ${focusRole.light['bg-solid']};\\n`;\n }\n if (surfaceRole) {\n css += `\\n /* Translucent surface + scrim */\\n`;\n css += ` --surface-glass: color-mix(in oklch, var(--color-bg-surface) 72%, transparent);\\n`;\n css += ` --overlay: color-mix(in oklch, var(--color-${surfaceRole.hue}-950) 45%, transparent);\\n`;\n }\n css += `}\\n\\n`;\n // Dark appearance: the automatic functional flip (solid stays mode-stable).\n {\n let fb = '';\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.dark))\n if (fr.light[t] !== val) fb += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n if (surfaceRole)\n fb += ` --overlay: color-mix(in oklch, var(--color-${surfaceRole.hue}-950) 60%, transparent);\\n`;\n if (fb) {\n css += `/* Functional role tokens (dark) */\\n`;\n css += `${DARK_SEL} {\\n color-scheme: dark;\\n${fb}}\\n\\n`;\n // The same delta again, for \"no explicit choice + a dark OS\". Opt-in,\n // because switching it on flips a site dark for dark-OS users.\n //\n // This is what makes <color-scheme-toggle>'s \"System\" position mean\n // anything: System *removes* data-theme, so with only the block above it\n // fell through to light on every machine. It also gives a no-JS page the\n // OS appearance, which the toggle alone never could.\n //\n // Yes, `fb` is emitted twice. It is a delta — only the tokens whose dark\n // value differs, and the raw hue ramps never re-point — and two identical\n // runs of text compress to almost nothing, so the cost is far below what\n // a second full colour layer would suggest.\n if (buildOpts.systemColorScheme)\n css +=\n `/* Functional role tokens (dark) — OS preference, no explicit choice */\\n` +\n `@media (prefers-color-scheme: dark) {\\n` +\n ` ${SYSTEM_DARK_SEL} {\\n color-scheme: dark;\\n${fb.replace(/^ {2}/gm, ' ')} }\\n}\\n\\n`;\n }\n }\n // Raw hue steps, then the role set. One axis means every class here is\n // emitted exactly once by construction — no precedence rule, and no reliance\n // on the minifier dropping a shadowed rule.\n css += `/* Colour utilities — ${UTILITIES.join(', ')} */\\n`;\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const n of Object.keys(hue.numeric))\n css +=\n UTILITIES.map(\n (cls) => `.${cls}-${name}-${n} { ${UTILITY_PROPS[cls]}: var(--color-${name}-${n}); }`,\n ).join('\\n') + '\\n';\n css += `\\n/* Role utilities (the public API) */\\n`;\n css += `${colorUtilityRules(roleColorUtilities(scaleRoles, UTILITIES))}\\n`;\n if (surfaceRole)\n css += `.glass { background-color: var(--surface-glass); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }\\n`;\n css += NON_PALETTE_BG;\n generated['color.css'] = css;\n }\n\n // ── shadows.css ──────────────────────────────────────────────────────────────\n {\n const entries = Object.entries(shadows ?? {});\n let sh = `/* GENERATED drop-shadow tokens + utilities — do not edit by hand. */\\n`;\n if (entries.length) {\n sh += `:root {\\n`;\n for (const [name, value] of entries) sh += ` --shadow-${name}: ${value};\\n`;\n sh += `}\\n\\n`;\n for (const [name] of entries)\n sh += `.drop-shadow-${name} { filter: drop-shadow(var(--shadow-${name})); }\\n`;\n }\n generated['shadows.css'] = sh;\n }\n\n // ── scales ───────────────────────────────────────────────────────────────────\n const typeSteps = ds.typeScale ? buildScale(ds.typeScale as ScaleConfig) : [];\n const spaceSteps = ds.spaceScale ? buildScale(ds.spaceScale as ScaleConfig) : [];\n const textMax: Record<string, string> = Object.fromEntries(\n typeSteps.map((s) => [`text-${s.name}`, s.max]),\n );\n\n const typographyFamilies = typography?.families ?? {};\n\n // The recognised key set is closed (TYPO_KEYMAP), and an unrecognised key is\n // dropped rather than emitted — so a typo, or one of the plausible-but-wrong\n // short forms (`transform` for `text-transform`, `decoration` for\n // `text-decoration`), produces a role that looks configured and renders\n // unstyled. That is invisible in the output and survives review, so say it here\n // rather than leaving it to be noticed on a live page.\n {\n const known = new Set(Object.keys(TYPO_KEYMAP));\n for (const [role, spec] of Object.entries(typography?.roles ?? {}))\n for (const key of Object.keys(spec as TypographyRole)) {\n if (known.has(key)) continue;\n const near = ALSO_MEANT[key];\n console.warn(\n `[vitops] typography.roles.${role}: unknown key \"${key}\" — ignored` +\n (near ? `. Did you mean \"${near}\"?` : `. Recognised: ${[...known].join(', ')}.`),\n );\n }\n }\n const withScaleFallback = (v: string) =>\n v.replace(/var\\(\\s*(--text-[\\w-]+)\\s*\\)/g, (m, name) =>\n textMax[name.slice(2)] ? `var(${name}, ${textMax[name.slice(2)]})` : m,\n );\n const roleDecls = (role: string, spec: TypographyRole): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [key, [prop, sfx]] of Object.entries(TYPO_KEYMAP)) {\n const identity = TYPO_IDENTITY[prop];\n if (spec[key] == null && identity == null) continue;\n const raw =\n spec[key] == null\n ? (identity as string)\n : key === 'family'\n ? (typographyFamilies[spec.family as string] ?? String(spec.family))\n : key === 'size'\n ? withScaleFallback(String(spec[key]))\n : String(spec[key]);\n out[prop] = `var(--${role}-${sfx}, ${raw})`;\n }\n return out;\n };\n\n // ── type-tokens.css ──────────────────────────────────────────────────────────\n let twTypeTokensCss = '';\n if (BRICKS) {\n generated['type-tokens.css'] =\n '/* Fonts + type/space scales provided by Bricks (Font + Variables managers). */\\n';\n } else {\n const root: Record<string, string> = {};\n for (const [name, stack] of Object.entries(ds.fonts ?? {})) root[`--font-${name}`] = stack;\n for (const s of typeSteps) root[`--text-${s.name}`] = s.value;\n for (const s of spaceSteps) root[`--space-${s.name}`] = s.value;\n const css =\n `/* GENERATED font families + fluid type/space scales — do not edit by hand.\\n` +\n ` --font-* are STACKS ONLY; no @font-face is emitted here. Load webfonts with\\n` +\n ` Astro's fonts: config and point the token at the family's cssVariable. */\\n` +\n `:root {\\n${decls(root)}\\n}\\n`;\n twTypeTokensCss = css;\n generated['type-tokens.css'] = css;\n }\n\n // ── spacing.css (gap utilities) ──────────────────────────────────────────────\n // Emitted for css AND bricks: the `--space-*` tokens come from this file in the\n // css format and from Bricks' Variables import in the bricks format, but the\n // class names are ours either way — Bricks generates utility classes only for\n // the colour palette.\n {\n const gaps = gapUtilities(spaceSteps);\n let sp = `/* GENERATED gap utilities — do not edit by hand. */\\n`;\n if (gaps.length) {\n for (const { cls, prop, value } of gaps) sp += `.${cls} { ${prop}: ${value}; }\\n`;\n for (const [bp, width] of BREAKPOINTS) {\n sp += `\\n@container (min-width: ${width}) {\\n`;\n for (const { cls, prop, value } of gaps) sp += ` .${bp}-${cls} { ${prop}: ${value}; }\\n`;\n sp += `}\\n`;\n }\n }\n generated['spacing.css'] = sp;\n }\n\n // ── tokens.css (pattern token cascade) ───────────────────────────────────────\n let twPatternTokensCss = '';\n {\n const tDefaults = patterns?.defaults ?? {};\n const tRadii = patterns?.radii ?? {};\n const tGroups = patterns?.groups ?? {};\n const tZ = patterns?.z ?? {};\n const tItems = (patterns?.items ?? {}) as Record<string, Pattern>;\n const root: Record<string, string> = {};\n for (const [prop, val] of Object.entries(tDefaults)) root[`--${prop}-default`] = val;\n if (!BRICKS) for (const [name, val] of Object.entries(tRadii)) root[`--br-${name}`] = val;\n for (const [group, props] of Object.entries(tGroups))\n for (const [prop, val] of Object.entries(props)) root[`--${prop}-${group}`] = val;\n for (const [name, n] of Object.entries(tZ)) root[`--z-tier-${name}`] = String(n);\n const aliases: Record<string, string> = {};\n for (const [name, p] of Object.entries(tItems)) {\n if (!p.group) continue;\n for (const prop of Object.keys(tGroups[p.group] ?? {}))\n aliases[`--${prop}-${name}-group`] = `var(--${prop}-${p.group})`;\n for (const [prop, val] of Object.entries(p.overrides ?? {}))\n aliases[`--${prop}-${name}-group`] = val;\n }\n let tok = `/* GENERATED pattern token cascade — do not edit by hand. */\\n:root {\\n`;\n tok += decls(root) + '\\n';\n if (Object.keys(aliases).length) tok += '\\n' + decls(aliases) + '\\n';\n tok += `}\\n`;\n twPatternTokensCss = tok;\n generated['tokens.css'] = tok;\n }\n\n // ── typography.css (.font-* roles) ───────────────────────────────────────────\n {\n const roles = (typography?.roles ?? {}) as Record<string, TypographyRole>;\n const headings = typography?.headings ?? {};\n let typo = `/* GENERATED typography roles — do not edit by hand. */\\n`;\n for (const [role, spec] of Object.entries(roles))\n typo += `.font-${role} {\\n${decls(roleDecls(role, spec))}\\n}\\n`;\n for (const [tag, role] of Object.entries(headings))\n if (roles[role]) typo += `${tag} {\\n${decls(roleDecls(role, roles[role]))}\\n}\\n`;\n generated['typography.css'] = typo;\n }\n\n // ── patterns.css (component interaction patterns) ────────────────────────────\n // `sel` is a *builder* taking the state's pseudo, not a finished selector, and\n // that indirection is load-bearing rather than stylistic: an element pattern\n // has to place the pseudo INSIDE its `:where()`, because `:where()` zeroes the\n // element but a pseudo appended outside it still counts. `:where(a, .link):hover`\n // is 0-1-0 — the same weight as `.cta-brand-primary` — so the link pattern's\n // hover colour tied with every `<a class=\"cta\">` and won on source order,\n // turning a filled CTA's text dark mid-hover. `:where(a:hover, .link:hover)` is\n // a true 0-0-0 and loses to any explicit class, which is what the base rule\n // already promised. It returns a list because an element pattern emits both\n // `:where(el, .cls).role` and `.cls-role`.\n const stateRules = (\n sel: (pseudo: string) => string[],\n role: string | null,\n states: Record<string, Record<string, unknown>>,\n colorProp: 'background-color' | 'color' = 'background-color',\n ) => {\n let out = '';\n for (const [state, spec] of Object.entries(states)) {\n const body: string[] = [];\n // `step` intensifies the pattern's colour: fills swap solid → solid-bold;\n // text swaps the bold emphasis stop → x-bold.\n if (typeof spec.step === 'number' && role) {\n const stateVar =\n colorProp === 'background-color'\n ? `var(--color-bg-${role}-${spec.step >= 1 ? 'solid-bold' : 'solid'})`\n : spec.step >= 1\n ? `var(--color-text-${role}-bold)`\n : `var(--color-text-${role})`;\n body.push(`${colorProp}: ${stateVar};`);\n }\n if (typeof spec.scale === 'number') body.push(`scale: ${spec.scale};`);\n if (typeof spec.lift === 'string') body.push(`translate: 0 calc(-1 * ${spec.lift});`);\n if (typeof spec.shadow === 'string' && shadows?.[spec.shadow])\n body.push(`filter: drop-shadow(var(--shadow-${spec.shadow}));`);\n else if (spec.shadow === true)\n body.push(`box-shadow: var(--lift-shadow, 0 8px 20px -6px rgb(0 0 0 / 0.25));`);\n if (spec.ring === true) {\n // A focus ring has to be *seen*, so it uses the solid tone rather than a\n // decorative border tint. `--color-border-focus` is the role-less\n // default, emitted once from ui-primary and contrast-checked as a\n // non-text boundary.\n const ringColor = role ? `var(--color-bg-${role}-solid)` : `var(--color-border-focus)`;\n body.push(`outline: none;`, `box-shadow: 0 0 0 3px ${ringColor};`);\n }\n if (spec.css && typeof spec.css === 'object')\n for (const [k, v] of Object.entries(spec.css as Record<string, string>))\n body.push(`${k}: ${v};`);\n if (!body.length) continue;\n const pseudo =\n state === 'hover'\n ? ':hover'\n : state === 'active'\n ? ':active'\n : state === 'focus-visible'\n ? ':focus-visible'\n : `:${state}`;\n const rule = `${sel(pseudo).join(',\\n')} {\\n ${body.join('\\n ')}\\n}\\n`;\n out += state === 'hover' ? `@media (hover: hover) {\\n${rule}}\\n` : rule;\n }\n return out;\n };\n\n let pat = `/* GENERATED component patterns — do not edit by hand. */\\n`;\n pat += `/* Interaction transitions for patterned elements (independent props compose). */\\n`;\n for (const [pname, p] of Object.entries((patterns?.items ?? {}) as Record<string, Pattern>)) {\n if (!p.base) continue;\n const states = p.states ?? {};\n // `class` defaults to the pattern key only for class-only patterns, so an\n // `element`-only entry never sprouts a surprise class.\n const cls = p.class ?? (p.element ? undefined : pname);\n // Element patterns style at zero specificity (`:where(…)`) so any explicit\n // class — a louder pattern, or a component's own BEM rule — wins without\n // !important. Class-only patterns stay unwrapped at 0-1-0, or they'd lose to\n // every utility. With both, the element and the class share one rule, which\n // is what lets `.btn` / `.link` be applied to any tag.\n //\n // `pseudo` goes inside the `:where()` so a state rule keeps that promise —\n // see the note on `stateRules`. `extra` (a role class) stays outside it,\n // since the variant is meant to carry a class's weight.\n const elementSel = (extra = '', pseudo = '') =>\n `:where(${[p.element, cls && `.${cls}`]\n .filter(Boolean)\n .map((s) => `${s}${pseudo}`)\n .join(', ')})${extra}`;\n const defaultSel = p.element ? elementSel() : `.${cls}`;\n const defaultSelFor = (pseudo: string) =>\n p.element ? [elementSel('', pseudo)] : [`.${cls}${pseudo}`];\n const defaultRole = p.default_role ?? null;\n const base = { ...p.base };\n // Explicit `fill` wins; otherwise infer, keeping the historical name-based\n // special cases so existing consumer configs don't shift behaviour.\n const fills =\n p.fill ??\n (pname === 'button' ||\n pname === 'badge' ||\n base['background-color'] != null ||\n base['background'] != null);\n const colorProp: 'background-color' | 'color' = fills ? 'background-color' : 'color';\n pat += `${defaultSel} {\\n`;\n const hasStates = Object.keys(states).length > 0;\n if (hasStates) {\n pat += ` transition-property: translate, scale, rotate, filter, box-shadow, background-color, color;\\n`;\n pat += ` transition-duration: var(--interact-duration, 200ms);\\n`;\n pat += ` transition-timing-function: var(--interact-easing, ease);\\n`;\n pat += ` translate: 0 0; scale: 1; rotate: 0deg;\\n`;\n }\n if (defaultRole && fills && base['background-color'] == null && base['background'] == null)\n base['background-color'] = `var(--color-bg-${defaultRole}-solid)`;\n const wrappedBase: Record<string, string> = {};\n for (const [prop, val] of Object.entries(base)) {\n const sfx = BASE_HOOK[prop];\n wrappedBase[prop] = sfx ? `var(--${sfx}-${pname}, ${val})` : String(val);\n }\n pat += decls(wrappedBase) + '\\n}\\n';\n pat += stateRules(defaultSelFor, defaultRole, states, colorProp);\n for (const role of p.roles ?? []) {\n // Element patterns take the role as a bare class (`<button class=\"danger\">`)\n // AND as the `<pattern>-<role>` form that class patterns use, so the same\n // variant reaches a non-element host (`<a class=\"btn btn-danger\">`). Both\n // land at 0-1-0 — the element half stays inside :where() so a role variant\n // can't outrank a plain class the way `button.danger` (0-1-1) used to.\n const variantSelsFor = (pseudo: string) =>\n p.element\n ? [elementSel(`.${role}`, pseudo), ...(cls ? [`.${cls}-${role}${pseudo}`] : [])]\n : [`.${cls}-${role}${pseudo}`];\n const variantSels = variantSelsFor('');\n // Fills sit on the role's solid and pair with the foreground computed\n // against it; text variants use the role's text token, which is the one\n // guaranteed legible over a surface in both appearances.\n const variantColorDecl = fills\n ? `background-color: var(--color-bg-${role}-solid); color: var(--color-text-on-${role})`\n : `color: var(--color-text-${role})`;\n pat += `${variantSels.join(',\\n')} { ${variantColorDecl}; }\\n`;\n pat += stateRules(variantSelsFor, role, states, colorProp);\n }\n pat += '\\n';\n }\n generated['patterns.css'] = pat;\n\n // ── animation-effects.css ────────────────────────────────────────────────────\n {\n const anim = ds.animations ?? {};\n const asStr = (v: string | number) => String(v);\n const block = (sel: string, d: Record<string, string>) => `.${sel} {\\n${decls(d)}\\n}\\n`;\n let out = `/* GENERATED animation effects + journeys — do not edit by hand. */\\n`;\n for (const [name, e] of Object.entries(anim.effects ?? {})) {\n const d: Record<string, string> = { '--_anim': e.kf };\n for (const [k, v] of Object.entries(e.css ?? {})) d[k] = asStr(v);\n for (const [k, v] of Object.entries(e.vars ?? {})) d[`--${k}`] = asStr(v);\n out += block(name, d);\n }\n const base = anim.journeys?.base ?? {};\n for (const parts of anim.journeys?.compose ?? []) {\n const d: Record<string, string> = {\n '--_anim': parts.map((p) => `${p}-journey`).join(', '),\n // A journey is entry → hold → exit (keyframes at 0%/100% hidden,\n // 25%–75% held), so it needs the long range that a one-shot entrance\n // doesn't. It starts on the same pivot as `.animate-view` — the\n // element's midpoint 15% into the viewport, which is `entry 50%` plus\n // 10vh (see the note on .animate-view in core's animation.css) — and\n // runs to the end of the exit phase, so the hold occupies the middle of\n // the crossing rather than the bottom edge of the screen.\n //\n // The END is spelled `exit 100%` rather than the equivalent bare `exit`,\n // because lightningcss misparses the shorthand: an omitted offset on the\n // END defaults to 0% there instead of the spec's 100%, so `entry exit`\n // bundled as `entry exit 0%` and every journey snapped back to its hidden\n // `from` state as the element reached the top of the viewport. Guarded by\n // animation-effects.test.ts, which asserts on the BUNDLED css.\n 'animation-range': 'entry calc(50% + 10vh) exit 100%',\n };\n for (const p of parts)\n for (const [k, v] of Object.entries(base[p] ?? {})) d[`--${k}`] = asStr(v);\n out += block(`${parts.join('-')}-journey`, d);\n }\n // Each state matches the element itself OR its direct parent, mirroring the\n // precedent animation.css already sets for the trigger driver\n // (`:is(.is-active, [data-active]) > .animate-trigger`). The parent form is\n // load-bearing, not a convenience: a `hover-reveal-*` element rests at\n // `clip-path: inset(0 100% 0 0)`, and clip-path clips HIT-TESTING as well as\n // painting — so with `:hover` alone the element has zero hittable area and\n // can never receive the hover that would reveal it. Same specificity (0,2,0)\n // as the self form, so nothing reorders.\n const STATES: [string, (s: string) => string][] = [\n ['hover', (s) => `.${s}:hover, :hover > .${s}`],\n ['focus', (s) => `.${s}:focus-visible, :focus-within > .${s}`],\n ['active', (s) => `.${s}.is-active, .${s}[data-active]`],\n // The top layer's own state. A popover/dialog rests CLOSED at the effect's\n // `from` values and flips to `to` when it opens — the same shape as hover,\n // so it costs one row here rather than a bespoke driver, and every effect\n // gains `open-<fx>` in all three formats for free. `:popover-open` covers\n // the Popover API; `[open]` covers `<dialog open>` (and `<details open>`,\n // which is a legitimate use of the same flip).\n //\n // The MECHANISM a top-layer element additionally needs — `display`/`overlay`\n // in transition-property with `allow-discrete`, plus the `@starting-style`\n // that makes the entry run at all — is not per-effect, so it lives once in\n // animation.css rather than being multiplied across every effect here.\n ['open', (s) => `.${s}:popover-open, .${s}[open]`],\n ];\n out += `\\n/* State-flip variants — compose with .transition (hover-/focus-/active-<fx>). */\\n`;\n // Every keyframe family gets state variants, `layout` included: `.transition`\n // covers `height` inside `@supports (interpolate-size: allow-keywords)`, and\n // the `layout` keyframe depends on exactly the same feature — so excluding\n // layout here bought no portability, it only made `hover-size-grow` a class\n // that resolved to nothing while the docs advertised it.\n for (const [name, e] of Object.entries(anim.effects ?? {})) {\n const props: Record<string, { from?: string; to?: string }> = {};\n for (const [k, v] of Object.entries(e.vars ?? {})) {\n const m = /^(.*)-(from|to)$/.exec(k);\n if (m) (props[m[1] as string] ??= {})[m[2] as 'from' | 'to'] = asStr(v);\n }\n // The effect's own `css` block travels with the variant too — `size-grow`\n // declares `overflow: clip`, without which a collapsed (0-height) box\n // spills its content instead of hiding it.\n const rest: Record<string, string> = {};\n for (const [k, v] of Object.entries(e.css ?? {})) rest[k] = asStr(v);\n for (const [p, ft] of Object.entries(props)) {\n if (ft.from != null && ft.from !== STATE_DEFAULT[p]) rest[`--${p}-from`] = ft.from;\n if (ft.to != null && ft.to !== STATE_DEFAULT[p]) rest[`--${p}-to`] = ft.to;\n }\n const flip: Record<string, string> = Object.fromEntries(\n Object.keys(props).map((p) => [`--t-${p}`, `var(--${p}-to, ${STATE_DEFAULT[p]})`]),\n );\n if (Object.keys(rest).length)\n out += `${STATES.map(([s]) => `.${s}-${name}`).join(', ')} {\\n${decls(rest)}\\n}\\n`;\n for (const [s, sel] of STATES) out += `${sel(`${s}-${name}`)} {\\n${decls(flip)}\\n}\\n`;\n }\n generated['animation-effects.css'] = out;\n }\n\n // ── Bricks palettes ──────────────────────────────────────────────────────────\n // Named = the hue scales (numeric steps); Semantic = the functional role\n // tokens with their automatic light/dark pairing.\n const namedColors: unknown[] = [];\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const [n, hex] of Object.entries(hue.numeric)) {\n const token = `${name}-${n}`;\n namedColors.push({\n raw: `var(--color-${token})`,\n light: hex,\n id: id(`named:${token}`),\n utilityClasses: UTILITIES,\n });\n }\n const semanticColors: unknown[] = [];\n for (const fr of scaleRoles)\n for (const [t, light] of Object.entries(fr.light)) {\n const dark = fr.dark[t] as string;\n semanticColors.push({\n raw: `var(${tokenVar(fr.role, t)})`,\n light,\n darkModeEnabled: light !== dark,\n dark,\n id: id(`semantic:${fr.role}-${t}`),\n utilityClasses: UTILITIES,\n });\n }\n const bricksColorsNamed = JSON.stringify(\n { id: id('palette:named'), name: 'Named', colors: namedColors },\n null,\n 2,\n );\n const bricksColorsSemantic = JSON.stringify(\n { id: id('palette:semantic'), name: 'Semantic', colors: semanticColors },\n null,\n 2,\n );\n\n // ── Bricks Global Variables (fonts + scales) ─────────────────────────────────\n const bricksVariables = (() => {\n type BrxScale = { scale: number; scaleName: string };\n type BrxVar = { id: string; name: string; value: string; category?: string; scale?: BrxScale };\n type BrxCat = { id: string; name: string; scale: Record<string, unknown>; utilityClasses: [] };\n const scaleMeta = (scope: string, prefix: string, s: ScaleConfig, names: string[]) => {\n const px = Math.round(rem(s.base) * 16);\n const lo = s.fluid?.minRatio ?? s.ratio;\n return {\n scaleScope: scope,\n scaleType: 'tshirt',\n scaleNames: names,\n prefix,\n minFontSize: px,\n minScaleRatio: lo,\n minScaleRatioSelect: lo,\n maxFontSize: px,\n maxScaleRatio: s.ratio,\n maxScaleRatioSelect: s.ratio,\n baseline: s.baseline ?? names[Math.floor((names.length - 1) / 2)],\n };\n };\n const categories: BrxCat[] = [];\n const variables: BrxVar[] = [];\n const addScale = (\n label: string,\n scope: string,\n prefix: string,\n cfg: ScaleConfig | undefined,\n steps: ScaleStep[],\n ) => {\n if (!cfg || !steps.length) return;\n const names = steps.map((s) => s.name);\n const catId = id(`varcat:${scope}`);\n categories.push({\n id: catId,\n name: label,\n scale: scaleMeta(scope, prefix, cfg, names),\n utilityClasses: [],\n });\n for (const st of steps)\n variables.push({\n id: id(`var:${prefix}${st.name}`),\n name: `${prefix}${st.name}`,\n value: st.value,\n category: catId,\n scale: { scale: st.offset, scaleName: st.name },\n });\n };\n addScale('Typography', 'typography', 'text-', ds.typeScale as ScaleConfig, typeSteps);\n addScale('Spacing', 'spacing', 'space-', ds.spaceScale as ScaleConfig, spaceSteps);\n for (const [name, stack] of Object.entries(ds.fonts ?? {}))\n variables.push({ id: id(`var:font-${name}`), name: `font-${name}`, value: stack });\n for (const [name, val] of Object.entries(ds.patterns?.radii ?? {}))\n variables.push({ id: id(`var:br-${name}`), name: `br-${name}`, value: val });\n return JSON.stringify({ variables, categories }, null, 2);\n })();\n\n // ── tokens.json (trimmed token export for programmatic consumers) ────────────\n const numericPalette = Object.fromEntries(\n Object.entries(expandedPalette).map(([k, v]) => [k, v.numeric]),\n );\n const tokensJson = JSON.stringify(\n {\n colors: {\n palette: numericPalette,\n roles: roleMap,\n functional: Object.fromEntries(\n scaleRoles.map((fr) => [fr.role, { light: fr.light, dark: fr.dark }]),\n ),\n },\n fonts: ds.fonts ?? {},\n text: Object.fromEntries(typeSteps.map((s) => [s.name, s.value])),\n spacing: Object.fromEntries(spaceSteps.map((s) => [s.name, s.value])),\n shadows: shadows ?? {},\n radii: ds.patterns?.radii ?? {},\n },\n null,\n 2,\n );\n\n // ── design-manifest.json (live-editor manifest; css format) ──────────────────\n const designManifest = (() => {\n const reverseIndex: Record<string, string> = {};\n // A numeric step maps back to that step's `anchors` entry, NOT to the hue's\n // `seed`: the seed regenerates the whole ramp (and every step would collapse\n // to one path, so editing two steps of a hue would silently keep only one),\n // whereas `anchors.<step>` is precisely the per-step override (see schema.ts).\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const n of Object.keys(hue.numeric))\n reverseIndex[`--color-${name}-${n}`] = `colors.palette.${name}.anchors.${n}`;\n // `kind` travels with the role so the editor picks the right `roleTokens`\n // variant on a remap — it used to infer that from `role === 'surface'`, which\n // silently did the wrong thing for any other surface-kind role.\n const colorRoles = Object.entries(roleMap).map(([name, spec]) => ({\n name,\n ramp: roleHue(spec),\n kind: roleKind(spec),\n }));\n // Per-hue token sets, so a client (the live editor) can re-point a role at\n // another hue. It can't derive these itself: `text-on` is a computed contrast\n // literal, not a var() ref. One variant per role KIND, because the two kinds\n // emit different token sets — a chromatic role has no bare `bg`, a surface\n // role has no solid tints.\n //\n // Keys are token keys (`bg`, `text-on`, `border-bold`, …) — the same ones\n // `tokenVar()` turns into `--color-<target>-<role>[-<variant>]`.\n const roleTokens = Object.fromEntries(\n Object.entries(expandedPalette).map(([hueName, hue]) => {\n const chromatic = functionalRole('_', hueName, hue, 'chromatic');\n const surface = functionalRole('_', hueName, hue, 'surface');\n return [\n hueName,\n {\n chromatic: { light: chromatic.light, dark: chromatic.dark },\n surface: { light: surface.light, dark: surface.dark },\n },\n ];\n }),\n );\n const typoRoles = (typography?.roles ?? {}) as Record<string, TypographyRole>;\n const hooks: Record<string, { prop: string; key: string }> = {};\n for (const [key, [prop, sfx]] of Object.entries(TYPO_KEYMAP)) hooks[sfx] = { prop, key };\n // Index EVERY hook for every role, not just the ones the role already\n // declares. The editor builds its control set from `typography.hooks` (all\n // of TYPO_KEYMAP), so a role that omits `tracking` still gets a `--<role>-ls`\n // control; without an entry here that edit previews live and is then dropped\n // as \"skipped\" on save. The path is a valid place to write whether or not it\n // exists yet — `roles` is an open record and the patch deep-merges.\n for (const role of Object.keys(typoRoles))\n for (const [key, [, sfx]] of Object.entries(TYPO_KEYMAP))\n reverseIndex[`--${role}-${sfx}`] = `typography.roles.${role}.${key}`;\n const pDefaults = patterns?.defaults ?? {};\n const pRadii = patterns?.radii ?? {};\n const pGroups = patterns?.groups ?? {};\n const pItems = (patterns?.items ?? {}) as Record<string, Pattern>;\n for (const prop of Object.keys(pDefaults))\n reverseIndex[`--${prop}-default`] = `patterns.defaults.${prop}`;\n for (const [group, props] of Object.entries(pGroups))\n for (const prop of Object.keys(props))\n reverseIndex[`--${prop}-${group}`] = `patterns.groups.${group}.${prop}`;\n const items = Object.entries(pItems).map(([name, p]) => {\n const base = p.base ?? {};\n const wrappable = Object.keys(base)\n .filter((prop) => prop in BASE_HOOK)\n .map((prop) => ({ sfx: BASE_HOOK[prop] as string, prop }));\n for (const { sfx, prop } of wrappable)\n reverseIndex[`--${sfx}-${name}`] = `patterns.items.${name}.base.${prop}`;\n return { name, group: p.group ?? null, base, wrappable, roles: p.roles ?? [] };\n });\n // Radii last, and only where a pattern hasn't already claimed the var: a\n // `patterns.radii` key that equals a pattern name collides on `--br-<name>`\n // (e.g. radii `card` vs the `card` pattern — a live collision in the example\n // config). The pattern's BASE_HOOK is the documented override, so it wins,\n // and `validate()` surfaces the collision as a warning so it isn't silent.\n for (const name of Object.keys(pRadii))\n if (!(`--br-${name}` in reverseIndex))\n reverseIndex[`--br-${name}`] = `patterns.radii.${name}`;\n return JSON.stringify(\n {\n colors: {\n ramps: Object.keys(expandedPalette),\n steps: NUMERIC_STEPS,\n palette: numericPalette,\n roles: colorRoles,\n roleTokens,\n },\n typography: {\n roles: Object.keys(typoRoles),\n hooks,\n families: typographyFamilies,\n specs: typoRoles,\n },\n scales: {\n text: typeSteps.map((s) => ({ name: s.name, value: s.value, max: s.max })),\n space: spaceSteps.map((s) => ({ name: s.name, value: s.value, max: s.max })),\n },\n fonts: ds.fonts ?? {},\n patterns: { defaults: pDefaults, radii: pRadii, groups: pGroups, items },\n shadows: shadows ?? {},\n reverseIndex,\n },\n null,\n 2,\n );\n })();\n\n // ── Tailwind bundle ──────────────────────────────────────────────────────────\n // Only the tailwind format consumes this (see `generate`), and assembling it\n // reads every framework partial off disk — so skip the work for css/bricks.\n const tailwind =\n format !== 'tailwind'\n ? ''\n : emitTailwind({\n ds,\n expandedPalette,\n scaleRoles,\n shadows,\n typeSteps,\n spaceSteps,\n typography,\n roleDecls,\n twTypeTokensCss,\n twPatternTokensCss,\n patternsCss: pat,\n assetsDir,\n utilities: UTILITIES,\n systemColorScheme: buildOpts.systemColorScheme === true,\n });\n\n // ── DESIGN.md ────────────────────────────────────────────────────────────────\n // Same deal as the tailwind bundle: only its own format consumes it, so the\n // other three don't pay for building it.\n const designMd =\n format !== 'design'\n ? ''\n : emitDesignMd({ ds, expandedPalette, scaleRoles, typeSteps, spaceSteps, shadows });\n\n return {\n generated,\n bricksColorsNamed,\n bricksColorsSemantic,\n bricksVariables,\n tokensJson,\n designManifest,\n tailwind,\n designMd,\n twTypeTokensCss,\n twPatternTokensCss,\n patternsCss: pat,\n };\n}\n\n// ── Tailwind emitter ──────────────────────────────────────────────────────────\ninterface TwCtx {\n ds: DesignSystem;\n expandedPalette: Record<string, ExpandedHue>;\n scaleRoles: FunctionalRole[];\n shadows: Record<string, string> | undefined;\n typeSteps: ScaleStep[];\n spaceSteps: ScaleStep[];\n typography: DesignSystem['typography'];\n roleDecls: (role: string, spec: TypographyRole) => Record<string, string>;\n twTypeTokensCss: string;\n twPatternTokensCss: string;\n patternsCss: string;\n assetsDir: string;\n /**\n * The configured `colors.utilities`. Was previously hardcoded to\n * bg/text/border at the emit site, so a consumer who enabled `outline`/\n * `fill`/`stroke` got them in css/bricks but not tailwind.\n */\n utilities: string[];\n /** `BuildOptions.systemColorScheme` — see the OS-preference block below. */\n systemColorScheme: boolean;\n}\n\nfunction emitTailwind(ctx: TwCtx): string {\n const {\n ds,\n expandedPalette,\n scaleRoles,\n shadows,\n typeSteps,\n spaceSteps,\n typography,\n roleDecls,\n twTypeTokensCss,\n twPatternTokensCss,\n patternsCss,\n assetsDir,\n utilities,\n } = ctx;\n const cssDir = join(assetsDir, 'css');\n const nl = (arr: string[]) => arr.filter(Boolean).join('\\n');\n const parts: string[] = [\n `/* GENERATED for Tailwind v4 (Astro) — do not edit by hand.\\n` +\n ` Class reference: npx vitops docs classes · All topics: npx vitops docs\\n` +\n ` Fonts below are STACKS ONLY — this file loads no webfonts. Load them with\\n` +\n ` Astro's fonts: config and point the token at the family's cssVariable. */`,\n ];\n parts.push(`@import \"tailwindcss\";\\n`);\n\n const theme: string[] = [];\n theme.push(` /* Hue scales → bg-<hue>-<step> text-* border-* (numeric, 50…950) */`);\n for (const [name, hue] of Object.entries(expandedPalette))\n for (const [n, hex] of Object.entries(hue.numeric))\n theme.push(` --color-${name}-${n}: ${hex};`);\n theme.push(`\\n /* Fonts → font-* (stacks only; no @font-face is emitted — see header) */`);\n for (const [name, stack] of Object.entries(ds.fonts ?? {}))\n theme.push(` --font-${name}: ${stack};`);\n theme.push(`\\n /* Fluid type scale → text-* */`);\n for (const s of typeSteps) theme.push(` --text-${s.name}: ${s.value};`);\n // Fluid space steps are NOT put in Tailwind's --spacing-* namespace: named\n // spacing keys shadow the size scales (e.g. `max-w-7xl` would resolve to\n // var(--spacing-7xl) ≈ 6rem and collapse layouts). They ship as --space-*\n // (matching the css format) in a plain :root below; use var(--space-<name>)\n // or the TW4 arbitrary form p-(--space-md). Numeric spacing (p-4 …) keeps\n // Tailwind's default --spacing multiplier.\n theme.push(`\\n /* Drop-shadows → shadow-* */`);\n for (const [name, value] of Object.entries(shadows ?? {}))\n theme.push(` --shadow-${name}: ${value};`);\n theme.push(`\\n /* Container breakpoints → @sm:/@md:/@lg:/@xl: */`);\n for (const [name, val] of BREAKPOINTS) theme.push(` --container-${name}: ${val};`);\n parts.push(`@theme {\\n${theme.join('\\n')}\\n}\\n`);\n\n if (spaceSteps.length)\n parts.push(\n `/* Fluid space scale — var(--space-<name>) or p-(--space-<name>) */\\n:root {\\n` +\n spaceSteps.map((s) => ` --space-${s.name}: ${s.value};`).join('\\n') +\n `\\n}\\n`,\n );\n\n // Role tokens go in a plain :root block, NOT @theme — including the emphasis\n // stops, despite those living in the --color-* namespace. The @utility set\n // below is the public API.\n //\n // This is load-bearing, not stylistic. Measured against tailwindcss@4.3.3:\n // when a token is in @theme AND an @utility of the derived name exists,\n // Tailwind merges both into one rule with the @theme declaration LAST, and it\n // does so regardless of source order. Putting `--color-<role>-<stop>` in\n // @theme would therefore silently substitute the stop for the plane on the\n // five colliding classes — including `text-<role>-muted` (step 800 → 300) and\n // `text-<role>-x-muted` (600 → 100), i.e. exactly the tokens tokens.ts's APCA\n // test guarantees are readable. Raw hue scales are safe in @theme because no\n // @utility competes for those names.\n if (scaleRoles.length) {\n let fn = '';\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.light)) fn += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n const focus = scaleRoles.find((r) => r.role === 'ui-primary') ?? scaleRoles[0];\n if (focus) fn += ` --color-border-focus: ${focus.light['bg-solid']};\\n`;\n const surface = scaleRoles.find((r) => r.role === 'surface');\n if (surface) {\n fn += ` --surface-glass: color-mix(in oklch, var(--color-bg-surface) 72%, transparent);\\n`;\n fn += ` --overlay: color-mix(in oklch, var(--color-${surface.hue}-950) 45%, transparent);\\n`;\n }\n parts.push(`/* Role tokens (the public API) */\\n:root {\\n${fn}}\\n`);\n }\n\n parts.push(\n `/* ── Framework tokens (consumed by the inlined components) ── */\\n` +\n `${twTypeTokensCss}\\n${twPatternTokensCss}`,\n );\n\n // Dark appearance: the automatic functional flip (solid stays mode-stable).\n let darkBlock = '';\n for (const fr of scaleRoles)\n for (const [t, val] of Object.entries(fr.dark))\n if (fr.light[t] !== val) darkBlock += ` ${tokenVar(fr.role, t)}: ${val};\\n`;\n {\n const surface = scaleRoles.find((r) => r.role === 'surface');\n if (surface)\n darkBlock += ` --overlay: color-mix(in oklch, var(--color-${surface.hue}-950) 60%, transparent);\\n`;\n }\n if (darkBlock) {\n parts.push(\n `/* Functional role tokens (dark) */\\n${DARK_SEL} {\\n color-scheme: dark;\\n${darkBlock}}\\n`,\n );\n // Same opt-in OS-preference block as the css/bricks path — see the comment\n // there. Emitted unlayered here for the same reason the rest of this format\n // is: Tailwind owns the layering, and role tokens must stay out of `@theme`.\n if (ctx.systemColorScheme)\n parts.push(\n `/* Functional role tokens (dark) — OS preference, no explicit choice */\\n` +\n `@media (prefers-color-scheme: dark) {\\n ${SYSTEM_DARK_SEL} {\\n` +\n ` color-scheme: dark;\\n${darkBlock.replace(/^ {2}/gm, ' ')} }\\n}\\n`,\n );\n }\n\n parts.push(\n `/* State variant for the active flip (hover/focus-visible are built in). */\\n` +\n `@custom-variant is-active (&.is-active, &[data-active]);\\n`,\n );\n\n // `typography.headings` — the bare-element → role bindings, the same rules the\n // css/bricks path emits into typography.css. This format used to emit only the\n // `@utility font-<role>` half, so a Tailwind consumer's <h1> and <body> got no\n // role styling at all: no family, no size, no text-wrap.\n //\n // Tailwind's `base` layer, deliberately. It puts these behind BOTH `@utility\n // font-<role>` (utilities layer) and the patterns (components layer), matching\n // css/bricks — where typography.css sits in vitops.utilities and the bare tag\n // selector loses to `.font-<role>` on specificity rather than on layer. Emitted\n // unlayered, an `h1` rule here would beat every Tailwind utility.\n {\n const roles = (typography?.roles ?? {}) as Record<string, TypographyRole>;\n const bindings = Object.entries(typography?.headings ?? {}).filter(([, r]) => roles[r]);\n if (bindings.length)\n parts.push(\n `/* Bare-element type roles (typography.headings) */\\n@layer base {\\n` +\n bindings\n .map(\n ([tag, role]) =>\n ` ${tag} {\\n${decls(roleDecls(role, roles[role] as TypographyRole), ' ')}\\n }`,\n )\n .join('\\n') +\n `\\n}\\n`,\n );\n }\n\n const util: string[] = [];\n if (scaleRoles.length) {\n util.push(`/* Role colour utilities (the public API) */`);\n // Same source as the css/bricks formats — the two used to diverge because\n // this path re-parsed the other's generated strings and only ever ran the\n // functional half. See roleColorUtilities().\n for (const { cls, prop, value } of roleColorUtilities(scaleRoles, utilities))\n util.push(`@utility ${cls} {\\n ${prop}: ${value};\\n}`);\n if (scaleRoles.some((r) => r.role === 'surface'))\n util.push(\n `@utility glass {\\n background-color: var(--surface-glass);\\n backdrop-filter: blur(12px);\\n -webkit-backdrop-filter: blur(12px);\\n}`,\n );\n }\n util.push(`/* Typography roles */`);\n for (const [role, spec] of Object.entries(\n (typography?.roles ?? {}) as Record<string, TypographyRole>,\n ))\n util.push(`@utility font-${role} {\\n${decls(roleDecls(role, spec))}\\n}`);\n util.push(`\\n/* Animation effects (pair with .transition or a driver) */`);\n const asStr = (v: string | number) => String(v);\n for (const [name, e] of Object.entries(ds.animations?.effects ?? {})) {\n const d: Record<string, string> = { '--_anim': e.kf };\n for (const [k, v] of Object.entries(e.css ?? {})) d[k] = asStr(v);\n for (const [k, v] of Object.entries(e.vars ?? {})) d[`--${k}`] = asStr(v);\n util.push(`@utility ${name} {\\n${decls(d)}\\n}`);\n // No `kf` filter — see the css path. `flip-size-grow` is as real as\n // `flip-fade-in`; both rest on `.transition`, which covers height behind\n // `@supports (interpolate-size: allow-keywords)`.\n const props = new Set<string>();\n for (const k of Object.keys(e.vars ?? {})) {\n const m = /^(.*)-(from|to)$/.exec(k);\n if (m) props.add(m[1] as string);\n }\n const flip = Object.fromEntries(\n [...props].map((p) => [`--t-${p}`, `var(--${p}-to, ${STATE_DEFAULT[p]})`]),\n );\n util.push(`@utility flip-${name} {\\n${decls(flip)}\\n}`);\n }\n util.push(`\\n/* Split — internal fractions (pair split with a ratio) */`);\n // The `.split` PATTERN itself is not here — it is emitted into `@layer\n // components` with the rest of the structure, so `flex-col` beats it by layer\n // exactly as it does in css/bricks. Only its modifiers are utilities.\n //\n // That placement costs `@md:split`, and nothing recovers it. Measured against\n // tailwindcss@4.3.3: `@utility` throws \"`@utility` cannot be nested\" inside\n // `@layer`, AND inside a file pulled in with `@import … layer(…)` — the layer\n // clause is itself a nesting context. A `@custom-variant` doesn't help either:\n // a variant applied to a components-layer class emits nothing, because variants\n // attach to utility candidates only. `md-flex-row` says \"become a row at md\" in\n // every format, so the loss is a bare `<bp>-split` that had no unique job.\n //\n // `order`, not `row-reverse`, so the swap applies on whichever axis the split\n // is currently on — which is the point: it decides which panel comes FIRST,\n // and that is mostly a question about the stacked state. `reading-flow` keeps\n // focus order with the visual order where supported; until that is broad,\n // only one of the two panels should hold focusable content (WCAG 2.4.3).\n util.push(\n `@utility split-reverse {\\n reading-flow: flex-visual;\\n & > :first-child { order: 1; }\\n}`,\n );\n const RATIOS: [number, number][] = [\n [1, 2],\n [2, 1],\n [1, 3],\n [3, 1],\n [1, 4],\n [4, 1],\n [2, 3],\n [3, 2],\n ];\n for (const [a, b] of RATIOS)\n util.push(\n `@utility split-${a}-${b} {\\n flex-direction: row;\\n --_split-a: ${a};\\n --_split-b: ${b};\\n}`,\n );\n // Not derivable from `@theme`: the fluid space steps are deliberately kept out\n // of Tailwind's `--spacing-*` namespace (see the note above the `:root` block),\n // so `gap-md` has to be an explicit utility here. Verified against\n // tailwindcss@4.3.3 to win over the built-in functional `gap-*` and to accept\n // variants (`@md:gap-md`), which is why no per-breakpoint classes are emitted.\n const gaps = gapUtilities(spaceSteps);\n if (gaps.length) {\n util.push(`\\n/* Gap — the fluid space scale (var(--space-<name>)) */`);\n for (const { cls, prop, value } of gaps)\n util.push(`@utility ${cls} {\\n ${prop}: ${value};\\n}`);\n }\n util.push(`\\n/* Track placement (inside .centered) */`);\n for (const track of ['measure', 'breakout', 'spotlight', 'fullbleed'])\n util.push(`@utility ${track} {\\n grid-column: ${track};\\n}`);\n\n // `layout.css` is skipped wholesale in this format and a subset re-emitted\n // above, which left these two families missing from tailwind ENTIRELY — not\n // dropped via TW_CLASH, just never re-emitted. Unlike the `<bp>-` classes they\n // have no Tailwind equivalent to fall back on, and unlike a misspelt class\n // `vitops lint` cannot flag them, because they are not anchored to the\n // consumer's config. A consumer who used them got silence and no styling.\n util.push(`\\n/* Auto-fit grid — column count is content-driven, unlike .split */`);\n util.push(\n `@utility grid-auto {\\n display: grid;\\n gap: var(--grid-gap, 1rem);\\n` +\n ` grid-template-columns: repeat(auto-fit, minmax(var(--grid-min, 13rem), 1fr));\\n` +\n // Was missing here while layout.css carried it, so in THIS format a\n // `<ul class=\"grid-auto\">` inside `.rhythm` kept the `li + li` margin: the\n // grid stretched the row to the tallest and the first cell alone looked\n // vertically offset — the exact symptom layout.css warns about.\n ` &:is(ul, ol) > li + li { margin-block-start: 0; }\\n}`,\n );\n // Applied to the SECOND element of a pair, to override the rhythm it inherited.\n util.push(`\\n/* Vertical-rhythm overrides (mirrors layout.css) */`);\n for (const pair of [\n 'h-p',\n 'p-p',\n 'p-h',\n 'h-h',\n 'p-list',\n 'list-p',\n 'li-li',\n 'text-media',\n 'media-text',\n ])\n util.push(\n `@utility m-${pair} {\\n margin-top: calc(var(--rhythm-base) * var(--rhythm-${pair}));\\n}`,\n );\n for (const [name, mult] of [\n ['0', null],\n ['xs', '0.25'],\n ['s', '0.5'],\n ['m', '1'],\n ['l', '1.5'],\n ['xl', '2'],\n ] as const)\n util.push(\n `@utility m-${name} {\\n margin-top: ${mult == null ? '0' : `calc(var(--rhythm-base) * ${mult})`};\\n}`,\n );\n parts.push(util.join('\\n') + '\\n');\n\n // Structure mirrors layout.css (kept literal for parity with the original emitter).\n parts.push(`/* ── Structure (mirrors src/css/layout.css) ── */\n:root {\n --rhythm-scale: 1;\n --rhythm-base: calc(1rlh * var(--rhythm-scale));\n --rhythm-h-p: 0.4;\n --rhythm-p-p: 0.9;\n --rhythm-p-h: 1.6;\n --rhythm-h-h: 0.6;\n --rhythm-p-list: 0.5;\n --rhythm-list-p: 0.9;\n --rhythm-li-li: 0.3;\n --rhythm-text-media: 1.2;\n --rhythm-media-text: 1.2;\n --width-measure: 65ch;\n --width-breakout: 90ch;\n --width-spotlight: 120ch;\n --gutter: clamp(1rem, 4cqi, 3rem);\n}\n\nbody {\n container-type: inline-size;\n /* Named so \\`patterns/scroll-target.css\\`'s \\`@container body (…)\\` queries\n resolve — .toc-layout/.toc-sidebar/.toc-inline. Those partials are inlined\n into this bundle verbatim, so dropping the name (as this literal did) left\n the TOC permanently in its narrow layout in the tailwind format only. */\n container-name: body;\n}\n\n/* Class-level structure rules live in \\`components\\` so track/spacing utilities\n (@layer utilities — later in the layer order) can override them; unlayered\n CSS would beat ALL layered utilities regardless of specificity (e.g.\n \\`.centered > *\\` pinning children to \\`measure\\` over \\`.spotlight\\`). */\n@layer components {\n.rhythm {\n display: flow-root;\n}\n.rhythm > * + * {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-p-p));\n}\n.rhythm > :where(h1, h2, h3, h4, h5, h6) + p {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-h-p));\n}\n.rhythm > p + :where(h1, h2, h3, h4, h5, h6) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-p-h));\n}\n.rhythm > :where(h1, h2, h3, h4, h5, h6) + :where(h1, h2, h3, h4, h5, h6) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-h-h));\n}\n.rhythm > p + :where(ul, ol) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-p-list));\n}\n.rhythm > :where(ul, ol) + p {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-list-p));\n}\n.rhythm :where(ul, ol) > li + li {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-li-li));\n}\n.rhythm > :where(p, h1, h2, h3, h4, h5, h6, ul, ol) + :where(figure, img, picture, video) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-text-media));\n}\n.rhythm > :where(figure, img, picture, video) + :where(p, h1, h2, h3, h4, h5, h6, ul, ol) {\n margin-top: calc(var(--rhythm-base) * var(--rhythm-media-text));\n}\n\n.centered {\n --_measure: min(var(--width-measure), 100% - var(--gutter) * 2);\n --_breakout: minmax(0, calc((var(--width-breakout) - var(--width-measure)) / 2));\n --_spotlight: minmax(0, calc((var(--width-spotlight) - var(--width-breakout)) / 2));\n position: relative;\n display: grid;\n grid-template-columns:\n [fullbleed-start] minmax(var(--gutter), 1fr)\n [spotlight-start] var(--_spotlight)\n [breakout-start] var(--_breakout)\n [measure-start] var(--_measure) [measure-end]\n var(--_breakout) [breakout-end]\n var(--_spotlight) [spotlight-end]\n minmax(var(--gutter), 1fr) [fullbleed-end];\n}\n.centered > * {\n grid-column: measure;\n}\n\n.region {\n padding-block: clamp(\n var(--region-space-min, 3rem),\n var(--region-space, 8vh),\n var(--region-space-max, 8rem)\n );\n}\n\n/* \\`.split\\` is a PATTERN, so it belongs here rather than in an \\`@utility\\` — that\n is what makes \\`flex-col\\` beat it by layer instead of by a source-order race\n whose winner depends on Tailwind's property-based sort of custom utilities.\n Its ratio/reversal modifiers stay utilities. Mirrors layout.css, where each\n rule's rationale is written out; in short: \\`min-inline-size: 0\\` because a flex\n item's automatic minimum is its min-content size; the ratio as a flex BASIS\n rather than a grow factor, because grow shares out only the free space and a\n child's padding is not part of it; scoped to a two-child split because a ratio\n is a pair contract and a middle child with no basis would collapse to zero;\n \\`box-sizing: border-box\\` because a basis only sizes the border box on a\n border-box item (Tailwind's preflight sets it, the other formats' reset does). */\n.split {\n display: flex;\n flex-direction: row;\n}\n.split > * {\n flex: 1;\n box-sizing: border-box;\n min-inline-size: 0;\n}\n.split > :first-child {\n flex-grow: var(--_split-a, 1);\n}\n.split > :last-child {\n flex-grow: var(--_split-b, 1);\n}\n.split > :first-child:nth-last-child(2) {\n flex-basis: ${splitBasis('--_split-a')};\n}\n.split > :nth-child(2):last-child {\n flex-basis: ${splitBasis('--_split-b')};\n}\n}\n`);\n\n // Same layering rationale as the structure block above. Guarded on existence\n // like componentPartialOrder below: `assets/**` is a gitignored build artifact\n // that `vp test` does not produce, so an unguarded read makes the tailwind\n // format untestable in a clean checkout — which is how an 87-class vocabulary\n // gap between css and tailwind went unnoticed. The token layer still emits.\n const animPath = join(cssDir, 'animation.css');\n const animEngine = existsSync(animPath) ? readFileSync(animPath, 'utf8') : '';\n if (animEngine)\n parts.push(\n `/* ── Animation engine (animation.css) ── */\\n@layer components {\\n${animEngine}\\n}`,\n );\n // Patterns live in Tailwind's `components` layer so single-purpose utilities\n // (@layer utilities — declared later in the layer order) override them, e.g.\n // `.text-on-ui-primary` beating the link pattern's element-level `a { color }`.\n // Unlayered CSS would win over ALL layered utilities regardless of specificity.\n parts.push(`/* ── Component patterns ── */\\n@layer components {\\n${patternsCss}\\n}`);\n\n // Component + structural partials: the full framework library, minus the\n // Tailwind-owned utility layer. Sourced live from the CSS partials (in index.css\n // cascade order) so this never goes stale, then run through stripForTailwind\n // (dropping the TW_CLASH names Tailwind provides itself).\n const droppedClashes = new Set<string>();\n let droppedVariantBlocks = 0;\n /**\n * Is this `@container (min-width: …)` block a PRE-EXPANDED VARIANT block —\n * i.e. only `.sm-*`/`.md-*`/`.lg-*`/`.xl-*` utility classes, which Tailwind\n * regenerates on demand as `@md:`?\n *\n * Anything else in a container query is component *behaviour*, not a variant,\n * and dropping it breaks the component. `sitenav.css` is the case that caught\n * this: its `@container (min-width: 48rem) { .sitenav--bp-md { … } }` is what\n * switches the nav to its desktop layout, and blanket-dropping every\n * container block meant the tailwind format shipped a nav stuck in mobile.\n */\n const isVariantBlock = (raw: string): boolean => {\n const open = raw.indexOf('{');\n const body = raw.slice(open + 1, raw.lastIndexOf('}'));\n const selectors: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < body.length; i++) {\n const ch = body[i];\n if (ch === '{') {\n if (depth === 0) selectors.push(body.slice(start, i));\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) start = i + 1;\n }\n }\n const names = selectors\n .flatMap((s) => s.split(','))\n .map((s) => s.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim())\n .filter(Boolean);\n return names.length > 0 && names.every((n) => /^\\.(sm|md|lg|xl)-/.test(n));\n };\n const stripForTailwind = (css: string): string => {\n const kept: string[] = [];\n let depth = 0;\n let start = 0;\n let preludeEnd = -1;\n for (let i = 0; i < css.length; i++) {\n const ch = css[i];\n if (ch === '/' && css[i + 1] === '*') {\n const end = css.indexOf('*/', i + 2);\n i = end === -1 ? css.length : end + 1;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n i += 1;\n while (i < css.length && css[i] !== ch) i += css[i] === '\\\\' ? 2 : 1;\n continue;\n }\n if (ch === '{') {\n if (depth === 0) preludeEnd = i;\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n const raw = css.slice(start, i + 1).trim();\n const prelude = css\n .slice(start, preludeEnd)\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .trim();\n const clash = /^\\.([A-Za-z0-9_-]+)/.exec(prelude);\n const name = clash?.[1] as string | undefined;\n if (/^@container\\s*\\(\\s*min-width:/.test(prelude) && isVariantBlock(raw))\n droppedVariantBlocks++;\n else if (name && TW_CLASH.has(name) && !CLASH_KEEP.has(name)) droppedClashes.add(name);\n else if (raw) kept.push(raw);\n start = i + 1;\n }\n }\n }\n return kept.join('\\n\\n');\n };\n\n const partials = componentPartialOrder(cssDir);\n const componentCss = partials\n .map((rel) => {\n const css = readFileSync(join(cssDir, rel), 'utf8');\n return `/* ── ${rel} ── */\\n${stripForTailwind(css)}`;\n })\n .join('\\n\\n');\n // Same layering rationale as the patterns block above. `componentPartialOrder`\n // already returns [] when assets are absent, so this is empty in that case.\n if (componentCss)\n parts.push(\n `/* ── Component + structural partials (Tailwind-clashing utilities dropped) ── */\\n` +\n `/* Dropped ${droppedVariantBlocks} pre-expanded breakpoint block(s) — write @sm:/@md:/@lg:/@xl: instead.\\n` +\n ` Dropped ${droppedClashes.size} clashing utilit(ies) Tailwind provides itself:\\n` +\n ` ${[...droppedClashes].sort().join(' ') || '(none)'} */\\n` +\n `@layer components {\\n${componentCss}\\n}`,\n );\n\n return nl(parts) + '\\n';\n}\n\n/**\n * Partials the tailwind format does NOT inline, because it re-creates them by\n * hand: the engine (`global.css` — Tailwind's preflight covers the reset;\n * `animation.css` — read directly and wrapped in `@layer components`), and the\n * two layout partials, whose utilities are re-emitted as `@utility` and whose\n * structure is re-emitted in the `@layer components` literal.\n *\n * **Every partial mapped to `vitops.utilities` must be listed here.** Inlining a\n * utility family lands it in tailwind's `@layer components`, the exact inversion\n * the layer split exists to remove — and it fails SILENTLY, because each of those\n * classes already exists as an `@utility` that wins on layer anyway. You would get\n * ~30 dead rules and no test failure. `format-parity.test.ts` asserts the\n * implication structurally rather than spot-checking the output.\n *\n * The implication is one-way: `layout.css` is skipped while sitting in\n * `vitops.components`, because its structure is re-emitted by hand.\n */\n/**\n * Framework COMPONENTS whose class name collides with a Tailwind utility, and\n * which must therefore survive the `TW_CLASH` strip.\n *\n * The clash test matches a rule's leading `.<name>`, which is right for a\n * single-purpose utility (Tailwind ships its own) and wrong for a pattern that\n * merely shares the name. `patterns/sticky.css` opens `.sticky { … }` and was\n * being deleted from the tailwind bundle WHOLESALE — the `--_sticky-offset`\n * wiring, the z-index, and every `&.sticky--bottom`/`--inline-start` variant —\n * so a consumer writing `class=\"sticky sticky--bottom\"` got bare\n * `position: sticky` and nothing else.\n *\n * `table` is here for the same reason but was never actually hit: `table.css`'s\n * prelude is `table,\\n.table`, which doesn't start with `.`, so the regex missed\n * it by luck. Listing it makes that explicit rather than accidental.\n */\nconst CLASH_KEEP: ReadonlySet<string> = new Set(['sticky', 'table']);\n\nexport const TAILWIND_SKIP: ReadonlySet<string> = new Set([\n 'global.css',\n 'animation.css',\n 'layout.css',\n 'layout-utilities.css',\n // Everything left here after the reveal family moved to patterns/reveal.css is\n // either a TW_CLASH name (display, sr-only, text-wrap) or a pre-expanded\n // variant block, so the strip already emptied it — reading it was pure waste,\n // and leaving it out made the invariant above look violated when it wasn't.\n 'utilities.css',\n]);\n\n/**\n * The component/structural CSS partials to inline into the Tailwind bundle, in\n * index.css cascade order. Everything the aggregator imports EXCEPT `TAILWIND_SKIP`\n * and the generated token layer (Tailwind builds its own via @theme).\n */\nfunction componentPartialOrder(cssDir: string): string[] {\n const indexPath = join(cssDir, 'index.css');\n const order: string[] = [];\n const seen = new Set<string>();\n const text = existsSync(indexPath) ? readFileSync(indexPath, 'utf8') : '';\n for (const m of text.matchAll(/@import\\s+['\"]\\.\\/([^'\"]+)['\"]/g)) {\n const rel = m[1] as string;\n if (rel.startsWith('generated/')) continue;\n if (TAILWIND_SKIP.has(rel)) continue;\n if (!seen.has(rel) && existsSync(join(cssDir, rel))) {\n seen.add(rel);\n order.push(rel);\n }\n }\n // Fallback: if no index.css, inline utilities + every pattern partial.\n if (!order.length) {\n if (existsSync(join(cssDir, 'utilities.css'))) order.push('utilities.css');\n const pdir = join(cssDir, 'patterns');\n if (existsSync(pdir))\n for (const f of readdirSync(pdir).sort()) if (f.endsWith('.css')) order.push(`patterns/${f}`);\n }\n return order;\n}\n\n// ── CSS bundling (css + bricks formats) ───────────────────────────────────────\n\n/** The bundle's cascade layers, in precedence order (last wins). */\nexport const CSS_LAYERS = ['vitops.base', 'vitops.components', 'vitops.utilities'] as const;\n\n/**\n * Which layer each `index.css` chunk belongs to. Anything unmapped defaults to\n * `vitops.components` — the safe default, since an unrecognised partial is far\n * more likely to be a component than a utility family.\n *\n * The split is by what the file *emits*, not what it's named:\n * • base — the UA reset and the pure `:root` token blocks.\n * • components — the animation engine, structural layout, and every pattern.\n * • utilities — the single-purpose classes that must be able to override a\n * pattern (`bg-*`, `drop-shadow-*`, `font-*`, effects, …).\n *\n * `color.css` and `shadows.css` each mix a `:root` block with utility classes\n * and go to `utilities` whole. That is safe because custom-property resolution\n * is NOT source-order dependent — a `:root` block declared after a rule that\n * reads it still resolves.\n *\n * `layout.css` is genuinely mixed (structural `.rhythm`/`.centered` AND\n * `.m-*`/`.flex`/`.split-*` utilities) and stays in `components` whole, so its\n * utility half still can't override a pattern. Splitting it is a separate\n * change; see the 0.9.0 changelog.\n */\nexport const CHUNK_LAYER: Record<string, (typeof CSS_LAYERS)[number]> = {\n 'global.css': 'vitops.base',\n 'generated/type-tokens.css': 'vitops.base',\n 'generated/tokens.css': 'vitops.base',\n 'generated/color.css': 'vitops.utilities',\n 'generated/shadows.css': 'vitops.utilities',\n 'generated/typography.css': 'vitops.utilities',\n 'generated/animation-effects.css': 'vitops.utilities',\n 'generated/spacing.css': 'vitops.utilities',\n 'layout-utilities.css': 'vitops.utilities',\n 'utilities.css': 'vitops.utilities',\n};\n\n/**\n * A `.split` child's flex basis. The ratio is a BASIS rather than a grow factor\n * because grow shares out only the FREE space, which a child's padding is not\n * part of — so a padded column came out wider than its sibling by exactly its\n * horizontal padding. Must stay character-identical to layout.css; the parity\n * suite matches this expression against both.\n */\nexport const splitBasis = (v: '--_split-a' | '--_split-b'): string =>\n `calc(var(${v}, 1) / (var(--_split-a, 1) + var(--_split-b, 1)) * 100%)`;\n\n/** The layer a partial's rules are wrapped in; unmapped partials are components. */\nexport const layerForPartial = (rel: string): (typeof CSS_LAYERS)[number] =>\n CHUNK_LAYER[rel] ?? 'vitops.components';\n\n/**\n * Assemble the full stylesheet by resolving index.css's @import order against the\n * static partials (from assets) and the freshly generated token partials (in\n * memory), then minify with lightningcss. No @import survives, so no disk\n * resolution / shared `generated/` dir is needed.\n *\n * Each chunk is wrapped in a cascade layer. This is what lets a single-purpose\n * utility override a component pattern — `class=\"card bg-danger-muted\"` — which\n * previously depended on source order and so silently did nothing here while\n * working in the tailwind format, where Tailwind's own layers already ordered\n * them correctly.\n *\n * Consequence worth knowing: unlayered CSS beats ALL layered CSS regardless of\n * specificity, so a consumer's own stylesheet now wins over the framework by\n * default. That is deliberate — it is the override story every layered\n * framework ships — but it means an unlayered *reset* will beat framework\n * component rules it used to lose to. Such a reset belongs in a layer declared\n * before `vitops.base` (see the `<style>` block in this repo's index.html).\n */\nfunction bundleCss(\n generated: Record<string, string>,\n assetsDir: string,\n minify: boolean,\n): { code: string; map: string | undefined } {\n const cssDir = join(assetsDir, 'css');\n const indexPath = join(cssDir, 'index.css');\n const index = readFileSync(indexPath, 'utf8');\n const chunks: string[] = [];\n for (const line of index.split('\\n')) {\n const m = /@import\\s+['\"]\\.\\/([^'\"]+)['\"]/.exec(line);\n if (!m) continue;\n const rel = m[1] as string;\n const body = rel.startsWith('generated/')\n ? (generated[rel.slice('generated/'.length)] ?? '')\n : readFileSync(join(cssDir, rel), 'utf8');\n if (!body.trim()) continue;\n chunks.push(`@layer ${layerForPartial(rel)} {\\n${body}\\n}`);\n }\n // `/*!` rather than `/*`: lightningcss strips ordinary comments when\n // minifying, and both the css and bricks bundles are minified — so a plain\n // banner would never reach the file anyone actually opens. Whoever opens this\n // is looking for a class name; point them at the live reference.\n const banner =\n `/*! GENERATED by @getvitops/generator — do not edit by hand.\\n` +\n ` Class reference: npx vitops docs classes · All topics: npx vitops docs */\\n`;\n // Declare the order up front so it is explicit rather than an artifact of\n // which chunk happened to appear first.\n const merged = banner + `@layer ${CSS_LAYERS.join(', ')};\\n` + chunks.join('\\n');\n const res = transform({\n filename: 'styles.css',\n code: Buffer.from(merged),\n minify,\n sourceMap: minify,\n });\n return {\n code: res.code.toString(),\n map: res.map ? res.map.toString() : undefined,\n };\n}\n\n// ── public generate() ─────────────────────────────────────────────────────────\n/**\n * Read `input` as whichever config kind it is, and return the design system to\n * build from plus the site config if that is what it was.\n *\n * The design system is validated here rather than in `resolveInput` so the error\n * can name where it came from: a theme inside a site config reports its `themes`\n * path, which is the difference between \"your config is wrong\" and \"your config\n * is wrong *here*\" when the file is a few hundred lines of company facts.\n */\nfunction loadInput(\n input: string | DesignSystem | Config,\n opts: { theme?: string; siteEnv?: string },\n): { ds: DesignSystem; config?: Config } {\n const raw = typeof input === 'string' ? JSON.parse(readFileSync(input, 'utf8')) : input;\n const resolved = resolveInput(raw, opts);\n const result = validate(resolved.designSystem);\n if (!result.ok) {\n const where =\n resolved.theme != null\n ? `design system at designSystem.themes.${resolved.theme}`\n : 'design-system.json';\n const lines = result.errors\n .slice(0, 12)\n .map((e) => ` • ${e.path.join('.') || '(root)'}: ${e.message}`)\n .join('\\n');\n throw new Error(`Invalid ${where}:\\n${lines}`);\n }\n for (const w of result.warnings) console.warn(`[vitops] ${w}`);\n return { ds: result.data, ...(resolved.config ? { config: resolved.config } : {}) };\n}\n\nexport async function generate(options: GenerateOptions): Promise<GenerateResult> {\n const format: Format = options.format ?? 'bricks';\n const outDir = options.outDir ?? 'dist';\n const assetsDir = options.assetsDir ?? DEFAULT_ASSETS;\n const { ds, config: embedded } = loadInput(options.input, {\n ...(options.theme != null ? { theme: options.theme } : {}),\n ...(options.siteEnv != null ? { siteEnv: options.siteEnv } : {}),\n });\n // Loaded before `build` because `designSystem.defaultColorScheme` decides what\n // the colour layer emits. (It is read again below for legal documents;\n // resolving twice would validate twice and double any warning.)\n //\n // An explicit `site` wins over one embedded in `input` — it is the more\n // specific statement, and the two are the same file in every case but the one\n // where a consumer deliberately split them.\n const config = options.site != null ? loadConfigFile(options.site, options.siteEnv) : embedded;\n const built = build(ds, format, assetsDir, {\n systemColorScheme:\n options.systemColorScheme ?? config?.designSystem?.defaultColorScheme === 'system',\n });\n mkdirSync(outDir, { recursive: true });\n const written: string[] = [];\n const put = (rel: string, content: string) => {\n const p = join(outDir, rel);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, content);\n written.push(p);\n };\n\n if (format === 'design') {\n // Deliberately the only output: DESIGN.md conventionally lives at the repo\n // root next to AGENTS.md, not in a build directory, so this format is meant\n // to be run with `--out .` — writing a stylesheet alongside it would be\n // surprising. Compose it when you want both: `--format css,design`.\n put('DESIGN.md', built.designMd);\n } else if (format === 'tailwind') {\n put('tailwind.css', built.tailwind);\n put('tokens.json', built.tokensJson);\n } else if (format === 'css') {\n const { code } = bundleCss(built.generated, assetsDir, true);\n put('styles.css', code);\n put('tokens.json', built.tokensJson);\n put('design-manifest.json', built.designManifest);\n } else {\n // bricks: bundled minified CSS + Bricks import JSON + copied JS/PHP/docs.\n const { code, map } = bundleCss(built.generated, assetsDir, true);\n put('styles.min.css', map ? code + `\\n/*# sourceMappingURL=styles.min.css.map */` : code);\n if (map) put('styles.min.css.map', map);\n put('bricks-colors-named.json', built.bricksColorsNamed);\n put('bricks-colors-semantic.json', built.bricksColorsSemantic);\n put('bricks-variables.json', built.bricksVariables);\n put('tokens.json', built.tokensJson);\n // Framework-static JS bundles → outDir root (theme enqueues them).\n const jsDir = join(assetsDir, 'js');\n if (existsSync(jsDir)) {\n cpSync(jsDir, outDir, { recursive: true });\n for (const f of readdirSync(jsDir)) written.push(join(outDir, f));\n }\n // Bricks PHP elements + loader → outDir/bricks.\n const bricksSrc = join(assetsDir, 'bricks');\n if (existsSync(bricksSrc)) {\n cpSync(bricksSrc, join(outDir, 'bricks'), { recursive: true });\n written.push(join(outDir, 'bricks'));\n }\n // OKF docs bundle (generated per-config) → outDir/docs.\n const docs = generateDocs(ds, assetsDir);\n for (const [rel, content] of Object.entries(docs)) put(join('docs', rel), content);\n }\n\n // Legal documents → outDir/legal, as HTML fragments.\n //\n // Opt-in via `site`, and emitted for every format that emits files at all —\n // passing a site config and silently getting nothing back would be the\n // surprising behaviour. `design` is excluded because it emits DESIGN.md and\n // deliberately nothing else.\n //\n // HTML rather than markdown because this is the fragment a WordPress theme,\n // a Bricks shortcode or a plain page can include with no build step of its own.\n if (config != null && format !== 'design') {\n const legal = generateLegal(config, { output: 'html' });\n for (const [name, content] of Object.entries(legal)) put(join('legal', name), content);\n\n // Icon sprite → outDir/icons.svg.\n //\n // Opt-in via `icons.sprite`, because building it needs the @iconify-json/*\n // collections and most consumers render icons through their framework's own\n // integration instead. This is the path for the ones that can't: Bricks,\n // EmDash renderers, any plain HTML — `<use href=\"…/icons.svg#id\">`, no JS.\n const icons = config.site.icons as\n | { sprite?: boolean; ui?: string; brand?: string; weight?: string; semantic?: string[] }\n | undefined;\n if (icons?.sprite) {\n const { ui, brand, weight, semantic, sprite: _sprite, ...sets } = icons;\n const include = generateIconInclude({\n ...(ui ? { ui } : {}),\n ...(brand ? { brand } : {}),\n ...(weight ? { weight } : {}),\n ...(semantic ? { semantic } : {}),\n ...sets,\n });\n // Semantic names get a set-independent alias (`icon-menu`) alongside the\n // qualified id, so markup written against a sprite survives a set swap —\n // the same guarantee `resolveIcon` gives Astro consumers.\n const aliases: Record<string, string> = {};\n for (const name of semantic ?? []) {\n try {\n aliases[`icon-${name}`] = resolveIcon(name, ui ?? 'fa7-solid', weight ? { weight } : {});\n } catch {\n // Already reported by generateIconInclude, which throws on the same input.\n }\n }\n const built = await buildIconSprite({ include, aliases });\n put('icons.svg', built.svg);\n if (built.missing.length)\n console.warn(\n `[vitops] icons.sprite: ${built.missing.length} icon(s) were not found and are ` +\n `absent from the sprite: ${built.missing.join(', ')}.`,\n );\n }\n }\n\n return { format, outDir, written };\n}\n\nfunction loadConfigFile(input: string | Config, siteEnv?: string): Config {\n const raw = typeof input === 'string' ? JSON.parse(readFileSync(input, 'utf8')) : input;\n // resolveConfig validates and throws with one issue per line.\n return resolveConfig(raw, siteEnv);\n}\n","/**\n * @getvitops/generator — public API.\n *\n * Turn a `design-system.json` into platform outputs (Bricks, standalone CSS,\n * Tailwind v4). The `zod/mini` schema is the single source of truth: types,\n * validation, and the published JSON Schema all derive from it.\n */\nexport { generate, roleColorUtilities } from './generate.ts';\nexport type {\n GenerateOptions,\n GenerateResult,\n Format,\n StylesheetFormat,\n ColorUtility,\n} from './generate.ts';\n\n// Exposed so `vitops lint` can ask what the generator emits instead of\n// re-deriving the vocabulary and drifting from it.\nexport { expandPalette, functionalRole } from './tokens.ts';\nexport type { ExpandedHue, FunctionalRole } from './tokens.ts';\n\nexport { generateDocs } from './docs.ts';\n/**\n * SVG sprite emitter. `spriteId` is the id grammar `<use href=\"…#id\">` targets;\n * @getvitops/astro's Icon.astro mirrors it, so treat it as a shared contract.\n */\nexport { buildIconSprite, loadIconSvg, spriteId } from './icons-sprite.ts';\nexport type { IconSpriteOptions, IconSpriteResult } from './icons-sprite.ts';\nexport { NUMERIC_STEPS } from './tokens.ts';\nexport {\n TW_CLASH,\n BASE_HOOK,\n DARK_SEL,\n REQUIRED_ROLES,\n ROLE_TOKEN_KEYS,\n roleHue,\n roleKind,\n} from './shared.ts';\nexport type { RoleSpec } from './shared.ts';\nexport { tokenVar, tokenClass, CONTRAST } from './tokens.ts';\nexport type { RoleKind } from './tokens.ts';\n\nexport { DesignSystemSchema, jsonSchema, SCHEMA_URL, validate } from './schema.ts';\nexport type { DesignSystem, ValidationResult } from './schema.ts';\nexport {\n ConfigSchema,\n SiteFontSchema,\n configJsonSchema,\n CONFIG_SCHEMA_URL,\n validateConfig,\n resolveConfig,\n resolvePrivacyContact,\n resolveTheme,\n // Every entry point that takes a config goes through these, so a consumer who\n // keeps their tokens inside the larger three-section config points the same\n // option at that file rather than maintaining a second one.\n isConfig,\n resolveInput,\n stripNulls,\n deepMerge,\n JURISDICTIONS,\n} from './config.ts';\nexport type {\n ContactObject,\n Jurisdiction,\n PostalAddress,\n ResolvedInput,\n Config,\n OrganizationConfig,\n SiteSection,\n SiteFont,\n SiteIndexNow,\n SiteIndexing,\n SiteSearchConsole,\n ConfigValidationResult,\n} from './config.ts';\n\n// Legal documents. A sibling of `generateDocs`, not a `generate()` format:\n// `generate()` is keyed to a DesignSystem, and these render from a Config.\nexport {\n generateLegal,\n enabledDocs,\n renderMarkdown,\n renderNodes,\n derivePolicyVars,\n detectProcessorKeys,\n resolveProcessors,\n KNOWN_PROCESSORS,\n parseMarkdown,\n toContentNodes,\n toHtmlFragment,\n toPortableText,\n DOC_ORDER,\n DOC_SLUGS,\n TEMPLATES,\n} from './legal/index.ts';\nexport type {\n GenerateLegalOptions,\n LegalDoc,\n LegalOutput,\n PolicyVars,\n Processor,\n KnownProcessorKey,\n Block,\n Span,\n DocSet,\n} from './legal/index.ts';\n\nimport { SCHEMA_URL, type DesignSystem } from './schema.ts';\n\n/**\n * A minimal but complete starter design system, used by `vitops init`. It\n * validates against the schema and generates real output in every format, so a\n * new project can `vitops generate` immediately and then tune from here.\n */\nexport function defaultConfig(): DesignSystem {\n return {\n $schema: SCHEMA_URL,\n colors: {\n // Each hue is generated as an 11-step OKLCH scale from its seed.\n palette: {\n brand: { seed: '#2e9b73' },\n ink: { seed: '#3f4a5c' },\n sky: { seed: '#2f7bc0' },\n sun: { seed: '#d08a1f' },\n rose: { seed: '#c74a42' },\n },\n // role → hue. Tokens (--color-<target>-<role>-<variant>) derive from the\n // hue's scale; dark mode flips automatically. `kind: \"surface\"` marks the\n // page/panel colours, which get a bare `bg-<role>`; the bare-string form\n // means chromatic, so a signal colour says tint-or-solid rather than\n // leaving \"how loud?\" to a guess.\n roles: {\n neutral: { hue: 'ink', kind: 'surface' },\n surface: { hue: 'ink', kind: 'surface' },\n 'ui-primary': 'brand',\n 'brand-primary': 'brand',\n info: 'sky',\n success: 'brand',\n warning: 'sun',\n danger: 'rose',\n },\n utilities: ['bg', 'text', 'icon', 'border'],\n },\n shadows: {\n sm: '0 1px 2px rgb(0 0 0 / 0.08)',\n md: '0 4px 6px rgb(0 0 0 / 0.12)',\n lg: '0 10px 15px rgb(0 0 0 / 0.18)',\n },\n fonts: {\n display: 'system-ui, -apple-system, \"Segoe UI\", sans-serif',\n sans: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n mono: 'ui-monospace, \"SF Mono\", Menlo, monospace',\n },\n typeScale: {\n base: '1rem',\n names: ['2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl'],\n baseStep: 4,\n baseline: 'm',\n ratio: 1.2,\n fluid: { minVw: '22.5rem', maxVw: '80rem', minRatio: 1.12 },\n },\n spaceScale: {\n base: '1rem',\n names: ['2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl'],\n baseStep: 4,\n baseline: 'm',\n ratio: 1.25,\n fluid: { minVw: '22.5rem', maxVw: '80rem', minRatio: 1.2 },\n },\n patterns: {\n defaults: {\n ds: 'none',\n b: '1px solid var(--color-border-surface-muted)',\n br: '0.375rem',\n p: '1rem',\n fs: '1rem',\n },\n // No `card` key here: a radii key named after a pattern collides on `--br-<name>`,\n // shadowing that pattern's override hook and leaving its `-group` alias unreachable\n // (validate() warns about exactly this). `card` is in the `panel` group, which already\n // carries the same 0.5rem, so dropping it is value-preserving.\n radii: { pill: '999px', circle: '50%' },\n groups: {\n control: {\n ds: 'var(--ds-default)',\n b: 'var(--b-default)',\n br: 'var(--br-default)',\n p: '0.5em 1em',\n fs: 'var(--fs-default)',\n },\n panel: {\n ds: 'var(--shadow-md)',\n b: 'var(--b-default)',\n br: '0.5rem',\n p: '1rem',\n fs: 'var(--fs-default)',\n },\n },\n z: { raised: 1, sticky: 100, overlay: 200, top: 1000 },\n items: {\n // Affordance tier: bare <button> and .btn share one zero-specificity rule,\n // so any explicit class (including .cta) overrides it.\n btn: {\n group: 'control',\n element: 'button',\n class: 'btn',\n fill: false,\n // Geometry resolves through the group alias layer (`--<prop>-btn-group`),\n // so the mapping to the `control` group lives in CSS and stays editable;\n // `overrides` restate only what this tier does differently.\n overrides: { b: '1px solid transparent', fs: 'inherit' },\n base: {\n display: 'inline-flex',\n 'align-items': 'center',\n 'justify-content': 'center',\n gap: '0.4em',\n padding: 'var(--p-btn-group)',\n 'border-radius': 'var(--br-btn-group)',\n border: 'var(--b-btn-group)',\n 'box-shadow': 'var(--ds-btn-group)',\n background: 'transparent',\n color: 'inherit',\n 'font-family': 'inherit',\n 'font-size': 'var(--fs-btn-group)',\n 'font-weight': 'inherit',\n 'text-decoration': 'none',\n cursor: 'pointer',\n },\n states: {\n hover: { step: 1, css: { 'background-color': 'var(--color-bg-surface-muted)' } },\n 'focus-visible': { ring: true },\n },\n roles: [],\n },\n // Persuasion tier: opt-in, works on any element (<a>, <button>, <summary>).\n cta: {\n group: 'control',\n class: 'cta',\n fill: true,\n // `ui-primary`, not `brand-primary`: a CTA is a prominent *interface*\n // affordance, and its prominence already comes from fill/weight/padding.\n // Keeping it on the ui role means the whole interaction family (btn,\n // link, cta) shares one hue lineage — otherwise focus rings change\n // colour depending on which tier you tabbed onto. Brand stays reachable\n // as an explicit `.cta-brand-primary` variant.\n default_role: 'ui-primary',\n overrides: { p: '0.75em 1.5em', b: 'none', ds: 'var(--shadow-sm)', fs: 'inherit' },\n base: {\n display: 'inline-flex',\n 'align-items': 'center',\n 'justify-content': 'center',\n gap: '0.5em',\n padding: 'var(--p-cta-group)',\n 'border-radius': 'var(--br-cta-group)',\n border: 'var(--b-cta-group)',\n 'font-family': 'inherit',\n 'font-size': 'var(--fs-cta-group)',\n 'font-weight': '600',\n 'text-decoration': 'none',\n cursor: 'pointer',\n color: 'var(--color-text-on-ui-primary)',\n 'box-shadow': 'var(--ds-cta-group)',\n },\n states: {\n hover: { step: 1, lift: '1px' },\n active: { scale: 0.97 },\n 'focus-visible': { ring: true },\n },\n roles: [],\n },\n card: {\n group: 'panel',\n class: 'card',\n base: {\n 'border-radius': 'var(--br-card-group)',\n padding: '1.5rem',\n background: 'var(--color-bg-surface)',\n border: 'var(--b-card-group)',\n 'box-shadow': 'var(--ds-card-group)',\n },\n states: {},\n roles: [],\n },\n },\n },\n typography: {\n families: {\n display: 'var(--font-display)',\n sans: 'var(--font-sans)',\n code: 'var(--font-mono, ui-monospace, monospace)',\n },\n // `text-wrap` is stated on every role because omitting it is NOT \"inherit\":\n // it is emitted at its identity (`wrap`) so role classes fully reset one\n // another, which would cancel the `pretty` a role inherits from body.\n roles: {\n display: {\n family: 'display',\n size: 'var(--text-3xl)',\n weight: 700,\n 'line-height': '1.05',\n tracking: '-0.03em',\n 'text-wrap': 'balance',\n },\n heading: {\n family: 'display',\n size: 'var(--text-xl)',\n weight: 600,\n 'line-height': '1.3',\n 'text-wrap': 'balance',\n },\n body: {\n family: 'sans',\n size: 'var(--text-m)',\n weight: 400,\n 'line-height': '1.55',\n 'text-wrap': 'pretty',\n },\n },\n // `body` binds base page typography to the body role, so prose inherits it\n // and the role's tokens stay the single place it's edited.\n headings: { body: 'body', h1: 'display', h2: 'heading', h3: 'heading' },\n },\n animations: {\n effects: {\n 'fade-in': { kf: 'composite', vars: { 'opacity-from': 0 } },\n 'slide-up': {\n kf: 'composite',\n vars: { 'translate-y-from': 'var(--slide-distance, 2rem)' },\n },\n },\n journeys: {\n // Each part must declare the `from` endpoint its keyframe reads — an\n // empty `slide` leaves slide-journey animating translate 0 → 0, i.e. a\n // journey that silently doesn't slide. Same var as the `slide-up`\n // effect above, so `--slide-distance` tunes both.\n base: {\n fade: { 'opacity-from': 0 },\n slide: { 'translate-y-from': 'var(--slide-distance, 2rem)' },\n },\n compose: [['fade'], ['slide'], ['fade', 'slide']],\n },\n },\n };\n}\n"],"mappings":"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"}
|