import type { VendoTheme, VendoThemeFont } from "../../core/apps/index.js"; import { z } from "zod"; /** Slot values → the frozen runtime VendoTheme contract — one derivation law, * never two (theme/provenance.ts leans on this exact derivation). */ export declare function toVendoTheme(slots: ThemeSlotValues): VendoTheme; /** * Record on a theme document which faces `.vendo/fonts.css` actually holds. * * The ONE place that metadata is attached, because there are two writers that * must agree — the install path builds a fresh document, the reconcile path * edits the host's — and they drifted: a rebrand rewrote the sheet and left * `typography.fonts` advertising the previous brand's faces. An empty list * REMOVES the key rather than writing `[]`, so a theme never claims faces that * are not on disk. * * Faces for a family this document does NOT select are dropped, so the metadata * cannot name a typeface the theme rejected — the case a `--theme fontFamily=` * answer creates by overriding the family AFTER the faces were resolved. */ export declare function applyThemeFonts(theme: unknown, fonts: VendoThemeFont[]): void; export interface ThemeSlotValues { accent: string; accentText: string; background: string; border: string; danger: string; surface: string; text: string; mutedText: string; radius: string; fontFamily: string; headingFamily: string; baseSize: string; density: "compact" | "comfortable"; motion: "full" | "reduced"; /** The host's code font, when it ships one. Deliberately absent from * DEFAULT_THEME_SLOTS — and therefore from SLOT_KEYS — because it has no * sensible neutral default: a host without a brand mono must fall through * to the system stack in `themeDefaults` rather than report a defaulted * slot or spend a model call. Derived after assembly, in `extractTheme`. */ monoFamily?: string; } export interface ThemeUncertainty { slot: keyof ThemeSlotValues; note: string; } export interface ThemeSummary { /** Fully resolved values used to assemble the frozen VendoTheme contract. */ slots: ThemeSlotValues; /** slot -> provenance: the exact token name, "(model)", or a derivation. */ matched: Record; /** Slots that fell back to neutral defaults (reported, never silent). */ defaulted: string[]; /** Model-flagged genuine uncertainty — init's only theme question trigger. */ uncertain: ThemeUncertainty[]; usedModel: boolean; errors: string[]; hasDarkVariant: boolean; /** Slots the exact allowlist pass did not read exactly — the staged theme * pass's `needed` input, and the only slots `applyThemeDraft` may fill. */ needed: SlotKey[]; /** The CSS/layout/tailwind-config paths the context gatherer collected, * repo-relative — seeded as evidence-path hints for the staged pass. */ evidencePaths: string[]; /** What `.vendo/fonts.css` ended up holding (embed-fonts.ts). Set by the * sync flow, not by extraction: resolving a face reads the build output and * can reach the network, and `extractTheme` does neither. */ fonts?: VendoThemeFont[]; } type SlotKey = keyof ThemeSlotValues; /** Brand-defining slots: any of these missing after the exact pass triggers * the staged theme pass, and only doubt about these becomes an init * question. The remaining slots (accentText, headingFamily, baseSize, * density, motion) derive or default safely — accentText derives from the * accent by WCAG contrast, headingFamily inherits fontFamily, and the rest * have safe brand-neutral defaults — so they never trigger a call or a * question on their own. */ export declare const BRAND_SLOTS: readonly SlotKey[]; export declare const modelThemeSchema: z.ZodObject<{ slots: z.ZodObject<{ accent: z.ZodOptional; accentText: z.ZodOptional; background: z.ZodOptional; border: z.ZodOptional; danger: z.ZodOptional; surface: z.ZodOptional; text: z.ZodOptional; mutedText: z.ZodOptional; radius: z.ZodOptional; fontFamily: z.ZodOptional; headingFamily: z.ZodOptional; monoFamily: z.ZodOptional; baseSize: z.ZodOptional; density: z.ZodOptional>; motion: z.ZodOptional>; }, "strip", z.ZodTypeAny, { text?: string | undefined; surface?: string | undefined; accent?: string | undefined; danger?: string | undefined; density?: "comfortable" | "compact" | undefined; fontFamily?: string | undefined; border?: string | undefined; background?: string | undefined; accentText?: string | undefined; headingFamily?: string | undefined; monoFamily?: string | undefined; baseSize?: string | undefined; radius?: string | undefined; motion?: "full" | "reduced" | undefined; mutedText?: string | undefined; }, { text?: string | undefined; surface?: string | undefined; accent?: string | undefined; danger?: string | undefined; density?: "comfortable" | "compact" | undefined; fontFamily?: string | undefined; border?: string | undefined; background?: string | undefined; accentText?: string | undefined; headingFamily?: string | undefined; monoFamily?: string | undefined; baseSize?: string | undefined; radius?: string | undefined; motion?: "full" | "reduced" | undefined; mutedText?: string | undefined; }>; uncertain: z.ZodOptional, "many">>; }, "strip", z.ZodTypeAny, { slots: { text?: string | undefined; surface?: string | undefined; accent?: string | undefined; danger?: string | undefined; density?: "comfortable" | "compact" | undefined; fontFamily?: string | undefined; border?: string | undefined; background?: string | undefined; accentText?: string | undefined; headingFamily?: string | undefined; monoFamily?: string | undefined; baseSize?: string | undefined; radius?: string | undefined; motion?: "full" | "reduced" | undefined; mutedText?: string | undefined; }; uncertain?: { slot: string; note: string; }[] | undefined; }, { slots: { text?: string | undefined; surface?: string | undefined; accent?: string | undefined; danger?: string | undefined; density?: "comfortable" | "compact" | undefined; fontFamily?: string | undefined; border?: string | undefined; background?: string | undefined; accentText?: string | undefined; headingFamily?: string | undefined; monoFamily?: string | undefined; baseSize?: string | undefined; radius?: string | undefined; motion?: "full" | "reduced" | undefined; mutedText?: string | undefined; }; uncertain?: { slot: string; note: string; }[] | undefined; }>; /** Deterministic validation of a proposed slot value (model or human). */ export declare function validateSlotValue(slot: SlotKey, raw: string): string | null; export declare function extractTheme(targetDir: string): Promise; /** * Merges a parsed theme-stage artifact (`modelThemeSchema`) onto an * exact-only `ThemeSummary` — the precedence law (kill-list §B2, Task 2): * exact reads are never overwritten; only `needed` slots may be filled; every * proposed value passes through `validateSlotValue` (invalid values are * ignored, the slot stays defaulted/derived); a model-provided accentText * stands; accentText re-derives by contrast only when the model filled * accent but not accentText and accentText itself wasn't an exact read; * headingFamily inherits fontFamily under the mirror condition. */ export declare function applyThemeDraft(summary: ThemeSummary, draft: z.infer): ThemeSummary; export {};