@omniharmonic/openspace-theme 0.0.0-stage → 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/color.ts","../src/compile.ts","../src/contrast.ts","../src/pairings.ts","../src/custom-fonts.ts","../src/type-scale.ts","../src/layout.ts","../src/vars.ts","../src/types.ts","../src/overrides.ts","../src/themes.ts","../src/scales.ts","../src/extract.ts","../src/palettes.ts","../src/index.ts"],"sourcesContent":["/**\n * Color math: OKLCH ⇄ OKLab ⇄ linear sRGB ⇄ sRGB (hex), CSS color parsing, and gamut mapping\n * by chroma reduction. Matrices from Björn Ottosson's OKLab reference and CSS Color 4.\n */\n\n/** OKLCH: lightness 0–1, chroma ≥ 0 (≈0–0.37 in sRGB), hue in degrees 0–360. */\nexport interface Oklch {\n l: number;\n c: number;\n h: number;\n}\n\n/** OKLab: lightness 0–1, a/b opponent axes. */\nexport interface Oklab {\n l: number;\n a: number;\n b: number;\n}\n\n/** RGB triple. Gamma-encoded sRGB or linear-light sRGB depending on context, channels 0–1. */\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nconst GAMUT_EPSILON = 1e-6;\n/** Below this chroma a color is treated as achromatic (hue is meaningless). */\nexport const ACHROMATIC_CHROMA = 1e-4;\n\n// --- transfer functions ---------------------------------------------------------------------\n\nexport function srgbChannelToLinear(v: number): number {\n const abs = Math.abs(v);\n const lin = abs <= 0.04045 ? abs / 12.92 : ((abs + 0.055) / 1.055) ** 2.4;\n return Math.sign(v) * lin;\n}\n\nexport function linearChannelToSrgb(v: number): number {\n const abs = Math.abs(v);\n const enc = abs <= 0.0031308 ? abs * 12.92 : 1.055 * abs ** (1 / 2.4) - 0.055;\n return Math.sign(v) * enc;\n}\n\nexport function srgbToLinear({ r, g, b }: Rgb): Rgb {\n return { r: srgbChannelToLinear(r), g: srgbChannelToLinear(g), b: srgbChannelToLinear(b) };\n}\n\nexport function linearToSrgb({ r, g, b }: Rgb): Rgb {\n return { r: linearChannelToSrgb(r), g: linearChannelToSrgb(g), b: linearChannelToSrgb(b) };\n}\n\n// --- OKLab ------------------------------------------------------------------------------------\n\nexport function linearSrgbToOklab({ r, g, b }: Rgb): Oklab {\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n return {\n l: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n };\n}\n\nexport function oklabToLinearSrgb({ l: L, a, b }: Oklab): Rgb {\n const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return {\n r: 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n g: -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n b: -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n };\n}\n\nexport function normalizeHue(h: number): number {\n const n = h % 360;\n return n < 0 ? n + 360 : n;\n}\n\nexport function oklabToOklch({ l, a, b }: Oklab): Oklch {\n const c = Math.sqrt(a * a + b * b);\n const h = c < ACHROMATIC_CHROMA ? 0 : normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n return { l, c, h };\n}\n\nexport function oklchToOklab({ l, c, h }: Oklch): Oklab {\n const rad = (h * Math.PI) / 180;\n return { l, a: c * Math.cos(rad), b: c * Math.sin(rad) };\n}\n\nexport function srgbToOklch(rgb: Rgb): Oklch {\n return oklabToOklch(linearSrgbToOklab(srgbToLinear(rgb)));\n}\n\n/** Unclamped sRGB (may fall outside 0–1 when the color is out of gamut). */\nexport function oklchToSrgb(color: Oklch): Rgb {\n return linearToSrgb(oklabToLinearSrgb(oklchToOklab(color)));\n}\n\n// --- gamut mapping ------------------------------------------------------------------------------\n\nexport function inSrgbGamut(color: Oklch): boolean {\n const { r, g, b } = oklabToLinearSrgb(oklchToOklab(color));\n return [r, g, b].every((v) => v >= -GAMUT_EPSILON && v <= 1 + GAMUT_EPSILON);\n}\n\n/**\n * Map an OKLCH color into sRGB by reducing chroma (hue and lightness preserved) — binary search\n * for the largest in-gamut chroma. Lightness is clamped to 0–1 first.\n */\nexport function gamutMap(color: Oklch): Oklch {\n const l = Math.min(1, Math.max(0, color.l));\n const base = { l, c: Math.max(0, color.c), h: normalizeHue(color.h) };\n if (l <= 0) return { l: 0, c: 0, h: base.h };\n if (l >= 1) return { l: 1, c: 0, h: base.h };\n if (inSrgbGamut(base)) return base;\n let lo = 0;\n let hi = base.c;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (inSrgbGamut({ ...base, c: mid })) lo = mid;\n else hi = mid;\n }\n return { ...base, c: lo };\n}\n\nconst clamp01 = (v: number) => Math.min(1, Math.max(0, v));\n\n/** Gamut-mapped, clamped sRGB (0–1 channels). */\nexport function oklchToSrgbInGamut(color: Oklch): Rgb {\n const { r, g, b } = oklchToSrgb(gamutMap(color));\n return { r: clamp01(r), g: clamp01(g), b: clamp01(b) };\n}\n\n// --- hex -----------------------------------------------------------------------------------------\n\nconst hex2 = (v: number) =>\n Math.round(clamp01(v) * 255)\n .toString(16)\n .padStart(2, \"0\");\n\n/** sRGB (0–1) → lowercase `#rrggbb`. */\nexport function rgbToHex({ r, g, b }: Rgb): string {\n return `#${hex2(r)}${hex2(g)}${hex2(b)}`;\n}\n\n/** `#rgb`, `#rgba`, `#rrggbb` or `#rrggbbaa` → sRGB (alpha ignored). */\nexport function hexToRgb(hex: string): Rgb {\n const m = /^#?([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(hex.trim());\n if (!m?.[1]) throw new Error(`Invalid hex color: ${hex}`);\n let h = m[1];\n if (h.length <= 4) h = [...h].map((ch) => ch + ch).join(\"\");\n const n = (i: number) => Number.parseInt(h.slice(i, i + 2), 16) / 255;\n return { r: n(0), g: n(2), b: n(4) };\n}\n\n/** OKLCH → gamut-mapped `#rrggbb`. */\nexport function oklchToHex(color: Oklch): string {\n return rgbToHex(oklchToSrgbInGamut(color));\n}\n\nexport function hexToOklch(hex: string): Oklch {\n return srgbToOklch(hexToRgb(hex));\n}\n\n// --- CSS parsing -----------------------------------------------------------------------------\n\n/** Parse a number with optional `%` against a reference value for 100%. */\nfunction num(token: string, percentRef: number): number {\n const t = token.trim().toLowerCase();\n if (t === \"none\") return 0;\n if (t.endsWith(\"%\")) return (Number.parseFloat(t) / 100) * percentRef;\n const v = Number.parseFloat(t);\n if (!Number.isFinite(v)) throw new Error(`Invalid number: ${token}`);\n return v;\n}\n\nfunction hue(token: string): number {\n const t = token.trim().toLowerCase();\n if (t === \"none\") return 0;\n const v = Number.parseFloat(t);\n if (!Number.isFinite(v)) throw new Error(`Invalid hue: ${token}`);\n if (t.endsWith(\"turn\")) return normalizeHue(v * 360);\n if (t.endsWith(\"grad\")) return normalizeHue(v * 0.9);\n if (t.endsWith(\"rad\")) return normalizeHue((v * 180) / Math.PI);\n return normalizeHue(v);\n}\n\n/** Split CSS function arguments (`a b c / alpha` or `a, b, c, alpha`); alpha is dropped. */\nfunction args(body: string): string[] {\n const noAlpha = body.split(\"/\")[0] ?? \"\";\n const parts = noAlpha\n .split(/[\\s,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n return parts.slice(0, 3);\n}\n\n// CIELAB (D50) → linear sRGB (CSS Color 4 matrices).\nconst D50 = [0.3457 / 0.3585, 1, (1 - 0.3457 - 0.3585) / 0.3585] as const;\nfunction labToLinearSrgb(L: number, a: number, b: number): Rgb {\n const k = 24389 / 27;\n const e = 216 / 24389;\n const fy = (L + 16) / 116;\n const fx = a / 500 + fy;\n const fz = fy - b / 200;\n const xr = fx ** 3 > e ? fx ** 3 : (116 * fx - 16) / k;\n const yr = L > k * e ? fy ** 3 : L / k;\n const zr = fz ** 3 > e ? fz ** 3 : (116 * fz - 16) / k;\n const x50 = xr * D50[0];\n const y50 = yr * D50[1];\n const z50 = zr * D50[2];\n const x = 0.955473421488075 * x50 - 0.02309845494876471 * y50 + 0.06325924320057072 * z50;\n const y = -0.0283697093338637 * x50 + 1.0099953980813041 * y50 + 0.021041441191917323 * z50;\n const z = 0.012314014864481998 * x50 - 0.020507649298898964 * y50 + 1.330365926242124 * z50;\n return {\n r: 3.2409699419045226 * x - 1.537383177570094 * y - 0.4986107602930034 * z,\n g: -0.9692436362808796 * x + 1.8759675015077202 * y + 0.04155505740717559 * z,\n b: 0.05563007969699366 * x - 0.20397695888897652 * y + 1.0569715142428786 * z,\n };\n}\n\nfunction hslToRgb(h: number, s: number, l: number): Rgb {\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n const a = s * Math.min(l, 1 - l);\n return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));\n };\n return { r: f(0), g: f(8), b: f(4) };\n}\n\n/**\n * Parse a CSS color (hex, `oklch()`, `oklab()`, `rgb()/rgba()`, `hsl()/hsla()`, `lab()`, `lch()`)\n * into OKLCH. Out-of-gamut inputs are kept as-is; map with {@link gamutMap} before display.\n */\nexport function parseColor(input: string): Oklch {\n const s = input.trim().toLowerCase();\n if (s.startsWith(\"#\")) return hexToOklch(s);\n const m = /^([a-z]+)\\(([^()]*)\\)$/.exec(s);\n if (!m?.[1] || m[2] === undefined) throw new Error(`Unsupported color: ${input}`);\n const fn = m[1];\n const parts = args(m[2]);\n if (parts.length !== 3) throw new Error(`Expected 3 components: ${input}`);\n const [p0, p1, p2] = parts as [string, string, string];\n switch (fn) {\n case \"oklch\":\n return { l: num(p0, 1), c: Math.max(0, num(p1, 0.4)), h: hue(p2) };\n case \"oklab\":\n return oklabToOklch({ l: num(p0, 1), a: num(p1, 0.4), b: num(p2, 0.4) });\n case \"rgb\":\n case \"rgba\":\n return srgbToOklch({ r: num(p0, 255) / 255, g: num(p1, 255) / 255, b: num(p2, 255) / 255 });\n case \"hsl\":\n case \"hsla\":\n return srgbToOklch(hslToRgb(hue(p0), num(p1, 100) / 100, num(p2, 100) / 100));\n case \"lab\":\n return oklabToOklch(\n linearSrgbToOklab(labToLinearSrgb(num(p0, 100), num(p1, 125), num(p2, 125))),\n );\n case \"lch\": {\n const L = num(p0, 100);\n const C = num(p1, 150);\n const H = (hue(p2) * Math.PI) / 180;\n return oklabToOklch(linearSrgbToOklab(labToLinearSrgb(L, C * Math.cos(H), C * Math.sin(H))));\n }\n default:\n throw new Error(`Unsupported color function: ${fn}()`);\n }\n}\n\n/** True when {@link parseColor} accepts the input. */\nexport function isColor(input: string): boolean {\n try {\n parseColor(input);\n return true;\n } catch {\n return false;\n }\n}\n\nconst round = (v: number, digits: number) => {\n const f = 10 ** digits;\n const r = Math.round(v * f) / f;\n return Object.is(r, -0) ? 0 : r;\n};\n\n/** Format as a CSS `oklch()` string, e.g. `oklch(0.62 0.09 145)`. */\nexport function formatOklch({ l, c, h }: Oklch): string {\n const cc = round(c, 4);\n return `oklch(${round(l, 4)} ${cc} ${cc === 0 ? 0 : round(h, 2)})`;\n}\n\n/** Any CSS color → gamut-mapped `#rrggbb`. */\nexport function toHex(input: string | Oklch): string {\n return oklchToHex(typeof input === \"string\" ? parseColor(input) : input);\n}\n\n/** Shortest-path interpolation between two hues (t = 0 → a, 1 → b). */\nexport function mixHue(a: number, b: number, t: number): number {\n const d = ((((b - a) % 360) + 540) % 360) - 180;\n return normalizeHue(a + d * t);\n}\n\n/** Euclidean distance in OKLab (ΔE_OK). */\nexport function deltaEOK(x: Oklch, y: Oklch): number {\n const a = oklchToOklab(x);\n const b = oklchToOklab(y);\n return Math.hypot(a.l - b.l, a.a - b.a, a.b - b.b);\n}\n","import {\n COLOR_ROLES,\n COLOR_SCALE_STEPS,\n COLOR_THEMES,\n type ColorTheme,\n type StyleChoices,\n type Styles,\n} from \"@omniharmonic/openspace-schema\";\nimport { formatOklch, type Oklch, oklchToHex, parseColor } from \"./color\";\nimport {\n auditContrast,\n type ContrastFailure,\n type ContrastMode,\n relativeLuminance,\n type ThemeColorSet,\n} from \"./contrast\";\nimport { chosenCustomFont, customFontStack, nearestWeight } from \"./custom-fonts\";\nimport {\n BUTTON_ROLES,\n buttonTokens,\n IMAGE_TREATMENT_VALUES,\n MOTION_VALUES,\n radiusTokens,\n SHADOW_VALUES,\n sectionTokens,\n spaceTokens,\n WIDTH_TOKENS,\n} from \"./layout\";\nimport { dtcgToCss, flattenDtcg, SOLE_ALIAS_RE } from \"./overrides\";\nimport {\n DEFAULT_PAIRING_ID,\n fontsourceCss,\n getPairing,\n googleFontsUrl,\n type TypePairing,\n} from \"./pairings\";\nimport {\n accentStates,\n buildPalette,\n type ContrastAdjustment,\n onColor,\n type Palette,\n solveThemes,\n themeRoles,\n} from \"./themes\";\nimport { fontTokens, TYPE_PRESET_NAMES, typeScale } from \"./type-scale\";\nimport { type ColorRole, type ColorScale, STATE_ROLES, type ThemeRole } from \"./types\";\nimport { imageTreatmentClass, THEME_CLASSES, themeClass, varName } from \"./vars\";\n\nexport interface CompileWarning {\n code:\n | \"invalid-brand\"\n | \"unknown-pairing\"\n | \"invalid-override\"\n | \"custom-token\"\n | \"contrast-adjusted\"\n | \"contrast-failure\";\n path?: string;\n message: string;\n}\n\nexport interface CompileOptions {\n /**\n * Run the contrast solver (default `true`). With `false`, colors ship exactly as chosen and\n * overridden, and `contrast.failures` lists what fails — what Studio shows before the\n * one-click \"nearest accessible\" fix.\n */\n solve?: boolean;\n}\n\nexport interface ThemeTokens {\n choices: StyleChoices;\n pairing: TypePairing;\n palette: {\n brand: string;\n brandOklch: string;\n accent: ColorScale<string>;\n neutral: ColorScale<string>;\n };\n /** Final role colors (`#rrggbb`) per section theme. */\n themes: ThemeColorSet;\n fonts: { googleFontsUrl: string; fontsource: string[] };\n /** Every emitted custom property, by where it is declared. */\n vars: {\n root: Record<string, string>;\n themes: Record<ColorTheme, Record<string, string>>;\n /** Declared on `:root` and every theme class so `var()` references resolve per section. */\n themed: Record<string, string>;\n imageTreatments: Record<string, Record<string, string>>;\n reducedMotion: Record<string, string>;\n };\n}\n\nexport interface CompiledStyles {\n tokens: ThemeTokens;\n css: string;\n contrast: { mode: ContrastMode; adjustments: ContrastAdjustment[]; failures: ContrastFailure[] };\n warnings: CompileWarning[];\n}\n\nconst FALLBACK_BRAND = \"oklch(0.55 0.12 250)\";\nconst COLOR_THEME_SET = new Set<string>(COLOR_THEMES);\nconst COLOR_ROLE_SET = new Set<string>(COLOR_ROLES);\n/** Override scope that targets every section theme: `color.all.<role>`. */\nexport const ALL_THEMES = \"all\";\nconst THEME_ROLES: readonly ThemeRole[] = [...COLOR_ROLES, ...STATE_ROLES];\n\nfunction scaleHex(scale: ColorScale<Oklch>): ColorScale<string> {\n const out = {} as ColorScale<string>;\n for (const step of COLOR_SCALE_STEPS) out[step] = oklchToHex(scale[step]);\n return out;\n}\n\n/** Resolve a theme color override value to a concrete color (aliases to the palette allowed). */\nfunction overrideColor(\n raw: unknown,\n palette: Palette,\n roles: Record<ColorRole, Oklch>,\n): Oklch | null {\n if (typeof raw !== \"string\") return null;\n const alias = SOLE_ALIAS_RE.exec(raw.trim());\n if (alias?.[1]) {\n const [group, name] = alias[1].split(\".\");\n if (group !== \"color\" || !name) return null;\n if (name === \"brand\") return palette.brand;\n const m = /^(accent|neutral)-(\\d+)$/.exec(name);\n if (m) {\n const scale = m[1] === \"accent\" ? palette.accent : palette.neutral;\n return (scale as Record<number, Oklch>)[Number(m[2])] ?? null;\n }\n return COLOR_ROLE_SET.has(name) ? roles[name as ColorRole] : null;\n }\n try {\n return parseColor(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Compile `content/styles.json` into the full token set and the site's token stylesheet.\n *\n * Override paths (DTCG):\n * - `color.all.<role>`: the role in **every** section theme;\n * - `color.<role>`: the role in the default (light) theme only;\n * - `color.<theme>.<role>`: the role in one section theme.\n * Precedence is theme > light > all. All three apply before the contrast solver runs; an\n * overridden `accent` gets a freshly picked `accent-text` unless that is overridden too, and\n * `accent-hover`/`accent-pressed` are always derived from the final accent.\n * - `color.accent-500` / `color.neutral-200` / `color.brand` replace scale variables.\n * - Every other path maps to `--os-<path>` (see `vars.ts`), e.g. `type.display.letterSpacing`.\n */\nexport function compileStyles(styles: Styles, options: CompileOptions = {}): CompiledStyles {\n const { choices } = styles;\n const warnings: CompileWarning[] = [];\n const mode: ContrastMode = choices.palette.contrast ?? \"standard\";\n\n // --- palette ---\n let brand: Oklch;\n try {\n brand = parseColor(choices.palette.brand);\n } catch {\n warnings.push({\n code: \"invalid-brand\",\n path: \"choices.palette.brand\",\n message: `Could not read brand color \"${choices.palette.brand}\"; using ${FALLBACK_BRAND}.`,\n });\n brand = parseColor(FALLBACK_BRAND);\n }\n const palette = buildPalette(brand, choices.palette.neutral);\n\n // --- pairing ---\n let pairing = getPairing(choices.pairing);\n if (!pairing) {\n warnings.push({\n code: \"unknown-pairing\",\n path: \"choices.pairing\",\n message: `Unknown type pairing \"${choices.pairing}\"; using \"${DEFAULT_PAIRING_ID}\".`,\n });\n pairing = getPairing(DEFAULT_PAIRING_ID) as TypePairing;\n }\n\n // --- token maps (insertion order = output order) ---\n const accentHex = scaleHex(palette.accent);\n const neutralHex = scaleHex(palette.neutral);\n const root = new Map<string, string>();\n root.set(varName(\"color\", \"brand\"), oklchToHex(palette.brand));\n for (const step of COLOR_SCALE_STEPS) root.set(varName(\"color\", \"accent\", step), accentHex[step]);\n for (const step of COLOR_SCALE_STEPS)\n root.set(varName(\"color\", \"neutral\", step), neutralHex[step]);\n\n const fonts = fontTokens(pairing);\n // Uploaded fonts replace the pairing's heading and/or body family (PRD §5.1).\n const headingFont = chosenCustomFont(styles, choices.headingFont);\n if (headingFont) {\n fonts.heading = customFontStack(headingFont);\n fonts[\"weight-heading\"] = String(nearestWeight(headingFont, pairing.headingWeight));\n }\n const bodyFont = chosenCustomFont(styles, choices.bodyFont);\n if (bodyFont) {\n fonts.body = customFontStack(bodyFont);\n fonts[\"weight-body\"] = String(nearestWeight(bodyFont, pairing.bodyWeight));\n fonts[\"weight-strong\"] = String(nearestWeight(bodyFont, pairing.strongWeight));\n }\n for (const [k, v] of Object.entries(fonts)) root.set(varName(\"font\", k), v);\n const type = typeScale(pairing);\n for (const preset of TYPE_PRESET_NAMES) {\n for (const [prop, v] of Object.entries(type[preset]))\n root.set(varName(\"type\", preset, prop), v);\n }\n root.set(varName(\"measure\"), \"70ch\");\n for (const [k, v] of Object.entries(spaceTokens(choices.density)))\n root.set(varName(\"space\", k), v);\n for (const [k, v] of Object.entries(sectionTokens(choices.density)))\n root.set(varName(\"section\", k), v);\n for (const [k, v] of Object.entries(WIDTH_TOKENS)) root.set(varName(\"width\", k), v);\n for (const [k, v] of Object.entries(radiusTokens(choices.shape)))\n root.set(varName(\"radius\", k), v);\n for (const [k, v] of Object.entries(SHADOW_VALUES)) root.set(varName(\"shadow\", k), v);\n for (const [k, v] of Object.entries(MOTION_VALUES[choices.motion]))\n root.set(varName(\"motion\", k), v);\n\n const themed = new Map<string, string>();\n const buttons = buttonTokens(choices.buttons);\n for (const role of BUTTON_ROLES) {\n for (const [prop, v] of Object.entries(buttons[role]))\n themed.set(varName(\"button\", role, prop), v);\n }\n for (const [k, v] of Object.entries(IMAGE_TREATMENT_VALUES[choices.imageTreatment]))\n themed.set(varName(\"image\", k), v);\n\n // --- overrides ---\n const roles = themeRoles(palette);\n const custom = new Map<string, string>();\n /** `theme:role` → the override path that set it. */\n const overriddenRoles = new Map<string, string>();\n const roleOverrides: {\n tier: number;\n scope: string;\n role: ColorRole;\n dotted: string;\n value: unknown;\n }[] = [];\n for (const { path, token, type: t } of flattenDtcg(styles.overrides)) {\n const dotted = path.join(\".\");\n const invalid = (why: string) =>\n warnings.push({ code: \"invalid-override\", path: dotted, message: why });\n\n if (path[0] === \"color\") {\n const [, a, b] = path;\n const scope =\n path.length === 3 && a && (a === ALL_THEMES || COLOR_THEME_SET.has(a)) ? a : null;\n const role = scope ? b : path.length === 2 ? a : undefined;\n if (role && COLOR_ROLE_SET.has(role)) {\n // Precedence: `color.<theme>.<role>` > `color.<role>` (light) > `color.all.<role>`.\n const tier = scope === ALL_THEMES ? 0 : scope ? 2 : 1;\n roleOverrides.push({\n tier,\n scope: scope ?? \"light\",\n role: role as ColorRole,\n dotted,\n value: token.$value,\n });\n continue;\n }\n }\n\n // Composite typography token: expand into per-property vars.\n if (t === \"typography\" && typeof token.$value === \"object\" && token.$value !== null) {\n for (const [prop, sub] of Object.entries(token.$value as Record<string, unknown>).sort()) {\n const subType =\n prop === \"fontFamily\" ? \"fontFamily\" : prop === \"fontSize\" ? \"dimension\" : undefined;\n const css = dtcgToCss(sub as never, subType);\n if (css === null) invalid(`Unsupported value for ${prop}.`);\n else applyVar(varName(...path, prop), css);\n }\n continue;\n }\n\n const colorPath = path[0] === \"color\";\n const css = dtcgToCss(token.$value, t ?? (colorPath ? \"color\" : undefined));\n if (css === null) {\n invalid(`Unsupported or unsafe value ${JSON.stringify(token.$value)}.`);\n continue;\n }\n applyVar(varName(...path), css);\n }\n\n function applyVar(name: string, css: string) {\n if (root.has(name)) root.set(name, css);\n else if (themed.has(name)) themed.set(name, css);\n else {\n custom.set(name, css);\n warnings.push({\n code: \"custom-token\",\n path: name,\n message: `${name} is not a built-in token; emitted as a custom property.`,\n });\n }\n }\n for (const name of [...custom.keys()].sort()) root.set(name, custom.get(name) as string);\n for (const o of roleOverrides.sort((x, y) => x.tier - y.tier)) {\n const targets = o.scope === ALL_THEMES ? COLOR_THEMES : [o.scope as ColorTheme];\n for (const target of targets) {\n const color = overrideColor(o.value, palette, roles[target]);\n if (!color) {\n warnings.push({\n code: \"invalid-override\",\n path: o.dotted,\n message: `\"${String(o.value)}\" is not a color.`,\n });\n break;\n }\n roles[target][o.role] = color;\n overriddenRoles.set(`${target}:${o.role}`, o.dotted);\n }\n }\n // A new accent gets a fresh label color unless that was overridden too.\n for (const theme of COLOR_THEMES) {\n if (overriddenRoles.has(`${theme}:accent`) && !overriddenRoles.has(`${theme}:accent-text`)) {\n roles[theme][\"accent-text\"] = onColor(roles[theme].accent, palette);\n }\n }\n\n // --- contrast ---\n let themes: ThemeColorSet;\n let adjustments: ContrastAdjustment[] = [];\n if (options.solve === false) {\n themes = {} as ThemeColorSet;\n for (const theme of COLOR_THEMES) {\n const set = roles[theme];\n const all = { ...set, ...accentStates(set.accent, set[\"accent-text\"]) };\n const out = {} as Record<ThemeRole, string>;\n for (const role of THEME_ROLES) out[role] = oklchToHex(all[role]);\n themes[theme] = out;\n }\n } else {\n ({ themes, adjustments } = solveThemes(roles, mode));\n }\n const failures = auditContrast(themes, { contrast: mode });\n for (const a of adjustments) {\n const path = overriddenRoles.get(`${a.theme}:${a.role}`);\n if (!path) continue;\n warnings.push({\n code: \"contrast-adjusted\",\n path,\n message: `Override ${a.from} adjusted to ${a.to} to reach ${a.required}:1 against ${a.against} (${a.theme}).`,\n });\n }\n for (const f of failures) {\n warnings.push({\n code: \"contrast-failure\",\n path: `${f.theme}.${f.fg}/${f.bg}`,\n message: `${f.fg} on ${f.bg} is ${f.ratio}:1 in ${f.theme}; needs ${f.required}:1 (try ${f.suggestion}).`,\n });\n }\n\n const themeVars = {} as Record<ColorTheme, Record<string, string>>;\n for (const theme of COLOR_THEMES) {\n const vars: Record<string, string> = {};\n for (const role of THEME_ROLES) vars[varName(\"color\", role)] = themes[theme][role];\n themeVars[theme] = vars;\n }\n\n const imageTreatments: Record<string, Record<string, string>> = {};\n for (const [treatment, values] of Object.entries(IMAGE_TREATMENT_VALUES)) {\n imageTreatments[treatment] = Object.fromEntries(\n Object.entries(values).map(([k, v]) => [varName(\"image\", k), v]),\n );\n }\n const reducedMotion = Object.fromEntries(\n Object.entries(MOTION_VALUES.none)\n .filter(([k]) => k !== \"ease\")\n .map(([k, v]) => [varName(\"motion\", k), v]),\n );\n\n const tokens: ThemeTokens = {\n choices,\n pairing,\n palette: {\n brand: oklchToHex(palette.brand),\n brandOklch: formatOklch(palette.brand),\n accent: accentHex,\n neutral: neutralHex,\n },\n themes,\n fonts: { googleFontsUrl: googleFontsUrl(pairing), fontsource: fontsourceCss(pairing) },\n vars: {\n root: Object.fromEntries(root),\n themes: themeVars,\n themed: Object.fromEntries(themed),\n imageTreatments,\n reducedMotion,\n },\n };\n\n return {\n tokens,\n css: emitCss(tokens),\n contrast: { mode, adjustments, failures },\n warnings,\n };\n}\n\nfunction block(selectors: string[], decls: Record<string, string>, indent = \"\"): string {\n const lines = Object.entries(decls).map(([k, v]) => `${indent} ${k}: ${v};`);\n return `${indent}${selectors.join(`,\\n${indent}`)} {\\n${lines.join(\"\\n\")}\\n${indent}}`;\n}\n\n/** Deterministic token stylesheet. */\nexport function emitCss(tokens: ThemeTokens): string {\n const parts: string[] = [\n \"/* OpenSpace design tokens. Generated by @omniharmonic/openspace-theme from content/styles.json; do not edit. */\",\n block([\":root\"], tokens.vars.root),\n ];\n for (const theme of COLOR_THEMES) {\n const scheme = relativeLuminance(tokens.themes[theme].background) > 0.18 ? \"light\" : \"dark\";\n const selectors =\n theme === \"light\" ? [\":root\", `.${themeClass(theme)}`] : [`.${themeClass(theme)}`];\n parts.push(block(selectors, { \"color-scheme\": scheme, ...tokens.vars.themes[theme] }));\n }\n parts.push(block([\":root\", ...THEME_CLASSES.map((c) => `.${c}`)], tokens.vars.themed));\n for (const [treatment, decls] of Object.entries(tokens.vars.imageTreatments)) {\n parts.push(block([`.${imageTreatmentClass(treatment)}`], decls));\n }\n parts.push(\n `@media (prefers-reduced-motion: reduce) {\\n${block([\":root\"], tokens.vars.reducedMotion, \" \")}\\n}`,\n );\n return `${parts.join(\"\\n\\n\")}\\n`;\n}\n","import { COLOR_THEMES, type ColorTheme } from \"@omniharmonic/openspace-schema\";\nimport { gamutMap, hexToRgb, type Oklch, oklchToHex, parseColor, srgbToLinear } from \"./color\";\nimport type { ColorRole, ThemeRole } from \"./types\";\n\n/** WCAG 2.x relative luminance of an sRGB color (0 = black, 1 = white). */\nexport function relativeLuminance(color: string | Oklch): number {\n const hex = typeof color === \"string\" ? toHexStrict(color) : oklchToHex(color);\n const { r, g, b } = srgbToLinear(hexToRgb(hex));\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/** WCAG 2.x contrast ratio, 1–21. Colors are gamut-mapped and quantized to 8-bit sRGB first. */\nexport function contrastRatio(a: string | Oklch, b: string | Oklch): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const [hi, lo] = la > lb ? [la, lb] : [lb, la];\n return (hi + 0.05) / (lo + 0.05);\n}\n\nfunction toHexStrict(color: string): string {\n return /^#[0-9a-f]{6}$/i.test(color) ? color.toLowerCase() : oklchToHex(parseColor(color));\n}\n\n/** Contrast levels: `body` text, or `large` text and UI components (WCAG 1.4.3 / 1.4.11). */\nexport type ContrastLevel = \"body\" | \"large\";\nexport type ContrastMode = \"standard\" | \"high\";\n\n/** Minimum ratios. `standard` = WCAG 2.2 AA; `high` = AAA (7:1 body, 4.5:1 large/UI). */\nexport const CONTRAST_MINIMUMS: Record<ContrastMode, Record<ContrastLevel, number>> = {\n standard: { body: 4.5, large: 3 },\n high: { body: 7, large: 4.5 },\n};\n\nexport interface ContrastPair {\n fg: ThemeRole;\n bg: ThemeRole;\n level: ContrastLevel;\n /** Which side the solver moves (default `fg`). State colors are always the side that moves. */\n adjust?: \"fg\" | \"bg\";\n}\n\nconst BACKGROUNDS = [\"background\", \"surface\", \"surface-raised\"] as const;\nconst onAll = (fg: ColorRole, level: ContrastLevel): ContrastPair[] =>\n BACKGROUNDS.map((bg) => ({ fg, bg, level }));\n\n/**\n * Every role pair that must meet contrast in every section theme. Order matters to the solver:\n * `accent` is settled against the backgrounds before `accent-text` is settled against `accent`.\n * `border` is decorative (inputs use `text-muted`-strength outlines) and is not checked.\n * The last four pairs cover the button hover/pressed fills ({@link STATE_PAIRS}).\n */\nexport const CORE_CONTRAST_PAIRS: readonly ContrastPair[] = [\n ...onAll(\"text\", \"body\"),\n ...onAll(\"heading\", \"body\"),\n ...onAll(\"text-muted\", \"body\"),\n ...onAll(\"link\", \"body\"),\n { fg: \"accent\", bg: \"background\", level: \"large\" },\n { fg: \"accent\", bg: \"surface\", level: \"large\" },\n { fg: \"accent\", bg: \"surface-raised\", level: \"large\" },\n { fg: \"accent-text\", bg: \"accent\", level: \"body\" },\n ...onAll(\"focus\", \"large\"),\n ...onAll(\"success\", \"body\"),\n ...onAll(\"warning\", \"body\"),\n ...onAll(\"danger\", \"body\"),\n];\n\n/** Button hover/pressed fills: labels stay legible and the fill stays visible as UI. */\nexport const STATE_PAIRS: readonly ContrastPair[] = [\n { fg: \"accent-text\", bg: \"accent-hover\", level: \"body\", adjust: \"bg\" },\n { fg: \"accent-text\", bg: \"accent-pressed\", level: \"body\", adjust: \"bg\" },\n { fg: \"accent-hover\", bg: \"background\", level: \"large\" },\n { fg: \"accent-pressed\", bg: \"background\", level: \"large\" },\n];\n\nexport const CONTRAST_PAIRS: readonly ContrastPair[] = [...CORE_CONTRAST_PAIRS, ...STATE_PAIRS];\n\nexport type ThemeColors = Record<ThemeRole, string>;\nexport type ThemeColorSet = Record<ColorTheme, ThemeColors>;\n\nexport interface ContrastFailure {\n theme: ColorTheme;\n fg: ThemeRole;\n bg: ThemeRole;\n fgColor: string;\n bgColor: string;\n ratio: number;\n required: number;\n level: ContrastLevel;\n /** Nearest accessible replacement (lightness-only) for the side the solver adjusts: `fg`, or `bg` for state fills. */\n suggestion: string;\n}\n\n/** List every failing text/background pair across the given themes. */\nexport function auditContrast(\n themes: Partial<ThemeColorSet>,\n options: { contrast?: ContrastMode } = {},\n): ContrastFailure[] {\n const mins = CONTRAST_MINIMUMS[options.contrast ?? \"standard\"];\n const failures: ContrastFailure[] = [];\n for (const theme of COLOR_THEMES) {\n const colors = themes[theme];\n if (!colors) continue;\n for (const { fg, bg, level, adjust } of CONTRAST_PAIRS) {\n const fgColor = colors[fg] as string | undefined;\n const bgColor = colors[bg] as string | undefined;\n if (fgColor === undefined || bgColor === undefined) continue;\n const required = mins[level];\n const ratio = contrastRatio(fgColor, bgColor);\n if (ratio < required) {\n failures.push({\n theme,\n fg,\n bg,\n level,\n fgColor,\n bgColor,\n ratio: Math.round(ratio * 100) / 100,\n required,\n suggestion:\n adjust === \"bg\"\n ? nearestAccessible(bgColor, fgColor, required)\n : nearestAccessible(fgColor, bgColor, required),\n });\n }\n }\n }\n return failures;\n}\n\n/** Safety margin the solver aims above the minimum so rounding never tips a pair under. */\nconst SOLVER_MARGIN = 0.03;\n\nfunction withL(color: Oklch, l: number): Oklch {\n return gamutMap({ ...color, l });\n}\n\n/**\n * Lightness-only search: the color closest in lightness to `color` (same hue, chroma reduced only\n * as the gamut requires) that reaches `min` contrast against `against`. Returns `null` when even\n * the darkest/lightest end of the line can't reach `min`. `direction` restricts the search to\n * moving darker or lighter.\n */\nexport type Direction = \"darker\" | \"lighter\" | \"either\";\n\nexport function solveLightness(\n color: Oklch,\n against: Oklch | string,\n min: number,\n direction: Direction = \"either\",\n): Oklch | null {\n const bg = typeof against === \"string\" ? parseColor(against) : against;\n const target = min + SOLVER_MARGIN;\n const start = gamutMap(color);\n if (contrastRatio(start, bg) >= target) return start;\n let best: Oklch | null = null;\n let bestDelta = Number.POSITIVE_INFINITY;\n const ends = direction === \"darker\" ? [0] : direction === \"lighter\" ? [1] : [0, 1];\n for (const end of ends) {\n if (contrastRatio(withL(start, end), bg) < target) continue;\n // Binary search the boundary between start.l (fails) and end (passes).\n let fail = start.l;\n let pass = end;\n for (let i = 0; i < 24; i++) {\n const mid = (fail + pass) / 2;\n if (contrastRatio(withL(start, mid), bg) >= target) pass = mid;\n else fail = mid;\n }\n const delta = Math.abs(pass - start.l);\n if (delta < bestDelta) {\n bestDelta = delta;\n best = withL(start, pass);\n }\n }\n return best;\n}\n\n/**\n * Nearest accessible version of `color` against `against`: same hue, lightness moved the least\n * distance needed to reach `min` (default 4.5:1). Falls back to the higher-contrast extreme.\n * Returns `#rrggbb`.\n */\nexport function nearestAccessible(color: string, against: string, min = 4.5): string {\n const fg = parseColor(color);\n const solved = solveLightness(fg, against, min);\n if (solved) return oklchToHex(solved);\n const dark = withL(fg, 0);\n const light = withL(fg, 1);\n return oklchToHex(contrastRatio(dark, against) >= contrastRatio(light, against) ? dark : light);\n}\n","/**\n * Curated type pairings (doc 04 §4.1). Every family is SIL Open Font License, available from\n * Google Fonts and Fontsource (self-hosted at build time — no third-party font requests).\n */\n\nexport type FontCategory = \"serif\" | \"sans-serif\" | \"monospace\";\n\nexport interface FontFamilySpec {\n /** CSS / Google Fonts family name. */\n family: string;\n category: FontCategory;\n /** Weights to load (ascending). */\n weights: number[];\n /** Load italics for these weights too. */\n italic?: boolean;\n /** Fontsource package id (`@fontsource/<id>`); derived from the family name when omitted. */\n fontsourceId?: string;\n /** The family has an optical-size axis (`font-optical-sizing: auto` is meaningful). */\n opticalSize?: boolean;\n}\n\nexport interface TypePairing {\n id: string;\n name: string;\n heading: FontFamilySpec;\n body: FontFamilySpec;\n /** Weight for display/h1–h4. */\n headingWeight: number;\n /** Weight for running text. */\n bodyWeight: number;\n /** Weight for `<strong>`, buttons and nav. */\n strongWeight: number;\n /** Tracking for large headings (display, h1, h2); smaller headings get half. */\n headingTracking: string;\n /** Uppercase eyebrow tracking. */\n eyebrowTracking: string;\n /** Mood keywords for Studio's pairing picker. */\n mood: string[];\n /** Launch template that uses this pairing (doc 04 §7). */\n template?: string;\n}\n\n/** System fallback stacks by category (appended after the web font). */\nexport const FALLBACK_STACKS: Record<FontCategory, string[]> = {\n serif: [\"ui-serif\", \"Georgia\", \"Cambria\", '\"Times New Roman\"', \"Times\", \"serif\"],\n \"sans-serif\": [\n \"ui-sans-serif\",\n \"system-ui\",\n \"-apple-system\",\n '\"Segoe UI\"',\n \"Roboto\",\n '\"Helvetica Neue\"',\n \"Arial\",\n \"sans-serif\",\n ],\n monospace: [\n \"ui-monospace\",\n \"SFMono-Regular\",\n \"Menlo\",\n \"Consolas\",\n '\"Liberation Mono\"',\n \"monospace\",\n ],\n};\n\nconst serif = (\n family: string,\n weights: number[],\n extra: Partial<FontFamilySpec> = {},\n): FontFamilySpec => ({ family, category: \"serif\", weights, ...extra });\nconst sans = (\n family: string,\n weights: number[],\n extra: Partial<FontFamilySpec> = {},\n): FontFamilySpec => ({ family, category: \"sans-serif\", weights, ...extra });\n\nfunction pairing(\n p: Omit<TypePairing, \"bodyWeight\" | \"strongWeight\" | \"eyebrowTracking\"> &\n Partial<Pick<TypePairing, \"bodyWeight\" | \"strongWeight\" | \"eyebrowTracking\">>,\n): TypePairing {\n return { bodyWeight: 400, strongWeight: 600, eyebrowTracking: \"0.12em\", ...p };\n}\n\nexport const TYPE_PAIRINGS: readonly TypePairing[] = [\n // --- the twelve launch-template pairings (doc 04 §7) ---\n pairing({\n id: \"fraunces-hanken\",\n name: \"Fraunces & Hanken Grotesk\",\n heading: serif(\"Fraunces\", [400, 500, 600], { italic: true, opticalSize: true }),\n body: sans(\"Hanken Grotesk\", [400, 500, 600]),\n headingWeight: 400,\n headingTracking: \"-0.02em\",\n mood: [\"calm\", \"organic\", \"warm\"],\n template: \"meadow\",\n }),\n pairing({\n id: \"newsreader-public-sans\",\n name: \"Newsreader & Public Sans\",\n heading: serif(\"Newsreader\", [400, 500, 600], { italic: true, opticalSize: true }),\n body: sans(\"Public Sans\", [400, 600, 700]),\n headingWeight: 500,\n headingTracking: \"-0.015em\",\n mood: [\"trustworthy\", \"civic\", \"editorial\"],\n template: \"harbor\",\n }),\n pairing({\n id: \"instrument\",\n name: \"Instrument Serif & Instrument Sans\",\n heading: serif(\"Instrument Serif\", [400], { italic: true }),\n body: sans(\"Instrument Sans\", [400, 500, 600]),\n headingWeight: 400,\n headingTracking: \"-0.01em\",\n mood: [\"minimal\", \"gallery\", \"refined\"],\n template: \"atelier\",\n }),\n pairing({\n id: \"source-serif-plex\",\n name: \"Source Serif 4 & IBM Plex Sans\",\n heading: serif(\"Source Serif 4\", [400, 600, 700], { italic: true, opticalSize: true }),\n body: sans(\"IBM Plex Sans\", [400, 500, 600]),\n headingWeight: 600,\n headingTracking: \"-0.015em\",\n mood: [\"crisp\", \"editorial\", \"confident\"],\n template: \"ledger\",\n }),\n pairing({\n id: \"young-serif-work-sans\",\n name: \"Young Serif & Work Sans\",\n heading: serif(\"Young Serif\", [400]),\n body: sans(\"Work Sans\", [400, 500, 600]),\n headingWeight: 400,\n headingTracking: \"-0.01em\",\n mood: [\"warm\", \"appetizing\", \"friendly\"],\n template: \"hearth\",\n }),\n pairing({\n id: \"bricolage-geist\",\n name: \"Bricolage Grotesque & Geist\",\n heading: sans(\"Bricolage Grotesque\", [500, 600, 700], { opticalSize: true }),\n body: sans(\"Geist\", [400, 500, 600]),\n headingWeight: 700,\n headingTracking: \"-0.035em\",\n mood: [\"bold\", \"modern\", \"technical\"],\n template: \"signal\",\n }),\n pairing({\n id: \"literata-manrope\",\n name: \"Literata & Manrope\",\n heading: serif(\"Literata\", [400, 500, 600], { italic: true, opticalSize: true }),\n body: sans(\"Manrope\", [400, 500, 700]),\n headingWeight: 500,\n headingTracking: \"-0.015em\",\n mood: [\"literary\", \"reading\", \"calm\"],\n template: \"field-notes\",\n }),\n pairing({\n id: \"syne-dm-sans\",\n name: \"Syne & DM Sans\",\n heading: sans(\"Syne\", [600, 700, 800]),\n body: sans(\"DM Sans\", [400, 500, 700]),\n headingWeight: 700,\n headingTracking: \"-0.02em\",\n mood: [\"expressive\", \"nocturnal\", \"artsy\"],\n template: \"encore\",\n }),\n pairing({\n id: \"gloock-albert-sans\",\n name: \"Gloock & Albert Sans\",\n heading: serif(\"Gloock\", [400]),\n body: sans(\"Albert Sans\", [400, 500, 600]),\n headingWeight: 400,\n headingTracking: \"-0.01em\",\n mood: [\"tactile\", \"crafted\", \"classic\"],\n template: \"kiln\",\n }),\n pairing({\n id: \"spectral-epilogue\",\n name: \"Spectral & Epilogue\",\n heading: serif(\"Spectral\", [400, 500, 600], { italic: true }),\n body: sans(\"Epilogue\", [400, 500, 600]),\n headingWeight: 500,\n headingTracking: \"-0.01em\",\n mood: [\"grounded\", \"collective\", \"earnest\"],\n template: \"commons\",\n }),\n pairing({\n id: \"cormorant-jost\",\n name: \"Cormorant Garamond & Jost\",\n heading: serif(\"Cormorant Garamond\", [400, 500, 600], { italic: true }),\n body: sans(\"Jost\", [400, 500]),\n headingWeight: 500,\n headingTracking: \"0em\",\n strongWeight: 500,\n eyebrowTracking: \"0.2em\",\n mood: [\"romantic\", \"refined\", \"elegant\"],\n template: \"vow\",\n }),\n pairing({\n id: \"outfit\",\n name: \"Outfit\",\n heading: sans(\"Outfit\", [600, 700]),\n body: sans(\"Outfit\", [400, 500]),\n headingWeight: 700,\n headingTracking: \"-0.025em\",\n strongWeight: 600,\n mood: [\"punchy\", \"mobile\", \"friendly\"],\n template: \"link\",\n }),\n // --- library pairings ---\n pairing({\n id: \"playfair-source-sans\",\n name: \"Playfair Display & Source Sans 3\",\n heading: serif(\"Playfair Display\", [400, 600, 700], { italic: true }),\n body: sans(\"Source Sans 3\", [400, 600]),\n headingWeight: 600,\n headingTracking: \"-0.015em\",\n mood: [\"classic\", \"fashion\", \"editorial\"],\n }),\n pairing({\n id: \"dm-serif-dm-sans\",\n name: \"DM Serif Display & DM Sans\",\n heading: serif(\"DM Serif Display\", [400], { italic: true }),\n body: sans(\"DM Sans\", [400, 500, 700]),\n headingWeight: 400,\n headingTracking: \"-0.015em\",\n mood: [\"confident\", \"warm\", \"modern\"],\n }),\n pairing({\n id: \"lora-inter\",\n name: \"Lora & Inter\",\n heading: serif(\"Lora\", [500, 600, 700], { italic: true }),\n body: sans(\"Inter\", [400, 500, 600], { opticalSize: true }),\n headingWeight: 600,\n headingTracking: \"-0.01em\",\n mood: [\"approachable\", \"balanced\", \"versatile\"],\n }),\n pairing({\n id: \"eb-garamond-inter\",\n name: \"EB Garamond & Inter\",\n heading: serif(\"EB Garamond\", [400, 500, 600], { italic: true }),\n body: sans(\"Inter\", [400, 500, 600], { opticalSize: true }),\n headingWeight: 500,\n headingTracking: \"-0.01em\",\n mood: [\"scholarly\", \"timeless\", \"quiet\"],\n }),\n pairing({\n id: \"libre-baskerville-karla\",\n name: \"Libre Baskerville & Karla\",\n heading: serif(\"Libre Baskerville\", [400, 700], { italic: true }),\n body: sans(\"Karla\", [400, 500, 700]),\n headingWeight: 400,\n headingTracking: \"-0.01em\",\n mood: [\"bookish\", \"trustworthy\", \"warm\"],\n }),\n pairing({\n id: \"space-grotesk-inter\",\n name: \"Space Grotesk & Inter\",\n heading: sans(\"Space Grotesk\", [500, 600, 700]),\n body: sans(\"Inter\", [400, 500, 600], { opticalSize: true }),\n headingWeight: 600,\n headingTracking: \"-0.03em\",\n mood: [\"technical\", \"startup\", \"precise\"],\n }),\n pairing({\n id: \"sora-inter\",\n name: \"Sora & Inter\",\n heading: sans(\"Sora\", [500, 600, 700]),\n body: sans(\"Inter\", [400, 500, 600], { opticalSize: true }),\n headingWeight: 600,\n headingTracking: \"-0.03em\",\n mood: [\"clean\", \"product\", \"modern\"],\n }),\n pairing({\n id: \"plus-jakarta\",\n name: \"Plus Jakarta Sans\",\n heading: sans(\"Plus Jakarta Sans\", [600, 700, 800]),\n body: sans(\"Plus Jakarta Sans\", [400, 500]),\n headingWeight: 700,\n headingTracking: \"-0.025em\",\n mood: [\"friendly\", \"product\", \"crisp\"],\n }),\n pairing({\n id: \"manrope\",\n name: \"Manrope\",\n heading: sans(\"Manrope\", [600, 700, 800]),\n body: sans(\"Manrope\", [400, 500]),\n headingWeight: 700,\n headingTracking: \"-0.025em\",\n mood: [\"neutral\", \"geometric\", \"calm\"],\n }),\n pairing({\n id: \"unbounded-figtree\",\n name: \"Unbounded & Figtree\",\n heading: sans(\"Unbounded\", [500, 600, 700]),\n body: sans(\"Figtree\", [400, 500, 600]),\n headingWeight: 600,\n headingTracking: \"-0.02em\",\n mood: [\"loud\", \"playful\", \"event\"],\n }),\n pairing({\n id: \"bodoni-montserrat\",\n name: \"Bodoni Moda & Montserrat\",\n heading: serif(\"Bodoni Moda\", [400, 500, 600], { italic: true, opticalSize: true }),\n body: sans(\"Montserrat\", [400, 500, 600]),\n headingWeight: 500,\n headingTracking: \"-0.01em\",\n mood: [\"luxury\", \"fashion\", \"dramatic\"],\n }),\n pairing({\n id: \"libre-caslon-nunito-sans\",\n name: \"Libre Caslon Text & Nunito Sans\",\n heading: serif(\"Libre Caslon Text\", [400, 700], { italic: true }),\n body: sans(\"Nunito Sans\", [400, 600, 700]),\n headingWeight: 400,\n headingTracking: \"-0.01em\",\n mood: [\"gentle\", \"heritage\", \"warm\"],\n }),\n pairing({\n id: \"zilla-slab-inter\",\n name: \"Zilla Slab & Inter\",\n heading: serif(\"Zilla Slab\", [500, 600, 700]),\n body: sans(\"Inter\", [400, 500, 600], { opticalSize: true }),\n headingWeight: 600,\n headingTracking: \"-0.01em\",\n mood: [\"sturdy\", \"journalistic\", \"honest\"],\n }),\n pairing({\n id: \"bitter-roboto\",\n name: \"Bitter & Roboto\",\n heading: serif(\"Bitter\", [500, 600, 700], { italic: true }),\n body: sans(\"Roboto\", [400, 500, 700]),\n headingWeight: 600,\n headingTracking: \"-0.015em\",\n mood: [\"practical\", \"clear\", \"service\"],\n }),\n pairing({\n id: \"alegreya\",\n name: \"Alegreya & Alegreya Sans\",\n heading: serif(\"Alegreya\", [500, 600, 700], { italic: true }),\n body: sans(\"Alegreya Sans\", [400, 500, 700]),\n headingWeight: 600,\n headingTracking: \"-0.01em\",\n mood: [\"humanist\", \"literary\", \"warm\"],\n }),\n pairing({\n id: \"josefin-crimson\",\n name: \"Josefin Sans & Crimson Pro\",\n heading: sans(\"Josefin Sans\", [400, 600, 700]),\n body: serif(\"Crimson Pro\", [400, 500, 600], { italic: true }),\n headingWeight: 600,\n headingTracking: \"0em\",\n eyebrowTracking: \"0.18em\",\n mood: [\"vintage\", \"elegant\", \"art-deco\"],\n }),\n pairing({\n id: \"merriweather-open-sans\",\n name: \"Merriweather & Open Sans\",\n heading: serif(\"Merriweather\", [400, 700], { italic: true }),\n body: sans(\"Open Sans\", [400, 600, 700]),\n headingWeight: 700,\n headingTracking: \"-0.01em\",\n mood: [\"readable\", \"dependable\", \"community\"],\n }),\n pairing({\n id: \"plex-mono-plex-sans\",\n name: \"IBM Plex Mono & IBM Plex Sans\",\n heading: { family: \"IBM Plex Mono\", category: \"monospace\", weights: [500, 600] },\n body: sans(\"IBM Plex Sans\", [400, 500, 600]),\n headingWeight: 600,\n headingTracking: \"-0.02em\",\n mood: [\"developer\", \"technical\", \"structured\"],\n }),\n pairing({\n id: \"crimson-figtree\",\n name: \"Crimson Pro & Figtree\",\n heading: serif(\"Crimson Pro\", [500, 600, 700], { italic: true }),\n body: sans(\"Figtree\", [400, 500, 600]),\n headingWeight: 600,\n headingTracking: \"-0.01em\",\n mood: [\"soft\", \"personal\", \"story\"],\n }),\n pairing({\n id: \"abril-lato\",\n name: \"Abril Fatface & Lato\",\n heading: serif(\"Abril Fatface\", [400]),\n body: sans(\"Lato\", [400, 700]),\n headingWeight: 400,\n headingTracking: \"-0.01em\",\n strongWeight: 700,\n mood: [\"poster\", \"bold\", \"retro\"],\n }),\n pairing({\n id: \"archivo\",\n name: \"Archivo\",\n heading: sans(\"Archivo\", [600, 700, 800]),\n body: sans(\"Archivo\", [400, 500]),\n headingWeight: 700,\n headingTracking: \"-0.03em\",\n mood: [\"industrial\", \"grotesque\", \"direct\"],\n }),\n];\n\n/** Pairing used when `choices.pairing` names an unknown id. */\nexport const DEFAULT_PAIRING_ID = \"fraunces-hanken\";\n\nconst BY_ID = new Map(TYPE_PAIRINGS.map((p) => [p.id, p]));\n\nexport function getPairing(id: string): TypePairing | undefined {\n return BY_ID.get(id);\n}\n\n/** `\"Hanken Grotesk\"` → `hanken-grotesk` */\nexport function fontsourceId(spec: FontFamilySpec): string {\n return (\n spec.fontsourceId ??\n spec.family\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n );\n}\n\nconst quoteFamily = (family: string) => (/^[a-z-]+$/i.test(family) ? family : `\"${family}\"`);\n\n/** CSS `font-family` stack for one family: the web font, then the category's system stack. */\nexport function fontStack(spec: FontFamilySpec): string {\n return [`\"${spec.family}\"`, ...FALLBACK_STACKS[spec.category]]\n .map((f) => (f.startsWith('\"') ? f : quoteFamily(f)))\n .join(\", \");\n}\n\n/** Families of a pairing with merged weights (heading and body may share a family). */\nexport function pairingFamilies(p: TypePairing): FontFamilySpec[] {\n const merged = new Map<string, FontFamilySpec>();\n for (const spec of [p.heading, p.body]) {\n const prev = merged.get(spec.family);\n if (!prev) {\n merged.set(spec.family, { ...spec, weights: [...spec.weights] });\n continue;\n }\n prev.weights = [...new Set([...prev.weights, ...spec.weights])].sort((a, b) => a - b);\n prev.italic = prev.italic || spec.italic;\n }\n return [...merged.values()];\n}\n\n/**\n * Google Fonts CSS2 API URL for a pairing — for previews and the Studio font picker only;\n * published sites self-host via Fontsource.\n */\nexport function googleFontsUrl(p: TypePairing, display = \"swap\"): string {\n const families = pairingFamilies(p).map((spec) => {\n const name = spec.family.replace(/ /g, \"+\");\n const weights = [...spec.weights].sort((a, b) => a - b);\n if (spec.italic) {\n const tuples = [...weights.map((w) => `0,${w}`), ...weights.map((w) => `1,${w}`)];\n return `family=${name}:ital,wght@${tuples.join(\";\")}`;\n }\n return `family=${name}:wght@${weights.join(\";\")}`;\n });\n return `https://fonts.googleapis.com/css2?${families.join(\"&\")}&display=${display}`;\n}\n\n/** Fontsource npm packages to install for a pairing, e.g. `@fontsource/fraunces`. */\nexport function fontsourcePackages(p: TypePairing): string[] {\n return pairingFamilies(p).map((spec) => `@fontsource/${fontsourceId(spec)}`);\n}\n\n/**\n * Fontsource CSS entry points per weight/style: module specifiers (`@fontsource/fraunces/400.css`)\n * by default, or jsDelivr URLs with `{ cdn: true }`.\n */\nexport function fontsourceCss(p: TypePairing, options: { cdn?: boolean } = {}): string[] {\n const out: string[] = [];\n for (const spec of pairingFamilies(p)) {\n const pkg = `@fontsource/${fontsourceId(spec)}`;\n const base = options.cdn ? `https://cdn.jsdelivr.net/npm/${pkg}@5` : pkg;\n for (const w of spec.weights) {\n out.push(`${base}/${w}.css`);\n if (spec.italic) out.push(`${base}/${w}-italic.css`);\n }\n }\n return out;\n}\n","/**\n * Uploaded fonts (PRD §5.1 \"Font uploads\"): `@font-face` rules for a site's own font files and\n * the font tokens that use them. The files publish with the site (`media/fonts/`), so the URLs\n * are resolved by the caller (renderer: base path; Studio canvas: preview URLs).\n */\nimport type { CustomFont, Styles } from \"@omniharmonic/openspace-schema\";\nimport { FALLBACK_STACKS } from \"./pairings\";\n\nconst FORMAT: Record<string, string> = { woff2: \"woff2\", ttf: \"truetype\", otf: \"opentype\" };\n\nconst CATEGORY_FALLBACK: Record<CustomFont[\"category\"], string[]> = {\n serif: FALLBACK_STACKS.serif,\n \"sans-serif\": FALLBACK_STACKS[\"sans-serif\"],\n monospace: FALLBACK_STACKS.monospace,\n display: FALLBACK_STACKS[\"sans-serif\"],\n handwriting: [\"cursive\", ...FALLBACK_STACKS.serif],\n};\n\nconst cssString = (s: string) => `\"${s.replace(/[\"\\\\\\n\\r]/g, \"\")}\"`;\n\n/** `\"Family\", <fallback stack>` for an uploaded family. */\nexport function customFontStack(font: CustomFont): string {\n return [cssString(font.family), ...CATEGORY_FALLBACK[font.category]].join(\", \");\n}\n\n/** The uploaded font a choice (`headingFont` / `bodyFont`) points at, if any. */\nexport function chosenCustomFont(\n styles: Pick<Styles, \"fonts\">,\n family: string | undefined,\n): CustomFont | undefined {\n if (!family) return undefined;\n const key = family.toLowerCase();\n return styles.fonts?.find((f) => f.family.toLowerCase() === key);\n}\n\n/** The available weight closest to `wanted` (ties go to the heavier one). */\nexport function nearestWeight(font: CustomFont, wanted: number): number {\n let best = font.files[0]?.weight ?? wanted;\n for (const f of font.files) {\n const d = Math.abs(f.weight - wanted);\n const bd = Math.abs(best - wanted);\n if (d < bd || (d === bd && f.weight > best)) best = f.weight;\n }\n return best;\n}\n\n/**\n * `@font-face` rules for every uploaded font in use (heading/body choices), or for all of them\n * with `all: true` (Studio previews). `font-display: swap` keeps text visible while they load.\n */\nexport function customFontFaces(\n styles: Pick<Styles, \"fonts\" | \"choices\">,\n url: (src: string) => string,\n opts: { all?: boolean } = {},\n): string {\n const used = new Set(\n [styles.choices.headingFont, styles.choices.bodyFont]\n .filter((x): x is string => !!x)\n .map((x) => x.toLowerCase()),\n );\n const rules: string[] = [];\n for (const font of styles.fonts ?? []) {\n if (!opts.all && !used.has(font.family.toLowerCase())) continue;\n for (const file of font.files) {\n const ext = file.src.split(\".\").pop()?.toLowerCase() ?? \"\";\n const format = FORMAT[ext];\n if (!format) continue;\n rules.push(\n `@font-face{font-family:${cssString(font.family)};src:url(${cssString(url(file.src))}) format(\"${format}\");font-weight:${file.weight};font-style:${file.style};font-display:swap}`,\n );\n }\n }\n return rules.join(\"\\n\");\n}\n\n/** WOFF2 files worth preloading: the upright file nearest each chosen weight (heading, body). */\nexport function customFontPreloads(\n styles: Pick<Styles, \"fonts\" | \"choices\">,\n weights: { heading: number; body: number },\n): string[] {\n const out: string[] = [];\n for (const [family, weight] of [\n [styles.choices.headingFont, weights.heading],\n [styles.choices.bodyFont, weights.body],\n ] as const) {\n const font = chosenCustomFont(styles, family);\n if (!font) continue;\n const w = nearestWeight(font, weight);\n const file = font.files.find(\n (f) => f.weight === w && f.style === \"normal\" && f.src.endsWith(\".woff2\"),\n );\n if (file && !out.includes(file.src)) out.push(file.src);\n }\n return out;\n}\n","import { fontStack, type TypePairing } from \"./pairings\";\n\n/** Every typography preset: the nine content presets plus the UI-only `button` and `nav`. */\nexport const TYPE_PRESET_NAMES = [\n \"display\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"lead\",\n \"body\",\n \"small\",\n \"eyebrow\",\n \"button\",\n \"nav\",\n] as const;\nexport type TypePresetName = (typeof TYPE_PRESET_NAMES)[number];\n\n/** Fluid scale parameters (doc 04 §4.2). Sizes interpolate between the two viewports. */\nexport const FLUID_TYPE = {\n minViewport: 360,\n maxViewport: 1440,\n /** Body size (px) at the min / max viewport. */\n minBase: 16,\n maxBase: 18,\n minRatio: 1.2,\n maxRatio: 1.333,\n} as const;\n\n/** Scale step per preset (0 = body); fractional steps sit between ratios. */\nconst PRESET_STEP: Record<TypePresetName, number> = {\n display: 5.5,\n h1: 4,\n h2: 3,\n h3: 2,\n h4: 1,\n lead: 0.5,\n body: 0,\n small: -1,\n eyebrow: -1,\n button: -0.5,\n nav: -0.5,\n};\n\nconst LINE_HEIGHT: Record<TypePresetName, number> = {\n display: 1.05,\n h1: 1.1,\n h2: 1.15,\n h3: 1.2,\n h4: 1.3,\n lead: 1.5,\n body: 1.6,\n small: 1.5,\n eyebrow: 1.3,\n button: 1.2,\n nav: 1.3,\n};\n\n/** Smallest rendered size (px) for any preset — keeps captions and eyebrows legible. */\nexport const MIN_FONT_SIZE_PX = 14;\n\nconst HEADINGS = new Set<TypePresetName>([\"display\", \"h1\", \"h2\", \"h3\", \"h4\"]);\nconst LARGE_HEADINGS = new Set<TypePresetName>([\"display\", \"h1\", \"h2\"]);\n\nconst r4 = (v: number) => {\n const r = Math.round(v * 10000) / 10000;\n return Object.is(r, -0) ? 0 : r;\n};\n\n/**\n * `clamp()` that moves linearly from `minPx` at the min viewport to `maxPx` at the max viewport.\n * Sizes are emitted in rem so they respect the reader's font-size preference.\n */\nexport function fluidClamp(\n minPx: number,\n maxPx: number,\n minViewport: number = FLUID_TYPE.minViewport,\n maxViewport: number = FLUID_TYPE.maxViewport,\n): string {\n if (Math.abs(maxPx - minPx) < 0.01) return `${r4(minPx / 16)}rem`;\n const slope = (maxPx - minPx) / (maxViewport - minViewport);\n const intercept = minPx - slope * minViewport;\n const lo = Math.min(minPx, maxPx);\n const hi = Math.max(minPx, maxPx);\n return `clamp(${r4(lo / 16)}rem, ${r4(intercept / 16)}rem + ${r4(slope * 100)}vw, ${r4(hi / 16)}rem)`;\n}\n\n/** Font size (px) for a scale step at the min and max viewport. */\nexport function stepSizes(step: number): { min: number; max: number } {\n return {\n min: FLUID_TYPE.minBase * FLUID_TYPE.minRatio ** step,\n max: FLUID_TYPE.maxBase * FLUID_TYPE.maxRatio ** step,\n };\n}\n\nexport interface TypePresetTokens {\n \"font-family\": string;\n \"font-size\": string;\n \"line-height\": string;\n \"letter-spacing\": string;\n \"font-weight\": string;\n \"text-transform\": string;\n}\n\n/** Half of an em tracking value: `-0.02em` → `-0.01em`. */\nfunction halfTracking(value: string): string {\n const m = /^(-?\\d*\\.?\\d+)em$/.exec(value.trim());\n return m?.[1] ? `${r4(Number.parseFloat(m[1]) / 2)}em` : value;\n}\n\n/** Typography preset tokens for a pairing. Families reference `--os-font-*` vars. */\nexport function typeScale(p: TypePairing): Record<TypePresetName, TypePresetTokens> {\n const out = {} as Record<TypePresetName, TypePresetTokens>;\n for (const name of TYPE_PRESET_NAMES) {\n const sizes = stepSizes(PRESET_STEP[name]);\n const min = Math.max(MIN_FONT_SIZE_PX, sizes.min);\n const max = Math.max(MIN_FONT_SIZE_PX, sizes.max);\n const heading = HEADINGS.has(name);\n let letterSpacing = \"0em\";\n if (LARGE_HEADINGS.has(name)) letterSpacing = p.headingTracking;\n else if (heading) letterSpacing = halfTracking(p.headingTracking);\n else if (name === \"eyebrow\") letterSpacing = p.eyebrowTracking;\n else if (name === \"button\" || name === \"nav\") letterSpacing = \"0.01em\";\n let weight = \"var(--os-font-weight-body)\";\n if (heading) weight = \"var(--os-font-weight-heading)\";\n else if (name === \"eyebrow\" || name === \"button\" || name === \"nav\")\n weight = \"var(--os-font-weight-strong)\";\n out[name] = {\n \"font-family\": heading ? \"var(--os-font-heading)\" : \"var(--os-font-body)\",\n \"font-size\": fluidClamp(min, max),\n \"line-height\": String(LINE_HEIGHT[name]),\n \"letter-spacing\": letterSpacing,\n \"font-weight\": weight,\n \"text-transform\": name === \"eyebrow\" ? \"uppercase\" : \"none\",\n };\n }\n return out;\n}\n\n/** Font family + weight tokens for a pairing. */\nexport function fontTokens(p: TypePairing): Record<string, string> {\n return {\n heading: fontStack(p.heading),\n body: fontStack(p.body),\n \"weight-heading\": String(p.headingWeight),\n \"weight-body\": String(p.bodyWeight),\n \"weight-strong\": String(p.strongWeight),\n };\n}\n","import type {\n BUTTON_STYLES,\n DENSITIES,\n ImageTreatment,\n MOTION_LEVELS,\n SHAPES,\n} from \"@omniharmonic/openspace-schema\";\nimport { fluidClamp } from \"./type-scale\";\n\nexport type Density = (typeof DENSITIES)[number];\nexport type Shape = (typeof SHAPES)[number];\nexport type ButtonStyle = (typeof BUTTON_STYLES)[number];\nexport type MotionLevel = (typeof MOTION_LEVELS)[number];\n\nconst rem = (px: number) => (px === 0 ? \"0\" : `${Math.round((px / 16) * 10000) / 10000}rem`);\n\n// --- density -----------------------------------------------------------------------------------\n\n/** Space steps (`3xs`…`3xl`) on a 4px base, in px, per density. */\nexport const SPACE_SCALES: Record<Density, Record<string, number>> = {\n compact: { \"3xs\": 4, \"2xs\": 8, xs: 12, sm: 16, md: 20, lg: 24, xl: 32, \"2xl\": 48, \"3xl\": 64 },\n comfortable: {\n \"3xs\": 4,\n \"2xs\": 8,\n xs: 12,\n sm: 16,\n md: 24,\n lg: 32,\n xl: 48,\n \"2xl\": 64,\n \"3xl\": 96,\n },\n airy: { \"3xs\": 4, \"2xs\": 8, xs: 16, sm: 24, md: 32, lg: 48, xl: 64, \"2xl\": 96, \"3xl\": 128 },\n};\n\n/** Fluid section rhythm (px at 360px → 1440px viewports). */\nconst SECTION_RHYTHM: Record<\n Density,\n { padY: [number, number]; gap: [number, number]; gutter: [number, number] }\n> = {\n compact: { padY: [48, 80], gap: [16, 24], gutter: [20, 32] },\n comfortable: { padY: [64, 120], gap: [24, 32], gutter: [24, 40] },\n airy: { padY: [88, 168], gap: [32, 48], gutter: [24, 48] },\n};\n\nexport function spaceTokens(density: Density): Record<string, string> {\n const out: Record<string, string> = { none: \"0\" };\n for (const [step, px] of Object.entries(SPACE_SCALES[density])) out[step] = rem(px);\n return out;\n}\n\nexport function sectionTokens(density: Density): Record<string, string> {\n const r = SECTION_RHYTHM[density];\n return {\n \"pad-y\": fluidClamp(...r.padY),\n \"block-gap\": fluidClamp(...r.gap),\n gutter: fluidClamp(...r.gutter),\n };\n}\n\n/** Content widths (doc 04 §2.2). */\nexport const WIDTH_TOKENS = { narrow: \"720px\", content: \"1280px\", wide: \"1440px\" } as const;\n\n// --- shape -------------------------------------------------------------------------------------\n\n/** Radius scale + component radii (px) per shape. `full` is always a pill. */\nexport const RADIUS_SCALES: Record<Shape, Record<string, number>> = {\n sharp: { none: 0, sm: 0, md: 0, lg: 0, xl: 0, button: 0, card: 0, input: 0, image: 0 },\n soft: { none: 0, sm: 4, md: 8, lg: 12, xl: 20, button: 8, card: 12, input: 6, image: 8 },\n round: { none: 0, sm: 8, md: 14, lg: 22, xl: 32, button: 14, card: 22, input: 12, image: 22 },\n};\n\nexport function radiusTokens(shape: Shape): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, px] of Object.entries(RADIUS_SCALES[shape]))\n out[name] = px === 0 ? \"0\" : `${px}px`;\n out.full = \"9999px\";\n return out;\n}\n\nexport const SHADOW_VALUES: Record<\"none\" | \"sm\" | \"md\" | \"lg\", string> = {\n none: \"none\",\n sm: \"0 1px 2px rgb(0 0 0 / 0.06), 0 1px 3px rgb(0 0 0 / 0.08)\",\n md: \"0 2px 4px rgb(0 0 0 / 0.05), 0 6px 16px rgb(0 0 0 / 0.08)\",\n lg: \"0 4px 8px rgb(0 0 0 / 0.04), 0 16px 40px rgb(0 0 0 / 0.12)\",\n};\n\n// --- buttons -----------------------------------------------------------------------------------\n\nexport const BUTTON_ROLES = [\"primary\", \"secondary\", \"tertiary\"] as const;\nexport type ButtonRole = (typeof BUTTON_ROLES)[number];\n\n/** Per-role CSS properties a button reads; each becomes `--os-button-<role>-<prop>`. */\nexport const BUTTON_PROPS = [\n \"bg\",\n \"color\",\n \"border-color\",\n \"border-width\",\n \"radius\",\n \"padding-x\",\n \"padding-y\",\n \"text-decoration\",\n \"icon\",\n \"bg-hover\",\n \"color-hover\",\n \"border-color-hover\",\n \"bg-active\",\n \"color-active\",\n \"border-color-active\",\n] as const;\nexport type ButtonProp = (typeof BUTTON_PROPS)[number];\n\ntype Kind = \"solid\" | \"outline\" | \"underline\" | \"text-arrow\";\ninterface Variant {\n kind: Kind;\n pill: boolean;\n /** `accent` (brand-colored) or `text` (neutral ink). */\n tone: \"accent\" | \"text\";\n}\n\n/** How each Site Styles button choice maps onto the three roles. */\nconst BUTTON_SYSTEMS: Record<ButtonStyle, Record<ButtonRole, Variant>> = {\n solid: {\n primary: { kind: \"solid\", pill: false, tone: \"accent\" },\n secondary: { kind: \"outline\", pill: false, tone: \"text\" },\n tertiary: { kind: \"underline\", pill: false, tone: \"text\" },\n },\n outline: {\n primary: { kind: \"outline\", pill: false, tone: \"accent\" },\n secondary: { kind: \"outline\", pill: false, tone: \"text\" },\n tertiary: { kind: \"underline\", pill: false, tone: \"text\" },\n },\n underline: {\n primary: { kind: \"underline\", pill: false, tone: \"accent\" },\n secondary: { kind: \"underline\", pill: false, tone: \"text\" },\n tertiary: { kind: \"text-arrow\", pill: false, tone: \"text\" },\n },\n \"pill-solid\": {\n primary: { kind: \"solid\", pill: true, tone: \"accent\" },\n secondary: { kind: \"outline\", pill: true, tone: \"text\" },\n tertiary: { kind: \"underline\", pill: false, tone: \"text\" },\n },\n \"pill-outline\": {\n primary: { kind: \"outline\", pill: true, tone: \"accent\" },\n secondary: { kind: \"outline\", pill: true, tone: \"text\" },\n tertiary: { kind: \"underline\", pill: false, tone: \"text\" },\n },\n \"text-arrow\": {\n primary: { kind: \"text-arrow\", pill: false, tone: \"accent\" },\n secondary: { kind: \"text-arrow\", pill: false, tone: \"text\" },\n tertiary: { kind: \"underline\", pill: false, tone: \"text\" },\n },\n};\n\nconst c = (role: string) => `var(--os-color-${role})`;\n\n/**\n * Button tokens. Every label/fill combination — including hover and pressed — is one the\n * contrast solver guarantees at 4.5:1: `accent-text` on `accent`/`accent-hover`/`accent-pressed`,\n * `background` on `text`, and `link` / `text` / `heading` on the section surfaces. No `color-mix()`.\n */\nfunction variantTokens(v: Variant): Record<ButtonProp, string> {\n const ink = v.tone === \"accent\" ? c(\"link\") : c(\"text\");\n const radius = v.pill ? \"var(--os-radius-full)\" : \"var(--os-radius-button)\";\n const padded = { \"padding-x\": \"var(--os-space-lg)\", \"padding-y\": \"var(--os-space-xs)\" };\n const bare = { \"padding-x\": \"0\", \"padding-y\": \"var(--os-space-3xs)\" };\n switch (v.kind) {\n case \"solid\": {\n const accent = v.tone === \"accent\";\n const fill = accent ? c(\"accent\") : c(\"text\");\n const label = accent ? c(\"accent-text\") : c(\"background\");\n const hover = accent ? c(\"accent-hover\") : c(\"heading\");\n const active = accent ? c(\"accent-pressed\") : c(\"heading\");\n return {\n bg: fill,\n color: label,\n \"border-color\": fill,\n \"border-width\": \"1px\",\n radius,\n ...padded,\n \"text-decoration\": \"none\",\n icon: \"none\",\n \"bg-hover\": hover,\n \"color-hover\": label,\n \"border-color-hover\": hover,\n \"bg-active\": active,\n \"color-active\": label,\n \"border-color-active\": active,\n };\n }\n case \"outline\": {\n const line = v.tone === \"accent\" ? c(\"accent\") : c(\"text\");\n const fillHover = v.tone === \"accent\" ? c(\"accent\") : c(\"text\");\n const labelHover = v.tone === \"accent\" ? c(\"accent-text\") : c(\"background\");\n return {\n bg: \"transparent\",\n color: ink,\n \"border-color\": line,\n \"border-width\": \"1.5px\",\n radius,\n ...padded,\n \"text-decoration\": \"none\",\n icon: \"none\",\n \"bg-hover\": fillHover,\n \"color-hover\": labelHover,\n \"border-color-hover\": fillHover,\n \"bg-active\": v.tone === \"accent\" ? c(\"accent-pressed\") : c(\"heading\"),\n \"color-active\": labelHover,\n \"border-color-active\": v.tone === \"accent\" ? c(\"accent-pressed\") : c(\"heading\"),\n };\n }\n case \"underline\":\n return {\n bg: \"transparent\",\n color: ink,\n \"border-color\": \"transparent\",\n \"border-width\": \"0\",\n radius: \"0\",\n ...bare,\n \"text-decoration\": \"underline\",\n icon: \"none\",\n \"bg-hover\": \"transparent\",\n \"color-hover\": c(\"heading\"),\n \"border-color-hover\": \"transparent\",\n \"bg-active\": \"transparent\",\n \"color-active\": c(\"heading\"),\n \"border-color-active\": \"transparent\",\n };\n case \"text-arrow\":\n return {\n bg: \"transparent\",\n color: ink,\n \"border-color\": \"transparent\",\n \"border-width\": \"0\",\n radius: \"0\",\n ...bare,\n \"text-decoration\": \"none\",\n icon: '\"→\"',\n \"bg-hover\": \"transparent\",\n \"color-hover\": c(\"heading\"),\n \"border-color-hover\": \"transparent\",\n \"bg-active\": \"transparent\",\n \"color-active\": c(\"heading\"),\n \"border-color-active\": \"transparent\",\n };\n }\n}\n\nexport function buttonTokens(style: ButtonStyle): Record<ButtonRole, Record<ButtonProp, string>> {\n const sys = BUTTON_SYSTEMS[style];\n return {\n primary: variantTokens(sys.primary),\n secondary: variantTokens(sys.secondary),\n tertiary: variantTokens(sys.tertiary),\n };\n}\n\n// --- motion ------------------------------------------------------------------------------------\n\nexport const MOTION_PROPS = [\n \"enabled\",\n \"duration-fast\",\n \"duration-base\",\n \"duration-slow\",\n \"ease\",\n \"reveal-distance\",\n \"reveal-duration\",\n \"stagger\",\n \"hover-scale\",\n \"parallax\",\n] as const;\nexport type MotionProp = (typeof MOTION_PROPS)[number];\n\nexport const MOTION_VALUES: Record<MotionLevel, Record<MotionProp, string>> = {\n none: {\n enabled: \"0\",\n \"duration-fast\": \"0ms\",\n \"duration-base\": \"0ms\",\n \"duration-slow\": \"0ms\",\n ease: \"linear\",\n \"reveal-distance\": \"0px\",\n \"reveal-duration\": \"0ms\",\n stagger: \"0ms\",\n \"hover-scale\": \"1\",\n parallax: \"0\",\n },\n subtle: {\n enabled: \"1\",\n \"duration-fast\": \"150ms\",\n \"duration-base\": \"250ms\",\n \"duration-slow\": \"400ms\",\n ease: \"cubic-bezier(0.2, 0, 0, 1)\",\n \"reveal-distance\": \"12px\",\n \"reveal-duration\": \"600ms\",\n stagger: \"60ms\",\n \"hover-scale\": \"1.02\",\n parallax: \"0\",\n },\n expressive: {\n enabled: \"1\",\n \"duration-fast\": \"200ms\",\n \"duration-base\": \"350ms\",\n \"duration-slow\": \"600ms\",\n ease: \"cubic-bezier(0.16, 1, 0.3, 1)\",\n \"reveal-distance\": \"32px\",\n \"reveal-duration\": \"900ms\",\n stagger: \"110ms\",\n \"hover-scale\": \"1.06\",\n parallax: \"0.2\",\n },\n};\n\n// --- image treatments --------------------------------------------------------------------------\n\nexport const IMAGE_PROPS = [\n \"radius\",\n \"clip-path\",\n \"aspect-ratio\",\n \"filter\",\n \"blend\",\n \"backdrop\",\n \"overlay\",\n \"overlay-blend\",\n \"overlay-opacity\",\n \"frame-padding\",\n \"frame-color\",\n \"frame-border\",\n] as const;\nexport type ImageProp = (typeof IMAGE_PROPS)[number];\n\n/** Fractal-noise tile for the `grain` treatment (inline SVG, no network request). */\nconst GRAIN_SVG =\n \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E\\\")\";\n\nconst IMAGE_BASE: Record<ImageProp, string> = {\n radius: \"0\",\n \"clip-path\": \"none\",\n \"aspect-ratio\": \"auto\",\n filter: \"none\",\n blend: \"normal\",\n backdrop: \"transparent\",\n overlay: \"none\",\n \"overlay-blend\": \"normal\",\n \"overlay-opacity\": \"0\",\n \"frame-padding\": \"0\",\n \"frame-color\": \"transparent\",\n \"frame-border\": \"0 solid transparent\",\n};\n\n/**\n * Image treatment tokens. The renderer reads them on the image wrapper (`radius`, `clip-path`,\n * `aspect-ratio`, `backdrop`, frame), the `<img>` (`filter`, `blend`) and a `::after` overlay.\n * Duotone: a grayscale image multiplied over a light accent, then a dark accent lightened in.\n */\nexport const IMAGE_TREATMENT_VALUES: Record<ImageTreatment, Record<ImageProp, string>> = {\n none: IMAGE_BASE,\n rounded: { ...IMAGE_BASE, radius: \"max(var(--os-radius-lg), 0.75rem)\" },\n arch: { ...IMAGE_BASE, radius: \"9999px 9999px 0 0\" },\n circle: { ...IMAGE_BASE, radius: \"50%\", \"aspect-ratio\": \"1\" },\n blob: { ...IMAGE_BASE, radius: \"42% 58% 63% 37% / 41% 44% 56% 59%\" },\n duotone: {\n ...IMAGE_BASE,\n radius: \"var(--os-radius-image)\",\n filter: \"grayscale(1) contrast(1.1)\",\n blend: \"multiply\",\n backdrop: \"var(--os-color-accent-200)\",\n overlay: \"linear-gradient(var(--os-color-accent-900), var(--os-color-accent-900))\",\n \"overlay-blend\": \"lighten\",\n \"overlay-opacity\": \"1\",\n },\n grain: {\n ...IMAGE_BASE,\n radius: \"var(--os-radius-image)\",\n overlay: GRAIN_SVG,\n \"overlay-blend\": \"overlay\",\n \"overlay-opacity\": \"0.22\",\n },\n frame: {\n ...IMAGE_BASE,\n radius: \"var(--os-radius-sm)\",\n \"frame-padding\": \"var(--os-space-xs)\",\n \"frame-color\": \"var(--os-color-surface-raised)\",\n \"frame-border\": \"1px solid var(--os-color-border)\",\n },\n};\n","/**\n * The CSS custom-property contract. Every token the compiler emits is named here; the renderer's\n * base stylesheet and blocks must reference tokens only through these names.\n *\n * Naming rule (also how DTCG override paths map to properties): path segments, camelCase turned\n * kebab-case, joined with `-`, prefixed `--os-`. `type.display.letterSpacing` →\n * `--os-type-display-letter-spacing`; `color.accent-500` → `--os-color-accent-500`.\n *\n * Where each lives in the compiled CSS:\n * - `color.*` roles: per section theme, on `:root, .os-theme-light` and `.os-theme-<name>`.\n * - `button.*`, `image.*`: re-declared on `:root` and every `.os-theme-*` so their `var()`\n * references resolve against the enclosing section's roles; `.os-image-<treatment>` classes\n * override `image.*` per block.\n * - everything else: `:root`.\n */\nimport {\n COLOR_ROLES,\n COLOR_SCALE_STEPS,\n COLOR_THEMES,\n type ColorTheme,\n RADIUS_TOKENS,\n SHADOW_TOKENS,\n SPACE_TOKENS,\n} from \"@omniharmonic/openspace-schema\";\nimport {\n BUTTON_PROPS,\n BUTTON_ROLES,\n type ButtonProp,\n type ButtonRole,\n IMAGE_PROPS,\n type ImageProp,\n MOTION_PROPS,\n type MotionProp,\n} from \"./layout\";\nimport { TYPE_PRESET_NAMES, type TypePresetName, type TypePresetTokens } from \"./type-scale\";\nimport { type ScaleStep, STATE_ROLES, type ThemeRole } from \"./types\";\n\nexport const VAR_PREFIX = \"--os-\";\n\n/** `[\"type\", \"display\", \"letterSpacing\"]` → `--os-type-display-letter-spacing` */\nexport function varName(...path: (string | number)[]): string {\n return (\n VAR_PREFIX +\n path\n .map((seg) =>\n String(seg)\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .toLowerCase(),\n )\n .join(\"-\")\n );\n}\n\n/** `var(--os-…)` for a path. */\nexport const cssVar = (...path: (string | number)[]) => `var(${varName(...path)})`;\n\n/** Variable for a schema color token (`accent`, `text-muted`, `neutral-200`). */\nexport const colorVar = (token: string) => varName(\"color\", token);\n\n/** Section theme class: `.os-theme-dark` → `os-theme-dark`. */\nexport const themeClass = (theme: ColorTheme) => `os-theme-${theme}`;\n/** Per-block image treatment class. */\nexport const imageTreatmentClass = (treatment: string) => `os-image-${treatment}`;\n\n/** Space steps (schema `SPACE_TOKENS`). */\nexport const SPACE_STEPS = SPACE_TOKENS;\n/** Schema `RADIUS_TOKENS` plus component radii set by the shape choice. */\nexport const RADIUS_NAMES = [...RADIUS_TOKENS, \"button\", \"card\", \"input\", \"image\"] as const;\n/** Schema `SHADOW_TOKENS`. */\nexport const SHADOW_NAMES = SHADOW_TOKENS;\nexport const TYPE_PROPS = [\n \"font-family\",\n \"font-size\",\n \"line-height\",\n \"letter-spacing\",\n \"font-weight\",\n \"text-transform\",\n] as const satisfies readonly (keyof TypePresetTokens)[];\n\nconst record = <K extends string | number, V>(keys: readonly K[], fn: (k: K) => V) =>\n Object.fromEntries(keys.map((k) => [k, fn(k)])) as Record<K, V>;\n\n/** The documented variable map. Values are custom-property names (`--os-…`). */\nexport const TOKEN_VARS = {\n /** Semantic roles plus `accent-hover` / `accent-pressed` (theme-scoped, contrast-solved). */\n color: record<ThemeRole, string>([...COLOR_ROLES, ...STATE_ROLES], (r) => varName(\"color\", r)),\n /** Accent scale `--os-color-accent-50` … `-950`. */\n accent: record<ScaleStep, string>(COLOR_SCALE_STEPS, (s) => varName(\"color\", \"accent\", s)),\n /** Neutral scale `--os-color-neutral-50` … `-950`. */\n neutral: record<ScaleStep, string>(COLOR_SCALE_STEPS, (s) => varName(\"color\", \"neutral\", s)),\n /** The (gamut-mapped) brand color as chosen. */\n brand: varName(\"color\", \"brand\"),\n font: {\n heading: varName(\"font\", \"heading\"),\n body: varName(\"font\", \"body\"),\n weightHeading: varName(\"font\", \"weight\", \"heading\"),\n weightBody: varName(\"font\", \"weight\", \"body\"),\n weightStrong: varName(\"font\", \"weight\", \"strong\"),\n },\n /** Typography presets: `--os-type-<preset>-<css-property>`. */\n type: record<TypePresetName, Record<(typeof TYPE_PROPS)[number], string>>(\n TYPE_PRESET_NAMES,\n (preset) => record(TYPE_PROPS, (prop) => varName(\"type\", preset, prop)),\n ),\n /** Max line length for running text (~70 characters). */\n measure: varName(\"measure\"),\n space: record(SPACE_STEPS, (s) => varName(\"space\", s)),\n section: {\n padY: varName(\"section\", \"pad-y\"),\n blockGap: varName(\"section\", \"block-gap\"),\n gutter: varName(\"section\", \"gutter\"),\n },\n width: {\n narrow: varName(\"width\", \"narrow\"),\n content: varName(\"width\", \"content\"),\n wide: varName(\"width\", \"wide\"),\n },\n radius: record(RADIUS_NAMES, (r) => varName(\"radius\", r)),\n shadow: record(SHADOW_NAMES, (s) => varName(\"shadow\", s)),\n /** Buttons: `--os-button-<primary|secondary|tertiary>-<prop>`. */\n button: record<ButtonRole, Record<ButtonProp, string>>(BUTTON_ROLES, (role) =>\n record(BUTTON_PROPS, (prop) => varName(\"button\", role, prop)),\n ),\n motion: record<MotionProp, string>(MOTION_PROPS, (p) => varName(\"motion\", p)),\n image: record<ImageProp, string>(IMAGE_PROPS, (p) => varName(\"image\", p)),\n} as const;\n\n/** Every variable name in {@link TOKEN_VARS}, flattened, in declaration order. */\nexport function allTokenVars(): string[] {\n const out: string[] = [];\n const walk = (v: unknown) => {\n if (typeof v === \"string\") out.push(v);\n else if (v && typeof v === \"object\") for (const x of Object.values(v)) walk(x);\n };\n walk(TOKEN_VARS);\n return out;\n}\n\n/** Section theme class names, in schema order. */\nexport const THEME_CLASSES = COLOR_THEMES.map(themeClass);\n","import type { COLOR_ROLES, COLOR_SCALE_STEPS } from \"@omniharmonic/openspace-schema\";\n\n/** A semantic color role (doc 04 §3.1), e.g. `text-muted`. */\nexport type ColorRole = (typeof COLOR_ROLES)[number];\n/** A color scale step, 50–950. */\nexport type ScaleStep = (typeof COLOR_SCALE_STEPS)[number];\n/** An 11-step color scale. */\nexport type ColorScale<T = string> = Record<ScaleStep, T>;\n\n/** Interaction states the solver derives from `accent` (not schema roles; theme-internal). */\nexport const STATE_ROLES = [\"accent-hover\", \"accent-pressed\"] as const;\nexport type StateRole = (typeof STATE_ROLES)[number];\n/** Every color a section theme defines: the 14 semantic roles plus the accent states. */\nexport type ThemeRole = ColorRole | StateRole;\n","import type { DtcgGroup, DtcgToken, DtcgValue } from \"@omniharmonic/openspace-schema\";\nimport { isColor } from \"./color\";\nimport { cssVar } from \"./vars\";\n\nexport interface FlatToken {\n /** Path segments, e.g. `[\"type\", \"display\", \"letterSpacing\"]`. */\n path: string[];\n token: DtcgToken;\n /** `$type` from the token or the nearest enclosing group. */\n type: string | undefined;\n}\n\nconst isToken = (v: unknown): v is DtcgToken =>\n typeof v === \"object\" && v !== null && !Array.isArray(v) && \"$value\" in v;\n\n/** Flatten a DTCG group into tokens (sorted by path for deterministic output). */\nexport function flattenDtcg(group: DtcgGroup | undefined): FlatToken[] {\n const out: FlatToken[] = [];\n const walk = (node: DtcgGroup, path: string[], inherited: string | undefined) => {\n const groupType = typeof node.$type === \"string\" ? node.$type : inherited;\n for (const key of Object.keys(node).sort()) {\n if (key.startsWith(\"$\")) continue;\n const child = node[key];\n if (isToken(child)) {\n out.push({ path: [...path, key], token: child, type: child.$type ?? groupType });\n } else if (typeof child === \"object\" && child !== null) {\n walk(child as DtcgGroup, [...path, key], groupType);\n }\n }\n };\n if (group) walk(group, [], undefined);\n return out;\n}\n\nconst ALIAS_RE = /\\{([^{}]+)\\}/g;\n/** A value that is exactly one alias, e.g. `{color.accent-500}`. */\nexport const SOLE_ALIAS_RE = /^\\{([^{}]+)\\}$/;\n\n/** `{color.accent-500}` → `var(--os-color-accent-500)` */\nexport function resolveAliases(value: string): string {\n return value.replace(ALIAS_RE, (_, ref: string) => cssVar(...ref.split(\".\")));\n}\n\n/** Rejects anything that could escape a declaration or fetch remote resources. */\nconst UNSAFE_RE = /[;{}<>\\\\]|\\/\\*|\\*\\/|url\\s*\\(|expression\\s*\\(|@import|!important|javascript:/i;\n\nexport function isSafeCssValue(value: string): boolean {\n return value.trim().length > 0 && !UNSAFE_RE.test(value);\n}\n\nconst UNIT_RE = /^(px|rem|em|%|vw|vh|svh|dvh|ch|ex|ms|s|deg|fr)$/;\nconst quoteFamily = (f: string) =>\n /^[a-z-]+$/i.test(f) || f.startsWith('\"') ? f : `\"${f.replace(/\"/g, \"\")}\"`;\n\nfunction shadowLayer(v: DtcgValue): string | null {\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) return null;\n const parts = [\"offsetX\", \"offsetY\", \"blur\", \"spread\"].map((k) => {\n const p = v[k];\n return p === undefined ? \"0\" : scalar(p, \"dimension\");\n });\n const color = v.color;\n if (parts.some((p) => p === null) || typeof color !== \"string\") return null;\n const layer = `${parts.join(\" \")} ${resolveAliases(color)}`;\n return v.inset === true ? `inset ${layer}` : layer;\n}\n\nfunction scalar(v: DtcgValue, type: string | undefined): string | null {\n if (typeof v === \"string\") return resolveAliases(v.trim());\n if (typeof v === \"number\") {\n if (!Number.isFinite(v)) return null;\n if (type === \"dimension\") return v === 0 ? \"0\" : `${v}px`;\n if (type === \"duration\") return `${v}ms`;\n return String(v);\n }\n if (typeof v === \"object\" && v !== null && !Array.isArray(v)) {\n // DTCG 2025 object form: { value, unit }\n const { value, unit } = v as { value?: unknown; unit?: unknown };\n if (typeof value === \"number\" && typeof unit === \"string\" && UNIT_RE.test(unit)) {\n return `${value}${unit}`;\n }\n }\n return null;\n}\n\n/**\n * Convert a DTCG `$value` to a CSS value, or `null` if it can't be represented safely.\n * Composite `typography` tokens are expanded by the caller.\n */\nexport function dtcgToCss(value: DtcgValue, type: string | undefined): string | null {\n let out: string | null = null;\n if (Array.isArray(value)) {\n if (type === \"cubicBezier\" && value.length === 4 && value.every((n) => typeof n === \"number\")) {\n out = `cubic-bezier(${value.join(\", \")})`;\n } else if (type === \"fontFamily\" || value.every((x) => typeof x === \"string\")) {\n out = value.map((f) => (typeof f === \"string\" ? quoteFamily(f) : \"\")).join(\", \");\n } else if (type === \"shadow\") {\n const layers = value.map(shadowLayer);\n out = layers.every((l) => l !== null) ? layers.join(\", \") : null;\n }\n } else if (type === \"shadow\") {\n out = shadowLayer(value);\n } else if (type === \"fontFamily\" && typeof value === \"string\") {\n out = value.includes(\",\") ? value : quoteFamily(value);\n } else {\n out = scalar(value, type);\n }\n if (out === null || !isSafeCssValue(out)) return null;\n if (type === \"color\" && !out.startsWith(\"var(\") && !isColor(out)) return null;\n return out;\n}\n","import { COLOR_ROLES, COLOR_THEMES, type ColorTheme } from \"@omniharmonic/openspace-schema\";\nimport { gamutMap, type Oklch, oklchToHex, parseColor } from \"./color\";\nimport {\n CONTRAST_MINIMUMS,\n CORE_CONTRAST_PAIRS,\n type ContrastMode,\n type ContrastPair,\n contrastRatio,\n type Direction,\n relativeLuminance,\n STATE_PAIRS,\n solveLightness,\n type ThemeColorSet,\n} from \"./contrast\";\nimport { accentScale, type NeutralTint, neutralScale } from \"./scales\";\nimport {\n type ColorRole,\n type ColorScale,\n STATE_ROLES,\n type StateRole,\n type ThemeRole,\n} from \"./types\";\n\nexport interface PaletteInput {\n brand: string;\n neutral: NeutralTint;\n contrast?: ContrastMode;\n}\n\nexport interface Palette {\n brand: Oklch;\n accent: ColorScale<Oklch>;\n neutral: ColorScale<Oklch>;\n}\n\nexport function buildPalette(brand: string | Oklch, neutral: NeutralTint): Palette {\n const b = gamutMap(typeof brand === \"string\" ? parseColor(brand) : brand);\n return { brand: b, accent: accentScale(b), neutral: neutralScale(b, neutral) };\n}\n\ntype RoleSet = Record<ColorRole, Oklch>;\n\nconst WHITE: Oklch = { l: 1, c: 0, h: 0 };\nconst BLACK: Oklch = { l: 0, c: 0, h: 0 };\nconst STATUS_HUE = { success: 150, warning: 70, danger: 27 } as const;\nconst status = (l: number, c = 0.14) => ({\n success: { l, c, h: STATUS_HUE.success },\n warning: { l, c, h: STATUS_HUE.warning },\n danger: { l, c: c + 0.04, h: STATUS_HUE.danger },\n});\n\n/** Pick the candidate with the highest contrast against `bg`. */\nexport function bestOn(bg: Oklch, candidates: Oklch[]): Oklch {\n let best = candidates[0] as Oklch;\n for (const c of candidates) if (contrastRatio(c, bg) > contrastRatio(best, bg)) best = c;\n return best;\n}\n\n/** Label color for text sitting on `bg`: white or the darkest neutral, whichever contrasts more. */\nexport function onColor(bg: Oklch, palette: Palette): Oklch {\n return bestOn(bg, [WHITE, palette.neutral[950]]);\n}\n\nconst shift = (c: Oklch, dl: number): Oklch => gamutMap({ ...c, l: c.l + dl });\n\n/** The un-solved role sets for each section theme (doc 04 §3.2). */\nexport function themeRoles(palette: Palette): Record<ColorTheme, RoleSet> {\n const { accent: a, neutral: n, brand } = palette;\n const onAccent = (bg: Oklch) => onColor(bg, palette);\n\n const light: RoleSet = {\n background: n[50],\n surface: n[100],\n \"surface-raised\": WHITE,\n text: n[900],\n \"text-muted\": n[600],\n heading: n[950],\n accent: brand,\n \"accent-text\": onAccent(brand),\n border: n[200],\n focus: a[600],\n link: a[700],\n ...status(0.5),\n };\n\n const lightAccent: RoleSet = {\n background: a[50],\n surface: a[100],\n \"surface-raised\": n[50],\n text: n[900],\n \"text-muted\": n[700],\n heading: n[950],\n accent: a[600],\n \"accent-text\": onAccent(a[600]),\n border: a[200],\n focus: a[700],\n link: a[700],\n ...status(0.48),\n };\n\n const dark: RoleSet = {\n background: n[950],\n surface: n[900],\n \"surface-raised\": n[800],\n text: n[100],\n \"text-muted\": n[400],\n heading: n[50],\n accent: a[400],\n \"accent-text\": onAccent(a[400]),\n border: n[800],\n focus: a[300],\n link: a[300],\n ...status(0.78, 0.13),\n };\n\n const darkAccent: RoleSet = {\n background: a[950],\n surface: a[900],\n \"surface-raised\": a[800],\n text: a[50],\n \"text-muted\": a[200],\n heading: WHITE,\n accent: a[300],\n \"accent-text\": onAccent(a[300]),\n border: a[800],\n focus: a[200],\n link: a[200],\n ...status(0.82, 0.12),\n };\n\n // Brand: the saturated brand color is the background; everything else inverts around it.\n const brandIsLight = contrastRatio(brand, BLACK) >= contrastRatio(brand, WHITE);\n const toward = brandIsLight ? -1 : 1;\n const ink = brandIsLight ? a[950] : a[50];\n const brandTheme: RoleSet = {\n background: brand,\n surface: shift(brand, -0.04 * toward),\n \"surface-raised\": shift(brand, -0.08 * toward),\n text: ink,\n \"text-muted\": brandIsLight ? a[900] : a[100],\n heading: brandIsLight ? n[950] : WHITE,\n accent: brandIsLight ? n[950] : WHITE,\n \"accent-text\": brand,\n border: shift(brand, 0.12 * toward),\n focus: ink,\n link: ink,\n ...status(brandIsLight ? 0.32 : 0.92, 0.1),\n };\n\n return {\n light,\n \"light-accent\": lightAccent,\n dark,\n \"dark-accent\": darkAccent,\n brand: brandTheme,\n };\n}\n\nexport interface ContrastAdjustment {\n theme: ColorTheme;\n role: ThemeRole;\n from: string;\n to: string;\n /** The role it was adjusted against. */\n against: ThemeRole;\n required: number;\n}\n\nexport interface SolvedThemes {\n themes: ThemeColorSet;\n adjustments: ContrastAdjustment[];\n}\n\n/** Backgrounds must reach this multiple of the body minimum against pure white/black. */\nconst POLARITY_HEADROOM = 1.2;\nconst SURFACES = [\"background\", \"surface\", \"surface-raised\"] as const;\nconst SURFACE_SET = new Set<ThemeRole>(SURFACES);\n/** OKLCH lightness step from `accent` to its hover fill (pressed is twice this). */\nconst HOVER_STEP = 0.06;\n\n/**\n * Unsolved hover/pressed fills: the accent stepped in lightness away from its label (toward it\n * only when the accent is already at black/white).\n */\nexport function accentStates(accent: Oklch, label: Oklch): Record<StateRole, Oklch> {\n const sign = label.l > accent.l ? -1 : 1;\n const step = (n: number) => {\n const next = shift(accent, sign * HOVER_STEP * n);\n return oklchToHex(next) === oklchToHex(accent) ? shift(accent, -sign * HOVER_STEP * n) : next;\n };\n return { \"accent-hover\": step(1), \"accent-pressed\": step(2) };\n}\n\n/**\n * The contrast solver (doc 04 §3.3). Lightness only, hue never changes.\n *\n * 1. Polarity: each theme has light-on-dark or dark-on-light text. Every surface is moved (if\n * needed) so the pure extreme of that polarity clears the body minimum with headroom — this\n * makes all text/surface pairs jointly solvable.\n * 2. For every pair in {@link CONTRAST_PAIRS}, the foreground moves the minimum distance (on\n * surfaces: only away from them, in the theme's polarity).\n * 3. If a foreground can't get there (e.g. `accent-text` on a mid-tone `accent` in `high` mode),\n * the background moves instead — choosing the direction that keeps the background's own pairs\n * passing, flipping the foreground's polarity when that is what it takes.\n *\n * 4. Button states: `accent-hover` / `accent-pressed` step the accent's lightness away from its\n * label, then are solved against `accent-text` (body) and `background` (UI).\n *\n * `text-muted` is kept no stronger than `text`. Iterates until every pair passes.\n */\nexport function solveThemes(\n roles: Record<ColorTheme, RoleSet>,\n mode: ContrastMode = \"standard\",\n): SolvedThemes {\n const mins = CONTRAST_MINIMUMS[mode];\n const adjustments = new Map<string, ContrastAdjustment>();\n const themes = {} as ThemeColorSet;\n\n for (const theme of COLOR_THEMES) {\n const set = { ...roles[theme] } as Record<ThemeRole, Oklch>;\n const hex = (role: ThemeRole) => oklchToHex(set[role]);\n const record = (role: ThemeRole, against: ThemeRole, required: number, next: Oklch) => {\n const key = `${theme}:${role}`;\n const prev = adjustments.get(key);\n const from = prev?.from ?? hex(role);\n set[role] = next;\n adjustments.set(key, { theme, role, from, to: hex(role), against, required });\n };\n\n // 1. polarity\n const lightText = relativeLuminance(set.text) > relativeLuminance(set.background);\n const extreme = lightText ? WHITE : BLACK;\n const away: Direction = lightText ? \"lighter\" : \"darker\";\n const need = mins.body * POLARITY_HEADROOM;\n for (const surface of SURFACES) {\n if (contrastRatio(extreme, set[surface]) >= need) continue;\n const moved = solveLightness(set[surface], extreme, need);\n if (moved) record(surface, \"text\", mins.body, moved);\n }\n\n // Pairs where `role` is the foreground — used to keep a moved background valid.\n const ownPairsPass = (role: ThemeRole, candidate: Oklch) =>\n CORE_CONTRAST_PAIRS.every(\n (p) => p.fg !== role || contrastRatio(candidate, set[p.bg]) >= mins[p.level],\n );\n\n const solvePairs = (pairs: readonly ContrastPair[], allowBgMoves: boolean) => {\n for (let pass = 0; pass < 10; pass++) {\n let changed = false;\n for (const { fg, bg, level, adjust } of pairs) {\n const required = mins[level];\n if (contrastRatio(hex(fg), hex(bg)) >= required) continue;\n const [move, fixed] = adjust === \"bg\" ? [bg, fg] : [fg, bg];\n const direction = SURFACE_SET.has(fixed) ? away : \"either\";\n const solved = solveLightness(set[move], set[fixed], required, direction);\n if (solved) {\n record(move, fixed, required, solved);\n changed = true;\n continue;\n }\n if (!allowBgMoves) continue;\n let best: { bg: Oklch; fg: Oklch; delta: number } | null = null;\n for (const end of [WHITE, BLACK]) {\n const fgEnd = gamutMap({ ...set[fg], l: end.l });\n const movedBg = solveLightness(set[bg], fgEnd, required);\n if (!movedBg || !ownPairsPass(bg, movedBg)) continue;\n const delta = Math.abs(movedBg.l - set[bg].l);\n if (best && delta >= best.delta) continue;\n best = {\n bg: movedBg,\n fg: solveLightness(set[fg], movedBg, required) ?? fgEnd,\n delta,\n };\n }\n if (!best) continue;\n record(bg, fg, required, best.bg);\n record(fg, bg, required, best.fg);\n changed = true;\n }\n if (!changed) break;\n }\n };\n\n // 2–3. semantic role pairs\n solvePairs(CORE_CONTRAST_PAIRS, true);\n\n // Hierarchy: muted text never out-contrasts body text (it equals text when no accessible\n // in-between exists).\n for (const surface of SURFACES) {\n if (contrastRatio(set[\"text-muted\"], set[surface]) > contrastRatio(set.text, set[surface])) {\n record(\"text-muted\", \"text\", mins.body, set.text);\n break;\n }\n }\n\n // 4. button states: step the accent away from its label, then solve only the state colors.\n Object.assign(set, accentStates(set.accent, set[\"accent-text\"]));\n solvePairs(STATE_PAIRS, false);\n // No room for a visible state (accent at black/white, label at the minimum): deepen the\n // label away from the accent so the pressed step — and so also hover — fits.\n if (hex(\"accent-hover\") === hex(\"accent\") || hex(\"accent-pressed\") === hex(\"accent\")) {\n const toward = set[\"accent-text\"].l > set.accent.l ? 1 : -1;\n const pressed = shift(set.accent, toward * HOVER_STEP * 2);\n const label = solveLightness(\n set[\"accent-text\"],\n pressed,\n mins.body,\n toward > 0 ? \"lighter\" : \"darker\",\n );\n if (label) {\n record(\"accent-text\", \"accent-pressed\", mins.body, label);\n set[\"accent-hover\"] = shift(set.accent, toward * HOVER_STEP);\n set[\"accent-pressed\"] = pressed;\n solvePairs(STATE_PAIRS, false);\n }\n }\n\n const out = {} as Record<ThemeRole, string>;\n for (const role of [...COLOR_ROLES, ...STATE_ROLES]) out[role] = hex(role);\n themes[theme] = out;\n }\n\n const list = [...adjustments.values()].filter((a) => a.from !== a.to);\n return { themes, adjustments: list };\n}\n","import { COLOR_SCALE_STEPS } from \"@omniharmonic/openspace-schema\";\nimport { gamutMap, mixHue, type Oklch, parseColor } from \"./color\";\nimport type { ColorScale, ScaleStep } from \"./types\";\n\nexport type NeutralTint = \"warm\" | \"cool\" | \"pure\";\n\n/** Accent ladder lightness per step: perceptually even in OKLCH. */\nexport const ACCENT_LIGHTNESS: ColorScale<number> = {\n 50: 0.975,\n 100: 0.94,\n 200: 0.88,\n 300: 0.8,\n 400: 0.71,\n 500: 0.625,\n 600: 0.545,\n 700: 0.465,\n 800: 0.385,\n 900: 0.305,\n 950: 0.235,\n};\n\n/** Fraction of the brand chroma kept at each accent step (tints and shades desaturate). */\nconst ACCENT_CHROMA: ColorScale<number> = {\n 50: 0.14,\n 100: 0.28,\n 200: 0.5,\n 300: 0.74,\n 400: 0.92,\n 500: 1,\n 600: 1,\n 700: 0.92,\n 800: 0.8,\n 900: 0.66,\n 950: 0.52,\n};\n\nexport const NEUTRAL_LIGHTNESS: ColorScale<number> = {\n 50: 0.985,\n 100: 0.962,\n 200: 0.922,\n 300: 0.86,\n 400: 0.72,\n 500: 0.6,\n 600: 0.5,\n 700: 0.415,\n 800: 0.325,\n 900: 0.245,\n 950: 0.185,\n};\n\nconst NEUTRAL_CHROMA: ColorScale<number> = {\n 50: 0.45,\n 100: 0.55,\n 200: 0.65,\n 300: 0.75,\n 400: 0.85,\n 500: 0.9,\n 600: 0.95,\n 700: 1,\n 800: 1,\n 900: 1,\n 950: 1,\n};\n\n/** Target hues for neutral temperature; the brand hue pulls the neutral toward the accent. */\nconst TINT_HUE = { warm: 70, cool: 250 } as const;\n\nconst toOklch = (c: string | Oklch): Oklch => (typeof c === \"string\" ? parseColor(c) : c);\n\nfunction buildScale(fn: (step: ScaleStep) => Oklch): ColorScale<Oklch> {\n const out = {} as ColorScale<Oklch>;\n for (const step of COLOR_SCALE_STEPS) out[step] = gamutMap(fn(step));\n return out;\n}\n\n/**\n * 11-step accent scale (50–950) from a brand color: fixed perceptual lightness ladder, hue held,\n * chroma following the brand's and tapering toward the ends, each step gamut-mapped to sRGB.\n */\nexport function accentScale(brand: string | Oklch): ColorScale<Oklch> {\n const b = gamutMap(toOklch(brand));\n return buildScale((step) => ({\n l: ACCENT_LIGHTNESS[step],\n c: b.c * ACCENT_CHROMA[step],\n h: b.h,\n }));\n}\n\n/**\n * 11-step neutral scale tinted toward the brand. `warm` and `cool` lean the hue toward amber or\n * blue (pulled 35% toward the brand hue); `pure` is achromatic gray.\n */\nexport function neutralScale(brand: string | Oklch, tint: NeutralTint): ColorScale<Oklch> {\n if (tint === \"pure\") return buildScale((step) => ({ l: NEUTRAL_LIGHTNESS[step], c: 0, h: 0 }));\n const b = gamutMap(toOklch(brand));\n const target = TINT_HUE[tint];\n const h = b.c < 0.02 ? target : mixHue(target, b.h, 0.35);\n const base = Math.min(0.018, Math.max(0.008, b.c * 0.12));\n return buildScale((step) => ({ l: NEUTRAL_LIGHTNESS[step], c: base * NEUTRAL_CHROMA[step], h }));\n}\n\n/** The scale step whose lightness is closest to the color's (where the brand \"sits\"). */\nexport function nearestStep(color: string | Oklch): ScaleStep {\n const { l } = toOklch(color);\n let best: ScaleStep = 500;\n for (const step of COLOR_SCALE_STEPS) {\n if (Math.abs(ACCENT_LIGHTNESS[step] - l) < Math.abs(ACCENT_LIGHTNESS[best] - l)) best = step;\n }\n return best;\n}\n","import {\n formatOklch,\n linearSrgbToOklab,\n type Oklab,\n oklabToOklch,\n oklchToHex,\n srgbChannelToLinear,\n} from \"./color\";\n\nexport interface PaletteCandidate {\n hex: string;\n oklch: string;\n l: number;\n c: number;\n h: number;\n /** Share of (opaque, sampled) pixels in this cluster, 0–1. */\n population: number;\n /** Ranking score: population weighted by chroma, penalizing near-white/black. */\n score: number;\n}\n\nexport interface ExtractOptions {\n /** Number of clusters (default 6). */\n k?: number;\n /** Max candidates returned (default 5). */\n count?: number;\n /** Max pixels sampled (default 20 000; sampling is a fixed stride, so deterministic). */\n maxSamples?: number;\n /** Channels per pixel in `pixels` (default 4, RGBA). */\n channels?: 3 | 4;\n}\n\n// 8-bit sRGB → linear lookup.\nconst LINEAR = Array.from({ length: 256 }, (_, i) => srgbChannelToLinear(i / 255));\n\nconst dist2 = (a: Oklab, b: Oklab) => (a.l - b.l) ** 2 + (a.a - b.a) ** 2 + (a.b - b.b) ** 2;\n\n/**\n * Brand color candidates from image pixels (logo or hero photo): weighted k-means in OKLab\n * (samples weighted toward chromatic pixels), deterministic farthest-point seeding, clusters\n * ranked by population × chroma. Near-white, near-black and gray clusters rank last; if the image\n * is entirely achromatic the grays are still returned.\n */\nexport function extractPalette(\n pixels: Uint8ClampedArray | Uint8Array | number[],\n options: ExtractOptions = {},\n): PaletteCandidate[] {\n const channels = options.channels ?? 4;\n const k = Math.max(1, options.k ?? 6);\n const count = options.count ?? 5;\n const total = Math.floor(pixels.length / channels);\n const stride = Math.max(1, Math.ceil(total / (options.maxSamples ?? 20000)));\n\n const samples: Oklab[] = [];\n const weights: number[] = [];\n for (let i = 0; i < total; i += stride) {\n const o = i * channels;\n if (channels === 4 && (pixels[o + 3] ?? 255) < 128) continue;\n const lab = linearSrgbToOklab({\n r: LINEAR[pixels[o] ?? 0] as number,\n g: LINEAR[pixels[o + 1] ?? 0] as number,\n b: LINEAR[pixels[o + 2] ?? 0] as number,\n });\n samples.push(lab);\n weights.push(1 + 12 * Math.hypot(lab.a, lab.b));\n }\n if (samples.length === 0) return [];\n\n // Farthest-point seeding from the heaviest (most chromatic) sample.\n let first = 0;\n for (let i = 1; i < samples.length; i++) if ((weights[i] ?? 0) > (weights[first] ?? 0)) first = i;\n const centers: Oklab[] = [{ ...(samples[first] as Oklab) }];\n const nearest = samples.map((s) => dist2(s, centers[0] as Oklab));\n while (centers.length < Math.min(k, samples.length)) {\n let far = 0;\n for (let i = 1; i < samples.length; i++) {\n if ((nearest[i] ?? 0) * (weights[i] ?? 0) > (nearest[far] ?? 0) * (weights[far] ?? 0))\n far = i;\n }\n if ((nearest[far] ?? 0) === 0) break;\n const c = { ...(samples[far] as Oklab) };\n centers.push(c);\n for (let i = 0; i < samples.length; i++) {\n nearest[i] = Math.min(nearest[i] ?? 0, dist2(samples[i] as Oklab, c));\n }\n }\n\n const assign = new Array<number>(samples.length).fill(0);\n for (let iter = 0; iter < 16; iter++) {\n let moved = false;\n for (let i = 0; i < samples.length; i++) {\n let best = 0;\n let bestD = Number.POSITIVE_INFINITY;\n for (let j = 0; j < centers.length; j++) {\n const d = dist2(samples[i] as Oklab, centers[j] as Oklab);\n if (d < bestD) {\n bestD = d;\n best = j;\n }\n }\n if (assign[i] !== best) {\n assign[i] = best;\n moved = true;\n }\n }\n const sums = centers.map(() => ({ l: 0, a: 0, b: 0, w: 0 }));\n for (let i = 0; i < samples.length; i++) {\n const s = samples[i] as Oklab;\n const w = weights[i] ?? 1;\n const acc = sums[assign[i] ?? 0];\n if (!acc) continue;\n acc.l += s.l * w;\n acc.a += s.a * w;\n acc.b += s.b * w;\n acc.w += w;\n }\n sums.forEach((acc, j) => {\n if (acc.w > 0) centers[j] = { l: acc.l / acc.w, a: acc.a / acc.w, b: acc.b / acc.w };\n });\n if (!moved && iter > 0) break;\n }\n\n const counts = centers.map(() => 0);\n for (const a of assign) counts[a] = (counts[a] ?? 0) + 1;\n\n const candidates: PaletteCandidate[] = [];\n centers.forEach((center, j) => {\n const n = counts[j] ?? 0;\n if (n === 0) return;\n const lch = oklabToOklch(center);\n const population = n / samples.length;\n const chromaWeight = Math.min(1, lch.c / 0.12);\n const extreme = lch.l > 0.96 || lch.l < 0.12 ? 0.05 : 1;\n const score = population * (0.04 + chromaWeight) * extreme;\n candidates.push({\n hex: oklchToHex(lch),\n oklch: formatOklch(lch),\n l: lch.l,\n c: lch.c,\n h: lch.h,\n population,\n score,\n });\n });\n\n candidates.sort((a, b) => b.score - a.score || a.hex.localeCompare(b.hex));\n // Merge near-duplicate clusters (same visible color).\n const out: PaletteCandidate[] = [];\n for (const c of candidates) if (!out.some((o) => o.hex === c.hex)) out.push(c);\n return out.slice(0, count);\n}\n","import type { NeutralTint } from \"./scales\";\n\nexport interface CuratedPalette {\n id: string;\n name: string;\n /** Brand color (OKLCH) the full palette is generated from. */\n brand: string;\n neutral: NeutralTint;\n description: string;\n /** Launch templates this palette was designed for (doc 04 §7). */\n templates?: string[];\n}\n\n/** Named starting palettes for Studio's palette picker. */\nexport const curatedPalettes: readonly CuratedPalette[] = [\n {\n id: \"sage\",\n name: \"Oat & Sage\",\n brand: \"oklch(0.62 0.07 145)\",\n neutral: \"warm\",\n description: \"Soft sage on oat paper; calm and organic.\",\n templates: [\"meadow\"],\n },\n {\n id: \"clay\",\n name: \"Clay\",\n brand: \"oklch(0.6 0.11 45)\",\n neutral: \"warm\",\n description: \"Sun-baked terracotta with bone neutrals.\",\n templates: [\"meadow\", \"kiln\"],\n },\n {\n id: \"harbor\",\n name: \"Harbor Blue\",\n brand: \"oklch(0.42 0.12 255)\",\n neutral: \"warm\",\n description: \"Deep civic blue on warm paper.\",\n templates: [\"harbor\"],\n },\n {\n id: \"signal-orange\",\n name: \"Signal Orange\",\n brand: \"oklch(0.68 0.19 45)\",\n neutral: \"warm\",\n description: \"A bright call-to-action orange.\",\n templates: [\"harbor\"],\n },\n {\n id: \"monochrome\",\n name: \"Monochrome\",\n brand: \"oklch(0.25 0 0)\",\n neutral: \"pure\",\n description: \"Ink and white; lets the photography lead.\",\n templates: [\"atelier\"],\n },\n {\n id: \"ledger-green\",\n name: \"Ledger Green\",\n brand: \"oklch(0.42 0.08 160)\",\n neutral: \"warm\",\n description: \"Deep green with ink and ivory.\",\n templates: [\"ledger\"],\n },\n {\n id: \"tomato\",\n name: \"Tomato\",\n brand: \"oklch(0.6 0.2 30)\",\n neutral: \"warm\",\n description: \"Ripe tomato red on cream.\",\n templates: [\"hearth\"],\n },\n {\n id: \"olive\",\n name: \"Olive Grove\",\n brand: \"oklch(0.55 0.09 115)\",\n neutral: \"warm\",\n description: \"Olive and cream, quietly appetizing.\",\n templates: [\"hearth\"],\n },\n {\n id: \"electric\",\n name: \"Electric Violet\",\n brand: \"oklch(0.62 0.25 285)\",\n neutral: \"cool\",\n description: \"Near-black chrome with an electric accent.\",\n templates: [\"signal\"],\n },\n {\n id: \"highlighter\",\n name: \"Highlighter\",\n brand: \"oklch(0.9 0.17 100)\",\n neutral: \"warm\",\n description: \"Paper and ink with a highlighter-yellow mark.\",\n templates: [\"field-notes\"],\n },\n {\n id: \"plum\",\n name: \"Night Plum\",\n brand: \"oklch(0.45 0.14 330)\",\n neutral: \"cool\",\n description: \"Dark plum with a vivid edge.\",\n templates: [\"encore\"],\n },\n {\n id: \"charcoal-clay\",\n name: \"Charcoal & Clay\",\n brand: \"oklch(0.52 0.08 50)\",\n neutral: \"warm\",\n description: \"Fired clay against charcoal and bone.\",\n templates: [\"kiln\"],\n },\n {\n id: \"earth\",\n name: \"Earth & Sky\",\n brand: \"oklch(0.5 0.1 140)\",\n neutral: \"cool\",\n description: \"Grounded greens under an open sky.\",\n templates: [\"commons\"],\n },\n {\n id: \"dusty-rose\",\n name: \"Dusty Rose\",\n brand: \"oklch(0.68 0.07 10)\",\n neutral: \"warm\",\n description: \"Linen, ink and a muted rose.\",\n templates: [\"vow\"],\n },\n {\n id: \"lagoon\",\n name: \"Lagoon\",\n brand: \"oklch(0.58 0.1 195)\",\n neutral: \"cool\",\n description: \"Clear teal water; fresh and open.\",\n templates: [\"link\"],\n },\n {\n id: \"saffron\",\n name: \"Saffron\",\n brand: \"oklch(0.78 0.15 80)\",\n neutral: \"warm\",\n description: \"Golden saffron, warm and generous.\",\n templates: [\"link\"],\n },\n {\n id: \"ink-blue\",\n name: \"Ink Blue\",\n brand: \"oklch(0.35 0.08 265)\",\n neutral: \"cool\",\n description: \"Fountain-pen blue; serious and literate.\",\n templates: [\"field-notes\", \"ledger\"],\n },\n {\n id: \"lavender\",\n name: \"Lavender\",\n brand: \"oklch(0.7 0.1 300)\",\n neutral: \"cool\",\n description: \"Gentle lavender for soft, restful brands.\",\n },\n {\n id: \"forest\",\n name: \"Forest\",\n brand: \"oklch(0.4 0.07 150)\",\n neutral: \"warm\",\n description: \"Old-growth green, steady and natural.\",\n templates: [\"commons\"],\n },\n {\n id: \"coral\",\n name: \"Coral\",\n brand: \"oklch(0.7 0.15 25)\",\n neutral: \"warm\",\n description: \"Playful coral with sunny neutrals.\",\n templates: [\"link\"],\n },\n];\n\nexport function getCuratedPalette(id: string): CuratedPalette | undefined {\n return curatedPalettes.find((p) => p.id === id);\n}\n","export const name = \"@omniharmonic/openspace-theme\";\n\nexport * from \"./color\";\nexport * from \"./compile\";\nexport * from \"./contrast\";\nexport * from \"./custom-fonts\";\nexport * from \"./extract\";\nexport * from \"./layout\";\nexport * from \"./overrides\";\nexport * from \"./pairings\";\nexport * from \"./palettes\";\nexport * from \"./scales\";\nexport * from \"./themes\";\nexport * from \"./type-scale\";\nexport type * from \"./types\";\nexport * from \"./vars\";\n"],"mappings":"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","names":["c","COLOR_ROLES","COLOR_SCALE_STEPS","COLOR_THEMES","name","name","name","COLOR_THEMES","COLOR_THEMES","quoteFamily","COLOR_ROLES","COLOR_THEMES","COLOR_SCALE_STEPS","c","COLOR_SCALE_STEPS","c","COLOR_THEMES","record","COLOR_ROLES","COLOR_THEMES","COLOR_ROLES","COLOR_SCALE_STEPS","name","pairing","css","c","c"]}
package/package.json CHANGED
@@ -1,6 +1,49 @@
1
1
  {
2
2
  "name": "@omniharmonic/openspace-theme",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "OpenSpace design tokens: OKLCH palettes, contrast solver, type pairings and the Site Styles compiler.",
5
+ "license": "MIT",
6
+ "author": "The OpenSpace contributors",
7
+ "homepage": "https://github.com/omniharmonic/openspace#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/omniharmonic/openspace.git",
11
+ "directory": "packages/theme"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/omniharmonic/openspace/issues"
15
+ },
16
+ "engines": {
17
+ "node": ">=22"
18
+ },
19
+ "type": "module",
20
+ "sideEffects": false,
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ }
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^22.18.0",
37
+ "tsup": "^8.5.0",
38
+ "typescript": "~5.9.3",
39
+ "vitest": "^3.2.4"
40
+ },
41
+ "dependencies": {
42
+ "@omniharmonic/openspace-schema": "0.1.0"
43
+ },
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "typecheck": "tsc --noEmit",
47
+ "test": "vitest run"
48
+ }
6
49
  }