// The validators behind `defineTheme()`: each slot's override checked against its canonical list // and value grammar, then rendered as custom-property lines in that list's order — never the // caller's — so a brand rendered twice is byte-identical and its CSP hash does not churn. import { invalidBrandTokenError, unknownTokenError } from '../errors'; import { parseChannels } from '../tokens/contrast'; import { COLOR_ROLES, type ColorRole, type RadiusName, radiusTokens, SHADOW_NAMES, type ShadowName, } from '../tokens/tokens'; import { FONT_SLOTS, type FontSlot } from './preset-shape'; import { isShadowValue, SHADOW_EXPECTED } from './shadow-value'; /** `0` or a number with a CSS length unit. No `calc()`, no `var()` — a scale rung is a value. */ const LENGTH_PATTERN = /^(0|\d+(\.\d+)?(px|rem|em|ch|%))$/; /** * Family names, quotes and separators only: everything a `font-family` list legitimately needs. * The separator is a literal SPACE, never `\s`: the HTML parser rewrites a CR or CRLF inside a * `